Uh oh!
There was an error while loading. Please reload this page.
docs(qa): drive the FEEDS_DISABLED case records-forms only named — add the qa-feeds-disabled fixture and its two probes - #12382
Conversation
`FEEDS_DISABLED` appeared in records-forms.json exactly once — inside a `negative` bullet of record-discussion-mentions — with no step and no acceptance clause provoking it. Nothing in the area, or in stock showcase, supplied a feeds-disabled parent: feeds is opt-OUT (spec default true, object.zod.ts:290), so every showcase object has comments on and there is no incidentally-disabled object to borrow, unlike the files case. An auditor grepping the area saw the code and moved on. Added the area's first area-level `fixtures` block — recipe `qa-feeds-disabled`, landing a scratch `qa_nofeeds` object with an EXPLICIT `enable.feeds: false`, modelled on `qa-scratch-authz` (#7670) rather than invented — and opted record-discussion-mentions into it. Added three steps and acceptance clauses 6 and 7: the create-side probe (POST sys_comment onto qa_nofeeds -> 403 FEEDS_DISABLED, and zero rows land) and the re-thread probe (PATCH an existing comment's thread_id onto it -> 403, thread_id unchanged), each paired with a feeds-ENABLED control so the refusal is attributable to the capability gate rather than to the sibling RECORD_NOT_ACCESSIBLE refusal. Added `automated` naming the pre-existing engine/API pins — the #10170 describe in capability-gate-update-verb.test.ts and the cmt_nofeeds create probe in comments-permission-matrix.dogfood.test.ts — and stating what they do NOT reach (the console half, and the showcase surface), so the next auditor does not re-derive it. Revision bumped 1 -> 2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
yinlianghui
commented
Aug 25, 2026
ACCEPT (pending gate) — devx@objectstack seat (#6023), R9Reviewed against the diff and the dispatch's Zone 1/2. One file, +95/−5, docs-only. The correction is the most valuable thing here, and it is endorsedThe card reads as though
⭐ Not reporting That answers my Zone 2b (I asked whether the write is reachable at all, and said an unreachable one made this a pin-only job). It is reachable and driven elsewhere; the narrower gap is the true one. Zone 1 held
What earns it
⭐ And the honesty that matters most: you state plainly that the coupling proof welds fixture to probes and is not a runtime assertion against a live boot. A weaker report would have let "both legs red" read as end-to-end proof. Landing conditions
Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#12118
FEEDS_DISABLEDappeared indocs/qa/platform-checklist/areas/records-forms.jsonexactly once — inside anegativebullet ofrecords-forms.record-discussion-mentions— with no step and no acceptance clause provoking it. An auditor grepping the area saw the code and moved on. This drives it.Why the area could not simply borrow a parent
Feeds is opt-OUT (spec default
true,packages/spec/src/data/object.zod.ts:290), so every stock showcase object has comments on and there is no incidentally-disabled parent to borrow. This is the mirror image of the files case:enable.filesis opt-IN (defaultfalse), which is whyattachments-storagecould probeshowcase_accountbeforeqa_nofileswas purpose-built. Closing either half here genuinely needed a new fixture — which is why PR #12116 reported this side rather than widening.What landed
The area's first area-level
fixturesblock — recipeqa-feeds-disabled, landing a scratchqa_nofeedsobject with an explicitenable.feeds: false. Shape copied fromqa-scratch-authzinareas/attachments-storage.json(#7670) rather than invented, per the README's "copy its shape".sharingModelispublic_read_writeon purpose: the probes must be refused by the capability gate, so a caller who can read and edit the parent isolatesFEEDS_DISABLEDfrom the siblingRECORD_NOT_ACCESSIBLErefusal (comment-access-hooks.ts:132) — the same isolation discipline #12116 used againstATTACHMENT_PARENT_ACCESS.Two acceptance clauses the term only promised, plus three steps and a
provisioning.use:POST /api/v1/data/sys_commentwith aqa_nofeedsthread_id → 403FEEDS_DISABLED, and zero rows land (a 2xx silent no-op fails it too).PATCHan existing comment'sthread_idonto it → 403, and the storedthread_idis unchanged. This is the UPDATE half ofenforceFilesCapability/enforceFeedsCapabilityarebeforeInsert-only — a re-point via update dodges the capability opt-in on the NEW parent object #10170 (enforceFeedsCapabilityonbeforeUpdateas well asbeforeInsert,audit-writers.ts:1456-1457).Each is paired with a feeds-ENABLED control: a 403 that also fires on the enabled parent is measuring access, not the capability gate, and a new
negativebullet makes scoring from the 403 alone a FAIL.An
automatedblock naming the pins that already existed —capability-gate-update-verb.test.ts:341(#10170 by-id + predicate re-thread, the insert control at:206, the absent-thread_idboundary at:393) andcomments-permission-matrix.dogfood.test.ts:317(create side over real REST againstcmt_nofeeds) — and what they do not reach: they run against their own fixtures (cmt_nofeeds/lead_walled) and never touched the showcase surface or the console half of the negative. Recording that is the point; the next auditor should not have to re-derive it.Revision bumped 1 → 2 with a history entry.
Correcting the card's framing
The card reads as though the
FEEDS_DISABLEDwrite is never driven anywhere. Measured on7986d973fa, that is too strong, and the correction is recorded here so it does not get re-filed:records-forms.json(this area)negativebullet onlyplugin-auditengine tests (lead_walled)qa/dogfood(cmt_nofeeds)So the enforcement is well pinned and no user is exposed — the card says as much under "What is NOT wrong here". The real gap is narrower than the title suggests: this area named a refusal it never provoked, and had no fixture with which to. That gap was real and is what this PR closes.
A positive control keeps the zero honest: the same query shape run for
files:falsereturns fewer hits thanfeeds:false, so "no feeds-disabled parent in showcase/this area" is a measurement, not a failed search.Proof the fixture drives the probes
A checklist item is data, not an executable assertion, so the honest proof is the bidirectional coupling
check:platform-checklistenforces (#11506) — ablated in both directions ate1267d661b, each mutation confirmed on disk by grep counts anchored to the exact text removed, restored undertrap … EXIT INT TERM:usekept —recipe-definitions=0, use-references=1"fixtures.provisioning.use" names "qa-feeds-disabled" but this area file has no area-level "fixtures" block to resolve it againstusedeleted, recipe kept —recipe-definitions=1, use-references=0area-level recipe "qa-feeds-disabled" is referenced by no item — dead textgit hash-objectbyte-identical to the clean tree across all three checkpointsBoth legs turned red in the predicted direction. To be precise about what this does and does not prove: it welds the fixture and the probes together so neither can be deleted without the gate failing. It is not a runtime assertion against a live boot — clauses 6 and 7 are scored by a runner replaying the recipe, exactly as the files-side clause 5 is.
Gates
Union re-run at the final commit
e1267d661b(tree clean), exit codes captured before any pipe:node scripts/check-platform-checklist.mjs→ 0 —OK — 15 areas, 207 items … provisioning: 5 area recipes, 8 item references resolved (1 area-qualified), 5/5 recipes referenced(baseline was 4 recipes / 7 references)node scripts/checklist-select.mjs --self-test→ 0 (17 cases pass)pnpm check:doc-authoring(both legs) → 0 —390 files clean/48 published skill files cleanpnpm --filter @objectstack/lint run check:doc-formula-expressions(both legs) → 0 —50 cases passed;22 record-scoped formula example(s) across 422 files / 1449 TS blocks judged cleanpnpm check:nul-bytes(both legs) → 0 —scanned 6852 text file(s) … no raw ASCII control bytesGate set derived by
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackate1267d661b(2 matched families, both run above);check:nul-bytesandcheck:platform-checklistadded by inspection.Docs-only — no published output changes, so no changeset (
skip-changeset).Generated by Claude Code
Generated by Claude Code