Repository navigation
fix(service-storage,spec): the upload size refusal answers 413 PAYLOAD_TOO_LARGE - #22359
Conversation
…D_TOO_LARGE The ledger lists PAYLOAD_TOO_LARGE under @objectstack/service-storage beside @objectstack/rest, and the four upload doors stamp it in place of the status-derived VALIDATION_ERROR. Same status, message, doors and refusal; tests, README, docs and the pending storage note follow. Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…AD_TOO_LARGE notes @objectstack/rest answers the code on both import routes, not only the synchronous one; the ledger row, the storage docblock and the spec note now say so. Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 12 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 6 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 141 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 6800c545620cdd3e5da2df922c8b74c46cdeea83 && git checkout 6800c545620cdd3e5da2df922c8b74c46cdeea83
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 1cb0edb82dcc7fb67a5eec1157c23900e3915924 5b5b812ce958740650aced54d57219029adf90c3 && git checkout -B drift-repro 1cb0edb82dcc7fb67a5eec1157c23900e3915924 && git merge --no-ff 5b5b812ce958740650aced54d57219029adf90c3
node scripts/docs-audit/affected-docs.mjs --json 1cb0edb82dcc7fb67a5eec1157c23900e3915924
|
|
Generated by Claude Code |
Contract reviewServed-tier: Inputs: card #22314 (body and all four comments), PR #22359 (body, the 10-file list, the net diff against the merge base ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #22314
Clause-②: yes (widening: a new owner provenance row in the published error-code ledger)
The upload size refusal that PR #22311 added (card #22283) now answers
413with the registered codePAYLOAD_TOO_LARGEat all fourservice-storageupload doors, in place of the status-derivedVALIDATION_ERROR. The error-code ledger listsPAYLOAD_TOO_LARGEunder@objectstack/service-storage, beside@objectstack/rest. This is ruling B from thedomain:servicesseat in PR #22311's ACCEPT, carried on the card.It is not a new code. The status (
413), the message, the four doors, and what is stored or refused are all unchanged.What changed
packages/spec/src/api/error-code-ledger.zod.ts: one provenance row,'PAYLOAD_TOO_LARGE', under the@objectstack/service-storageowner key.PACKAGE_DELETE_PARTIALandWRITABLE_PACKAGE_REQUIREDunder@objectstack/runtime): a comment naming the wire path and the other emitter, then "Provenance, not identity".ErrorCode,RegisteredErrorCodeandREGISTERED_ERROR_CODESare unchanged, because the union dedupes.standardSynonymOfstays true, including "a phrase for a status the catalog does not name (PAYLOAD_TOO_LARGE, 413) is NOT a synonym".packages/services/service-storage/src/storage-routes.ts: the one constant changes fromUPLOAD_TOO_LARGE_CODE: StandardErrorCode = 'VALIDATION_ERROR'toUPLOAD_TOO_LARGE_CODE: RegisteredErrorCode = 'PAYLOAD_TOO_LARGE'. Its docblock is rewritten to state the new choice and the reason for it.PAYLOAD_TOO_LARGEand still assert bothcodeandstatusat every door.storage-limits.test.ts: the sharedexpectTooLargehelper asserts413+PAYLOAD_TOO_LARGE, and every door case calls it:content-length;content-length.error-envelope.conformance.test.ts: the case for the over-limit upload.packages/qa/dogfood/test/storage-upload-limits.dogfood.test.ts: three assertions over a real boot.service-storageREADME limits row;content/docs/api/error-catalog.mdx: theVALIDATION_ERROR413 callout moves to a newPAYLOAD_TOO_LARGEentry, the quick-reference 413 row changes, and the wire-code count goes from 51 to 52;content/docs/protocol/kernel/error-handling.mdx: the 413 row and theVALIDATION_ERRORentry..changeset/22314-storage-payload-too-large-provenance.mdis new:@objectstack/specminor, carrying the Clause-② line above..changeset/22283-storage-limits-honoured.mdgets a one-sentence correction (see the next section).Pending release note corrected: confirmation requested (
Check Changesetis red by design).changeset/22283-storage-limits-honoured.mdis #22283's pending, unreleased note (@objectstack/service-storageminor). This PR changes one sentence in it:413and the standard codeVALIDATION_ERROR, in the usual error envelope,"413and the registered codePAYLOAD_TOO_LARGE, in the usual error envelope,"Nothing else in that note changes. With this edit, the release that first ships the refusal names one code.
check-empty-changesetrefuses a changed foreign changeset by design. This PR is the DELIBERATE CORRECTION class: the gate's own remedy is to say so on the PR and have it confirmed. Do not restore the old sentence, which would put the false code back. Do not applyskip-changeset. Please confirm the correction here.The
service-storagecode change rides on that note. This PR's own changeset declares@objectstack/speconly. Nocheck-changeset*gate asked for@objectstack/service-storagein an added changeset:check-changeset-no-majorexits 0.check-adr-0087-registrationexits 0.Require a changesetcounts the added22314changeset.Release coupling, checked before building
@objectstack/service-storage:latestis17.7.0, published 2026-10-06T12:09Z.limitsSnapshotorUPLOAD_TOO_LARGE_CODE. The control,upload/presigned, matches in 4 dist files.main.So no published version ships the
VALIDATION_ERRORrefusal.Measurements (the dispatch's hypotheses)
PAYLOAD_TOO_LARGEwas listed under@objectstack/restonly, which answers it for both import routes' row ceilings (import-prepare.ts, 5,000 and 50,000 rows).HTTP_REASON_PHRASE_STATUSmaps it to 413.sendError(@objectstack/types) takesErrorCode=StandardErrorCode | RegisteredErrorCode.RegisteredErrorCodeis the typeservice-analyticsalready uses for ledger-code constants (read-scope-refusal.ts,dataset-refusal.ts).PAYLOAD_TOO_LARGE. Sweep hits outside the tests, with line numbers at the base41d0d4038::113,error-catalog.mdx:67and:920,error-handling.mdx:217,:405and:421, the dogfood test:68,:91and:102, and the pending changeset:15.storage-adapter-list.conformance.test.ts:436and:447(VALIDATION_ERRORfor the listlimit/cursor);import-mappings.mdx:224andimport-job-integration.test.ts:202(rest's import 413, alreadyPAYLOAD_TOO_LARGE);references/api/contract.mdxandreferences/api/error-code-ledger.mdx(generated union listings, which this change does not move);error-code-ledger.test.ts:87(the synonym pin, still true).objectuicheckout has no branch on this refusal's code.check:error-code-provenanceis the gate that makes the row required:41d0d4038: exit 0, with 334 stamp sites (315 listed, 19 waived).b5f9d332f: the storage constant switched and the ledger row removed. The removal went throughscripts/ablation-replace.mjs, which showed the anchor count go from 1 to 0 and the blob change, then restored the file to equalHEAD. Result: exit 1,@objectstack/service-storage stamps 'PAYLOAD_TOO_LARGE' (constdef) at packages/services/service-storage/src/storage-routes.ts:93 — not listed under its own owner key.5b5b812ce: exit 0, with 335 stamp sites (316 listed, 19 waived).pnpm --filter @objectstack/spec build,check:generatedreports all 15 generated artifacts up to date, andgit statusis clean.check:error-status-conformancenow reconcilesPAYLOAD_TOO_LARGE. Its scope line reads "4 ledger code(s) a doc page publishes a status for (INVALID_REQUEST, PAYLOAD_TOO_LARGE, UNIQUE_VIOLATION, VALIDATION_FAILED)", and the derived producer is413 storage-routes.ts:315.VALIDATION_ERRORkeeps no 413 producer and no 413 doc claim. Exit 0.Tests
At
5b5b812ce, each run under the shared verify lock:pnpm --filter @objectstack/service-storage exec vitest run --maxWorkers=2: 45 files and 749 tests passed.src/api/plus every spec test that reads the ledger) withvitest run --project local --maxWorkers=2: 59 files and 1724 tests passed.pnpm --filter @objectstack/service-storage run typecheck: exit 0.pnpm --filter @objectstack/spec run typecheck: exit 0.At
b5f9d332f. The only change from there to5b5b812ceis comment and changeset wording in three files (5 lines changed):pnpm --filter @objectstack/spec test: 626 files passed, with 18740 tests passed and 1 todo.storage-upload-limits.dogfood.test.ts: 1 file and 2 tests passed. Theservice-storagedist it loaded had 1PAYLOAD_TOO_LARGEmatch.'PAYLOAD_TOO_LARGE_ABLATED'throughablation-replace.mjs, andtsc --noEmitfailed withTS2820 ... Did you mean '"PAYLOAD_TOO_LARGE"'?. The file was then restored to equalHEAD, with an emptygit diff HEAD.Gates
At
5b5b812ce:dispatch-gates --commandsderived 115 commands. All 115 ran:node scripts/check-empty-changeset.mjs --base origin/mainexited 1, by design (the DELIBERATE CORRECTION above).--ranverdict:✓ dispatch-gates --ran: 115 derived famil(ies) accounted for — 115 run, 0 NOT-MEASURED.check:generated, plus the roster gatescheck:authz-resolverandcheck:filter-alias-parity. All exited 0.ESLint was narrowed to the touched files, with this proof:
eslint.config.mjslints**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}. The touched TypeScript files are the five listed in the next point. The.mdand.mdxfiles match nofilesglob.pnpm exec eslint --no-inline-config --format jsonover those 5 files at5b5b812cereported 5 files, 0 errors and 0 warnings.parserOptions.projectand no typed rules; the config says so at:327). The config's only file reads are two baselines this diff does not touch. So this diff cannot change the lint result of any untouched file.Acceptance notes
service-storageREADME, and the dogfood test. The H3 sweep named each one as describing this refusal, and each is edited only where it does.PAYLOAD_TOO_LARGEentry also names@objectstack/rest's import row ceilings. The entry catalogs the code, not one door.error-catalog-docs.test.ts.content/docs/references/**is unchanged and regenerates byte-identically.Generated by Claude Code