Skip to content

Assert every {connection_test_id} route enforces the ct:self scope - #71835

Open
potiuk wants to merge 1 commit into
apache:mainfrom
potiuk:ct-self-dual-test
Open

Assert every {connection_test_id} route enforces the ct:self scope#71835
potiuk wants to merge 1 commit into
apache:mainfrom
potiuk:ct-self-dual-test

Conversation

@potiuk

@potiuk potiuk commented Aug 19, 2026

Copy link
Copy Markdown
Member

What

Adds test_routes_with_connection_test_id_param_enforce_ct_self — the missing dual of the existing ct:self route-consistency test.

Why

The execution API has two scope-consistency tests for ti:self:

ti:self ct:self
routes with the scope have the path parameter test_ti_self_routes_have_task_instance_id_param test_ct_self_routes_have_connection_test_id_param
routes with the path parameter have the scope test_routes_with_task_instance_id_param_enforce_ti_self missing

ct:self only ever got the forward half, and the missing half is the one that matters.

The forward test iterates routes that already declare ct:self and checks each takes {connection_test_id}. A new route that takes {connection_test_id} and declares no scope at all is invisible to it — there is simply nothing to iterate. That is precisely how the ti:self gap on /task-reschedules/{task_instance_id}/start_date survived until its dual was added in #67628: the forward test was green the entire time.

So today ct:self sits in the same state ti:self was in before that fix.

Approach

Mirrors test_routes_with_task_instance_id_param_enforce_ti_self exactly, so the two stay easy to read side by side:

  • checks the served OpenAPI spec for every API version, since the execution API assembles routes per version — a per-version regression would otherwise slip through;
  • allows deliberate exemptions via CT_ID_ROUTES_WITHOUT_CT_SELF (empty today) so an intentional exception is a visible, justified edit rather than a silently missing scope;
  • asserts the check is non-vacuous, so it cannot pass by matching nothing if the path parameter is ever renamed.

Production impact

None. connection_tests.py already carries ct:self; this is purely preventative.

Verification

Negative control — removed ct:self from the connection_tests router and re-ran:

FAILED  test_routes_with_connection_test_id_param_enforce_ct_self
PASSED  test_ct_self_routes_have_connection_test_id_param

The new test catches it; the pre-existing forward test stays green, which is the gap this closes. Scope restored, full file green (27 passed).

🤖 Generated with Claude Code

The execution API has two scope-consistency tests for ti:self — a forward one
(routes with the scope have the path parameter) and a dual (routes with the
path parameter have the scope). ct:self only ever got the forward half.

That leaves the gap open in the direction that matters. The forward test walks
routes that already declare ct:self and checks they take {connection_test_id};
a new route that takes {connection_test_id} and declares no scope at all is
invisible to it, because there is nothing to iterate over. Which is exactly how
the ti:self gap on /task-reschedules/{task_instance_id}/start_date survived
until its dual test was added.

Add the missing dual, mirroring test_routes_with_task_instance_id_param_-
enforce_ti_self: check the served OpenAPI spec for every API version, allow
deliberate exemptions through CT_ID_ROUTES_WITHOUT_CT_SELF (empty today), and
assert the check is non-vacuous so it cannot silently pass by matching nothing.

No production change — connection_tests.py already carries ct:self, so this is
preventative. Verified by negative control: removing the scope from the router
fails the new test while the pre-existing forward test still passes.
@boring-cyborg boring-cyborg Bot added the area:API Airflow's REST/HTTP API label Aug 19, 2026
@potiuk
potiuk requested a review from ephraimbuddy August 19, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:API Airflow's REST/HTTP API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant