Skip to content

Commit d1ea236

Browse files
docs(qa): attachments-storage checklist — apply the 18.2.0 sweep's 18 ledger findings (#25839) (#26124)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi992ENsi4QDy53qYTKqkVjaX)_ Fixes #25839 Clause-②: no Metadata-protocol: none Part of the 18.2.0 release sweep, wave anchor #25807. This applies all 18 checklist-accuracy findings that Tier 1 record #25815 (`release-18.2.0-tier1`, at `6679644a`) logged against `docs/qa/platform-checklist/areas/attachments-storage.json`. Only checklist text changes. 10 items each take one `revision` bump and one `history` row. Each row cites #25815 and the finding. There is no product code, test, pin, `RUNNER.md` or changeset change. `attachments-storage.field-accept-maxsize-server-enforced` is untouched. - Base `f6c61932`. The file has had no commit on `main` since the card was filed (last change `0f1eeeee`, 2026-10-22). Every pin named below was re-read on `main`. None of the read paths changed between `9753d163` and `f6c61932`. - A scripted span editor made every edit and never re-serialises the file. It re-parses the result and asserts three things: the new document equals the old one with the declared ops applied; each changed item has revision +1 and exactly one appended row; and the 1 item it did not touch is byte-identical. - All 18 lines were stale text. None describes a product defect, so no card is owed. ## How RUNNER rule 6 was applied A pin scores only the layer it drives. Each edit names the layer from the pin's own harness: route-handler unit (a registered `RouteHandler` with a hand-built request and response, or a mock HTTP server), engine (ObjectQL in-process), or HTTP (a booted stack). Where a pin stops above a clause's oracle layer, the item now says the pin scores that clause `partial` and names the leg to drive by hand. Where a ref claimed a whole item, it is scoped per clause. ## Changes | finding (#25815) | item | field | what changed | pin read (layer) | |:--|:--|:--|:--|:--| | a2 uploader leg not driven; n1 no re-read after a refused attach | `attach-requires-parent-edit` | `automated.ref` | clause 2 narrowed to the three delete answers pinned. The uploader-without-parent-edit leg and negative[1] for attaches are named as hand-driven | permission matrix: uploaders are the admin and memberA on public_read_write `att_case`. Cases (b), (item 3) and (#2727) never re-read `sys_attachment` (HTTP) | | a1 literal `[1]` vs pin `[0]` | `chunked-upload-integrity` | `acceptance[1].verify` | the literal belongs to steps[0]'s fixture. A pin-scored verdict records the pin's `[0]` | `storage-chunked-resume-integrity.dogfood.test.ts` 'REFUSED: …' withholds chunk 0 of two (HTTP) | | a2 owner case is a parent reader; url not followed | `download-authz-both-sides` | `automated.ref` | clause 2 scoped to the envelope. The uploader-bypass and bytes legs are named as hand-driven | permission matrix '(e-read)' (HTTP) | | a2 upload requests not captured | `inline-grid-receipt-cells` | `acceptance[2].verify` | says the pin asserts only the chip | `grid-file-upload.spec.ts` (browser, live backend) | | a3 no sys_file read, no batch success | `inline-grid-receipt-cells` | `acceptance[3].verify` | names both legs as hand-driven (steps[7]) | same spec | | n1 a `data:` URL passes the string checks | `inline-grid-receipt-cells` | `negative[1]` | a pin-scored verdict rests on the follow-up storage GET leg | same spec | | a1 sweep in-process; failed byte delete unit-only | `orphan-tombstone-reap` | `acceptance[1].verify` | names the layers. The failed-delete leg scores partial unless staged | permission matrix lifecycle block (`lifecycle.sweep()` in-process); `attachment-lifecycle.test.ts` (fake engine, mock logger) | | bare ref | `presigned-upload-roundtrip` | `automated.ref` | scoped to acceptance[0]'s committed owner_id, acceptance[2]'s envelope and acceptance[4]'s 401. The rest is named as hand-driven | permission matrix; the `uploadFile` helper asserts statuses only (HTTP) | | a4 no sys_file count | `presigned-upload-roundtrip` | `automated.ref` | the no-row half is named as hand-driven | '(e) anonymous presigned upload' (HTTP) | | a3 probe half and warning text at unit | `read-inherits-parent-rls` | `acceptance[3].verify` | names both pins' layers. The warning is asserted by fragment at unit only | `attachment-read-leaf.integration.test.ts` (engine + SQL driver, silent logger); `attachment-read-leaf.test.ts` (stand-in engine, recording logger) | | a2 live-holder half unit; live legs unpinned | `sys-file-status-pipeline` | `acceptance[2].verify`, `automated.ref` | unit half scores partial. The holder-less 404 and post-re-attach 200 go to steps[6]/[7]. The ref says acceptance[2] where it said 'clause 3' | `tombstone-download-live-reference.test.ts` (mock HTTP server, fake engine) | | a1 pending 404 has no HTTP pin | `sys-file-status-pipeline` | `acceptance[1].verify` | the unit case never scores the api clause; drive steps[1] | same file, 'leaves `pending` refused' | | a1–a3 handler-level; restart at kernel | `upload-limits-scope-and-ownership` | `automated.ref` | each pin's layer named. acceptance[1]–[3] score partial and are hand-driven | `storage-limits`, `upload-scope-vocabulary`, `upload-door-ownership` (route-handler unit; the settings save inside one `ObjectKernel`) | | a5 hydrate pins engine-level | `upload-limits-scope-and-ownership` | `automated.ref` | acceptance[5] is hand-driven (steps[4]) | both `engine-file-hydrate-*` (engine) | | a2/a3/n0/n1 unit pins not in ref | `upload-session-abort` | `automated.ref` | adds the `createUploadSessionReapGuard` block, per clause | `attachment-lifecycle.test.ts` (unit, stub adapters; the veto case asserts a warn call, not its text) | | a5 410 unit pin not in ref | `upload-session-abort` | `automated.ref` | adds the 'terminal upload-session statuses (#7667)' cases, scored at their layer only | `storage-routes.test.ts` (route-handler unit) | | bare ref scores a1 alone | `upload-session-abort` | `automated.ref` | the matrix file is scoped to acceptance[1] | permission matrix '(item 4 + multipart-abort guard)' | The first row carries two card lines (a2 and n1), so 17 rows cover all 18 card lines, and every one is applied. ## Retired objectui pin wording #26035 left the retired pin wording in the area JSON to these cards. This file has no hits for `objectui:(build|refresh|bump|clean)`, `build-console.sh`, `.objectui-sha` or `objectuiPin`, either before or after this change. Pin-era statements in two items this PR edits are corrected. - `download-authz-both-sides`: the ref said "a console bundle this repo does not build". It now says the console is built from `ui/` by `pnpm console:build` into the gitignored `packages/console/dist`. `source[3]`'s `objectui packages/app-shell/...` path now reads `ui/packages/app-shell/src/views/RecordAttachmentsPanel.tsx`. - `inline-grid-receipt-cells`: `knownGaps[0]` said "AUTOMATION IS PINNED IN THE objectui REPO, NOT HERE", with the spec runnable only "in an objectui checkout". Since the objectui import, the spec is `ui/e2e/live/grid-file-upload.spec.ts` in this tree. `automated.ref` and `source[1]` now name that path. `knownGaps[0]` now says how to run it from `ui/` (`pnpm test:e2e:live`, with a backend on port 3000 and the console dev server on port 5180), and it keeps the rule that an unrun pin is a claim, not evidence. This change rides on the item's one revision bump, and its history row says so. Earlier history rows are records and are left as written. ## Acceptance notes - `RUNNER.md`'s standing fact on objectui-pinned automation ("Some items carry an `automated.ref` that lives ENTIRELY in the `objectui` repo") still says this repository holds none of those specs and builds no console bundle. Both are stale since the objectui import. By that entry's own rule, `inline-grid-receipt-cells` has now left the set, because its ref names a path that exists here. `RUNNER.md` is outside this card's file surface. #26101 kept its own items' objectui-only framing in step with that entry, so the two cards now differ on this point. Carrier: the devx seat (#25850 / #26035). ## Gates (head `75c55dcc`) - `pnpm check:platform-checklist` exits 0: `16 areas, 329 items (324 active, 1 planned)`. - `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derives 13 families, and all 13 were run. Each exited 0. `check:doc-formula-expressions` first exited 3 on an unbuilt prerequisite, which measured nothing. After `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` under the verify lock, it exited 0. `--ran` reconciliation: 13 derived, 13 run, 0 NOT-MEASURED (a derived zero: every row records an exit code). - `skip-changeset`: the only change is under `docs/qa/`, which no package publishes. --- _Generated by [Claude Code](https://claude.ai/code/session_01VZNpUpuT1YtHY5bfFn3xN8)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 40bba68 commit d1ea236

1 file changed

Lines changed: 91 additions & 31 deletions

File tree

0 commit comments

Comments
 (0)