henry3260 opened a new pull request, #75213:
URL: https://github.com/apache/airflow/pull/75213

   ## Why
   
   The pending partitioned Dag run detail response (`GET 
/ui/partitioned_dag_runs/{dag_id}/pending`)
   carries two asset-bearing fields. `asset_expression` is scoped to the assets 
the caller may read;
   the sibling `assets` array was not. The query that builds it
   (`routes/ui/partitioned_dag_runs.py`) filters on nothing but 
`DagScheduleAssetReference.dag_id`,
   so every asset the Dag schedules on comes back with its full name and uri.
   
   That makes one payload contradict itself — it can blank an asset inside the 
boolean tree while
   spelling its name and uri out one key over:
   
   ```json
   {
     "assets": [{"asset_id": 7, "asset_name": "sales_daily", "asset_uri": 
"s3://bucket/sales"}],
     "asset_expression": {"asset": {"group": "asset", "hidden": true, "id": 
null, "name": null, "uri": null}}
   }
   ```
   
   The route's own asset dependency does not close the gap: 
`requires_access_asset(method="GET")`
   reads `asset_id` from the path (`core_api/security.py`), and this route has 
none, so it asks the
   coarse "may you read assets at all" question rather than "may you read asset 
#7".
   
   Reachability is the same as for the expression redaction: with FAB or 
SimpleAuthManager every
   asset id is authorized, so nothing changes in a stock deployment. The gap is 
reachable by a
   third-party auth manager that implements per-asset 
`filter_authorized_assets`.
   
   ## What
   
   Backend — `airflow-core/src/airflow/api_fastapi/core_api/`:
   
   - `datamodels/ui/partitioned_dag_runs.py`: 
`PartitionedDagRunAssetResponse.asset_id`, `.asset_name`
     and `.asset_uri` become nullable and a `hidden` flag is added, mirroring 
the shape
     `redact_asset_expression` already produces for the sibling field.
   - `routes/ui/partitioned_dag_runs.py`: blanks those three fields and sets 
`hidden` for an asset
     outside `ReadableAssetsFilterDep`. The redaction lands on the response 
only — the row is still
     read in full, because the rollup mapper is keyed by the asset's real name 
and uri and the
     received-key lookup by its real id. `readable_asset_ids` is hoisted so the 
`assets` loop and the
     `asset_expression` call share it; no extra query.
   
   Deliberately kept: `received_count`, `required_count`, `received_keys` and 
`required_keys` of a
   blanked asset. They describe the Dag's own schedule, which a caller who 
reached this endpoint can
   already read, and dropping them would leave a stuck run with no explanation 
at all. The run's
   `total_required` / `total_received` therefore stay accurate.
   
   Frontend — `airflow-core/src/airflow/ui/`:
   
   - `src/components/AssetProgressCell.tsx` renders a lock icon and a muted 
"Hidden asset" label in
     place of the asset link for a hidden asset, and drops hidden assets from 
the `events` list it
     feeds `AssetExpression` (a blanked asset has no id to match an expression 
leaf on, and the leaf
     it would have matched is redacted to `id: null` anyway).
   - `public/i18n/locales/en/common.json`: adds `expression.hiddenAsset`.
   
   Generated: `openapi/_private_ui.yaml` and the two 
`ui/openapi-gen/requests/*.gen.ts` files were
   regenerated. This endpoint is UI-only — `v2-rest-api-generated.yaml` 
regenerates byte-identical and
   no airflow-ctl model references the response — so no public REST API surface 
changes.
   
   Tests:
   
   - `tests/unit/api_fastapi/core_api/routes/ui/test_partitioned_dag_runs.py`: 
the existing
     
`TestGetPendingPartitionedDagRun::test_hides_assets_the_caller_may_not_read` 
now also asserts the
     `assets` array is blanked and that `total_required` still counts the 
hidden asset. Its comment
     disclaiming the `assets` array is removed. No query-count change.
   - `src/components/AssetProgressCell.test.tsx`: a new test opens the popover 
and asserts the hidden
     asset renders a label while the readable one stays a link, with exactly 
one link in the tree.
   
   Verified locally: the module's 51 backend tests pass; the full UI suite 
passes (1981 tests);
   `prek --stage pre-commit` and `--stage manual` pass. Both new assertions 
fail when the source
   change is reverted.
   
   Notes for reviewers:
   
   - This builds on #75180, which added `ReadableAssetsFilterDep` to this route 
for the sibling
     `asset_expression` field, and shares the `expression.hiddenAsset` i18n key 
with #75178. Please
     review those first; this branch rebases cleanly onto `main` once they land.
   - No newsfragment: `/ui/` endpoints are served to the bundled UI rather than 
to API clients, and
     the public v2 spec is unchanged. Happy to add one if you read it 
differently.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5)
   
   Generated-by: Claude Code (Opus 5) following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to