Skip to content

fix(artifacts): reject missing prerelease version fallback - #7528

Draft
bokelley wants to merge 1 commit into
mainfrom
conductor/reject-prerelease-artifact-fallback
Draft

bokelley wants to merge 1 commit into
mainfrom
conductor/reject-prerelease-artifact-fallback

Conversation

@bokelley

@bokelley bokelley commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

An absent explicit prerelease such as /schemas/3.2.0-rc.4/index.json can currently serve rc.3 bytes, and its directory routes can redirect to rc.3. This change makes Worker and Fly schema/compliance routing return a generic 404 with Cache-Control: no-store before an absent prerelease can reach a redirect, edge cache, compatibility rewrite, or fallback origin.

Exact published prefixes retain immutable caching and their complete identity, including build metadata and Fly's accepted leading v. Missing files under exact prerelease/compliance prefixes also terminate locally, so an older origin or downstream handler cannot substitute content. Discovery still lists stored versions only. Protocol routing, parsing, tarball and sidecar cache policies are unchanged.

Stable docs-gap fallback remains supported for schemas: highest selectable stable version at or below the request, preferring the same minor and then the same major. scripts/rewrite-dist-links.sh creates these schema pins; it does not create compliance pins. Compliance version pins now require an exact version. This bounds the compatibility behavior introduced in #5690/#5691 to its demonstrated consumer contract. With version listings available, resolved stable-schema docs-gap directory redirects and cache policy agree between Worker and Fly. Stable-schema listing outages remain operationally asymmetric: the Worker fails closed, while Fly may serve an exact local file or fall through without rewriting. This PR does not claim broad response-code parity outside exact-only paths. This residual does not permit prerelease fallback or wrong-version substitution.

Related to #7404; this does not close the broader hosted-grader incident.

Incident scope and sequencing

The verified 2026-09-14 candidate inventory spans 2,101 paths: 1,612 schema + 485 compliance + 4 protocol. Existing schema/compliance paths returned exact rc.3 bytes when the rc.4 prefix was absent; bare/trailing version routes redirected to rc.3. Discovery omitted rc.4, and the four candidate-only compliance paths plus protocol artifact paths already returned 404. The inventory is the observed blast radius being audited, not evidence of 2,101 incorrect stored objects. No rc.4 tag or GitHub Release existed in the supplied incident evidence.

This is routing containment, not artifact recovery. No migration, generated/released artifact, dependency, R2/CDN state, tag, release, or deployment changes are included or performed. #7510 remains the publication-fence predecessor for #7509/#7507; this PR does not satisfy or bypass that fence.

Validation

  • Worker suite: npm run test:cdn-artifacts-worker — 33 passed, including origin/edge-cache traps and stale version-listing file misses.
  • Server integration: npx vitest run --config server/vitest.config.ts server/tests/integration/schema-routing.test.ts server/tests/integration/schema-versioning.test.ts — 120 passed. Both real handlers run against shared temporary fixtures covering GET/HEAD, exact/missing prereleases, file/bare/trailing/index/nested forms, candidate-only files, discovery, headers, stable bounds, malformed versions, build metadata, listing failures, and protocol regression behavior.
  • Red-before-green: new Worker guard reproduced 301 instead of 404; shared parity tests reproduced 30 failures before the fix.
  • npm run typecheck (including fixed-trace rollout checks), Worker/test Node syntax checks, git diff --check, image hook, conventional PR title, and changeset scope checks passed. No protocol changeset is required.
  • Fresh direct-main rebase gates passed on 7d494c9977507185eb361995d9fe2024dee1df7f: .husky/pre-commit ran 71 root unit files / 1,063 tests, all static guards and both typecheck stages. The full server suite ran explicitly because the staged-file selector skips a clean rebased checkout: 617 files / 9,476 passed / 31 skipped. The fix(auth): allow trailing slashes on MCP CSRF exemptions #7533 and adjacent CSRF/MCP authorization selection passed 3 files / 83 tests. Registration/scope/immutable regression checks 3/3, docs navigation 55/55, schema links, version sync, and scope/immutable/whitespace checks passed. The normal pre-push hook remained enabled.
  • Exact-head CI for 7d494c9977507185eb361995d9fe2024dee1df7f: terminal CLEAR, verified 2026-09-15 05:18 UTC — 28 successful check runs + successful IPR status (29 successful contexts), one expected Draft review skip, zero pending/fail. All seven workflows passed on attempt 1; no retry was needed for this head. Previous-head CI and superseded local composition results are not reused.
  • Historical terminal CI for previous head 8686c63bfcaa05ced45f6f2a9219ec6bd22b507c: 28 successful check runs + successful IPR status (29 successful contexts), one expected Draft review skip, zero pending/fail. The two attempts below belong only to that previous head.
  • Historical Attempt 1 is retained explicitly: the only failing test was capability discovery in server/tests/integration/external-smoke-check.test.ts, which timed out at its unchanged, fixed 30,000 ms deadline (30,005 ms observed). The exact test blob, configuration, imports, and dependency graph matched base 2da35544ffb7257861324786a33cae9db0457bac; all four changed routing/test files were outside that direct graph. Its next discovery call and the same test on base passed.
  • Historical Attempt 2 was one failed-job retry, passing 41 files / 503 tests, including discovery in 783 ms, on exact unchanged head 8686c63bfcaa05ced45f6f2a9219ec6bd22b507c with the same timeout. This was external latency resampling; no stabilization or source fix is claimed. Both attempts and the independent diagnosis remain preserved; no additional retry or source adjustment was made.
  • Independent isolated direct-main rebase code/security review: CLEAR, no unresolved findings. It reproduced all four result blobs, both diff hashes and stable patch ID; confirmed the sole parent is current main, zero overlap with fix(auth): allow trailing slashes on MCP CSRF exemptions #7533, exact carryforward of its three CSRF/MCP paths, unchanged artifacts, and no fix(release): fence publication and recover superseded releases #7510 ancestry or delta. Prerelease redirect/cache/origin/downstream containment and the stable-schema listing-outage qualification remain unchanged.

Review hold and exact revision

Draft; auto-merge off; unmerged. The existing maintainers human-review team request was renewed after terminal exact-head green at 2026-09-15T05:18:11Z; the native renewal event was verified. Human review remains requested; no readiness or merge change was made.

  • Base: main at cdcc8f996e8acd2417d5f7a547711cd21929289b (verified against GitHub).
  • Head: 7d494c9977507185eb361995d9fe2024dee1df7f.
  • Tree: 7295192ee535743f133d1f35a0d625b50107a64e.
  • Pure rebase from old head 8686c63bfcaa05ced45f6f2a9219ec6bd22b507c / old base 2da35544ffb7257861324786a33cae9db0457bac, directly onto current main. Publication uses an explicit force-with-lease requiring that exact old remote head. fix(release): fence publication and recover superseded releases #7510 terminal qualification is a release-lane ordering gate, not this PR's ancestry; this PR remains independent and main-based.
  • Scope: the same four routing/test files, +461 / -59; all four result blobs are identical. fix(auth): allow trailing slashes on MCP CSRF exemptions #7533's three-path main advance has zero overlap and carries forward unchanged.
  • Prior coordinator final audit: CLEAR for old head e480ed82f6ed036686d9f9335493dbbef013f176, old base 336546b0dc2b1af9f12b955bddcfd74e002a23f9, and old tree 74d73a58cf175a3879028f426da994759dd5d9b4. The fresh isolated review covers the rebased revision above.
  • Binary diff SHA-256: 750fd8f1153f3db15e3703502d6dc5742b43739a88b4f015a26279aa8cb90b83 (git diff --binary --abbrev=10 <base> <head>), unchanged.
  • Full-index binary diff SHA-256: 70c12dc5cf75bdf6f5ef74d1cdaa751beab3475c5a6d2d411cae86c3d5cfc742, unchanged.
  • Stable patch ID: 073b17211ae461d72384bae84b1ae9265f315426, unchanged.

Open workspace in Conductor

Draft disposition — 2026-10-09

This draft is retained for the stated workstream. Continue on this existing branch; no parallel PR is needed. This disposition does not waive CI, review, migration, or release gates.

@bokelley
bokelley requested a review from a team September 14, 2026 22:03
@bokelley
bokelley force-pushed the conductor/reject-prerelease-artifact-fallback branch 2 times, most recently from 8686c63 to 7d494c9 Compare September 15, 2026 05:07
@bokelley
bokelley requested review from a team and removed request for a team September 15, 2026 05:18

Copy link
Copy Markdown
Contributor Author

Refreshed the unchanged four-file containment patch onto current main at b9ba4ebc0d4ec0f97afbf8d3e38538649ec1375e; new exact head: 044a28816118e171d8e6e8551333f3f0d55263d9. The sole conflict was additive test placement beside main's newer JSONL coverage, and both blocks are preserved. Focused validation on the composed tree: artifact CDN Worker 38/38, schema routing/versioning 120/120, and full typecheck passed. The PR remains draft and retains its human-review hold while exact-head CI reruns; older base/head identities in the description are historical.

This branch has not been deployed

No deployments
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