Skip to content

feat(gate): runtime route-presence via the live OpenAPI spec (P1) - #207

Merged
agjs merged 1 commit into
mainfrom
fix/reachability-http-sentinel
Jul 27, 2026
Merged

feat(gate): runtime route-presence via the live OpenAPI spec (P1)#207
agjs merged 1 commit into
mainfrom
fix/reachability-http-sentinel

Conversation

@agjs

@agjs agjs commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Observable-gates plan, P1 (3rd in the false-green-hardening series after #205/#206).

The reachability stage's API-registration check was source-substring — 'does the resource name appear in routes.ts' — a proxy #202 proved false-greens (a route that merely looks mounted). New openapi-routes.ts queries the running API's public OpenAPI spec (/swagger/json — no auth; the same spec generate:api consumes every cycle) and asserts the feature's CRUD paths (/api/v1/<entity>/ + /{id}) are actually served. A route present in source but absent from the live spec = the resource isn't mounted → 404 at runtime. Observable end-state, not source.

  • Augments (doesn't replace) the static check in reachabilityStage.
  • Inconclusive is non-blocking (spec unreachable/not-a-spec/non-2xx) — the build-start pre-flight already fail-closes a down API; a transient blip must not red a feature. Only a reachable spec that omits the routes reds.
  • Injectable SpecFetcher → deterministic unit tests, no server; default fetch aborts after 10s. Path convention verified against the live spec.
  • Scope note: the authenticated create→row-appears sentinel round-trip stays with the browser-based acceptance (P2) — replicating Elysia's refresh-token auth in a bare fetch is fragile and would risk gate flakiness (the panel's explicit caution). This P1 is the no-auth runtime observable.

Proven: 7 openapi-routes unit tests + 2 reachabilityStage wiring tests (routes absent → not reachable; present → reachable) + live integration vs valbuild27's running API (mounted bookmark passes; never-built widget reds, 62 real paths). Full suite 3158/0; typecheck + lint clean. Additive/gate-preserving.

Observable-gates plan P1. The reachability stage's API check was source-substring —
'does the resource name appear in routes.ts' — a proxy #202 proved false-greens (a
route that merely LOOKS mounted). New openapi-routes.ts queries the RUNNING API's
public OpenAPI spec (/swagger/json — no auth, the same spec generate:api consumes
every cycle) and asserts the feature's CRUD paths (/api/v1/<entity>/ and /{id}) are
ACTUALLY served. A route present in source but absent from the live spec means the
resource isn't mounted → its create/list/edit/delete 404 at runtime. Observable
end-state, not the source's story.

- Wired into reachabilityStage (augments, doesn't replace, the static check): static
  problems + runtime route-presence combine into one reachability error.
- INCONCLUSIVE (spec unreachable / not a spec / non-2xx) is NON-BLOCKING — the
  build-start pre-flight already fail-closes a genuinely down API, and a transient
  mid-loop blip must not red a feature. Only a reachable spec that OMITS the routes reds.
- Injectable fetcher (SpecFetcher) keeps it deterministically unit-testable with no
  server; the default fetch aborts after 10s.
- Path convention verified against the live spec (/api/v1/<key>/ + /{id}).

NOTE: the authenticated create→row-appears sentinel round-trip stays with the
browser-based acceptance (P2) — replicating Elysia's refresh-token auth in a bare
fetch is fragile and would risk gate flakiness (the panel's explicit caution).

Proven: 7 openapi-routes unit tests (pure matcher + fetcher inconclusive/garbage) + 2
reachabilityStage wiring tests (routes absent → not reachable, present → reachable) +
LIVE integration vs valbuild27's running API (mounted bookmark passes, never-built
widget reds). Full suite 3158/0. Additive/gate-preserving.
@agjs
agjs merged commit 3fe37cb into main Jul 27, 2026
8 checks passed
@agjs
agjs deleted the fix/reachability-http-sentinel branch July 27, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant