Context
Umbrella / architectural. Successive fixes (#347, #354, #358/#359, and the route/method follow-ups) have grown scan_endpoint_metadata into a special-case state machine: _reconcile_all_methods_expansion, explode_canonical, find_by_function_id, endpoint_key fallback, and short-name fallback all interact. Each new binding shape has required another branch.
Proposed invariant model to collapse the special cases:
- Azure
@app.route binding is the source of truth for route + method.
@openapi / endpoint / validation metadata is enrichment only (schema, description, params) — never routing truth (except explicit @openapi(route=/method=) as deliberate override).
- Registry operation identity =
method::path (not function_id).
function_id = source handler identity, one-to-many allowed.
- Scan flow: resolve binding → concrete operations FIRST, then merge each metadata source into the exact matching operation.
This makes route/method loss and method collapse structurally impossible rather than patched per-case, and subsumes the one-to-many function_id issue.
Acceptance Checklist
Out of scope
- Point fixes shipped in the preceding P0/P1 issues (this refactor lands after them, in a minor release).
References
Context
Umbrella / architectural. Successive fixes (#347, #354, #358/#359, and the route/method follow-ups) have grown
scan_endpoint_metadatainto a special-case state machine:_reconcile_all_methods_expansion,explode_canonical,find_by_function_id,endpoint_keyfallback, and short-name fallback all interact. Each new binding shape has required another branch.Proposed invariant model to collapse the special cases:
@app.routebinding is the source of truth for route + method.@openapi/ endpoint / validation metadata is enrichment only (schema, description, params) — never routing truth (except explicit@openapi(route=/method=)as deliberate override).method::path(notfunction_id).function_id= source handler identity, one-to-many allowed.This makes route/method loss and method collapse structurally impossible rather than patched per-case, and subsumes the one-to-many
function_idissue.Acceptance Checklist
scan_endpoint_metadatato binding-first operation resolution.make check-allgreen; coverage >= 95%.Out of scope
References
src/azure_functions_openapi/bridge.py::scan_endpoint_metadata.