Skip to content

docs(qa): re-quote enable.files citation, add update-verb FILES_DISABLED probe - #12116

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-10735-attachments-update-verb-probe
Aug 25, 2026
Merged

docs(qa): re-quote enable.files citation, add update-verb FILES_DISABLED probe#12116
yinlianghui merged 1 commit into
mainfrom
claude/issue-10735-attachments-update-verb-probe

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#10735

What changed

docs/qa/platform-checklist/areas/attachments-storage.json:

  1. Re-quoted the step-4 fixture citation (fixtures.qa-scratch-authz.sequence[3].source) against the live enable.files describe string at packages/spec/src/data/object.zod.ts:281. The old citation ended at "otherwise creation is rejected" — the pre-enforceFilesCapability / enforceFeedsCapability are beforeInsert-only — a re-point via update dodges the capability opt-in on the NEW parent object #10170 wording PR docs(spec): re-derive two stale contract statements in object.zod.ts against the behaviour that landed (#10526, #10336) #10733 rewrote post-[finding] enable.files / enable.feeds describe strings say "creation is rejected" — the gates now refuse a re-point via update too #10336. The live string now reads "otherwise any write that makes an attachment target it is rejected (403 FILES_DISABLED) — a create and an update that re-points an existing attachment alike", which names the exact case the checklist was not probing.

  2. Added the update-verb probe to attachments-storage.attach-requires-parent-edit (revision 4 → 5): a new step + acceptance clause 5 that re-points an existing sys_attachment's parent_object onto the qa_nofiles fixture (already provisioned by the area's qa-scratch-authz recipe, Land the attachments-storage QA scratch fixture (qa_vault/qa_shared/qa_nofiles + two personas) as permanent #7670 — one throwaway record inserted into it, no new fixture) and expects 403 FILES_DISABLED. #10170 registered the enforceFilesCapability gate (packages/plugins/plugin-audit/src/audit-writers.ts:1483-1503) on beforeUpdate as well as beforeInsert, because the flag gates the target object, not the verb — a create-only probe (clause 4) keeps passing while this half regresses. The new step runs as admin (who can edit both the original and target parents) to isolate the refusal from ATTACHMENT_PARENT_ACCESS. knownGaps/negative/source/automated updated to match, citing the engine-level #10170 pin (packages/plugins/plugin-audit/src/capability-gate-update-verb.test.ts) that grounds the isolation claim.

Investigation: the parent_object hits triage flagged

Triage's premise re-verification measured 3 hits for parent_object in the area file and flagged them for inspection (one could already be an update in disguise). Re-measured case-sensitively there are only 2 literal parent_object hits; the third is case-insensitive-only (parent_OBJECT, inside prose describing an unreachable fail-closed branch in read-inherits-parent-rls's automated field — not a probe at all). All three sites are: a scoped list (read, not a probe of the write gate), a create (POST), and that unreachable-branch prose. None is an update-verb probe in disguise — the gap triage flagged is real and unnarrowed.

Feeds side (records-forms.json) — investigated, not built

Per triage's clause ("include the feeds-side look... if it needs new fixtures, report rather than widen"):

  • FEEDS_DISABLED appears in records-forms.record-discussion-mentions, but only inside a negative entry — there is no step or acceptance clause that actually drives a feeds-disabled write, on either the create or update side.
  • No fixture provides a feeds-disabled parent: records-forms.json has no area-level fixtures block, no stock showcase object declares enable.feeds: false (feeds defaults to true, opt-out), and there is no scratch-object recipe analogous to qa_nofiles for this area.
  • So closing either half (create or the thread_id re-thread) needs a new feeds-disabled fixture the area does not currently land. Per triage's clause, this PR does not widen to add one — reported here and in the final report instead.
  • For context: the underlying update-verb mechanism for feeds is already engine-pinned (packages/plugins/plugin-audit/src/capability-gate-update-verb.test.ts, describe [#10170] enable.files is asked on the UPDATE verb too / the feeds sibling describe in the same file) — what's missing is the platform-checklist's own driven coverage of it, not the runtime enforcement.

Verification

  • pnpm check:platform-checklist — OK (structural validator; revision/history, oracle presence, provisioning resolution all pass).
  • pnpm check:doc-authoring — pass.
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions — pass (after building @objectstack/formula and @objectstack/lint, which the gate requires pre-built).
  • pnpm check:nul-bytes — pass.

Gate list derived via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack from this checkout at merge-base commit a933ed720.


Generated by Claude Code

…e-verb FILES_DISABLED probe
attachments-storage.json's step-4 fixture citation still quoted the
pre-#10170 create-only wording of enable.files' describe string, which
PR #10733 rewrote post-#10336 to name the update case explicitly ("a
create and an update that re-points an existing attachment alike").
Re-quoted against the live object.zod.ts:281 string.
The stale citation was masking a real coverage gap: #10170 registered
the FILES_DISABLED capability gate on beforeUpdate as well as
beforeInsert (a re-point of parent_object is gated identically to a
create), but attach-requires-parent-edit only ever probed the create
side. Added a new step + acceptance clause 5 that re-points an
existing sys_attachment onto the qa_nofiles fixture (already
provisioned by qa-scratch-authz, #7670 — one throwaway record inserted
into it, no new fixture) and expects 403 FILES_DISABLED, isolated from
ATTACHMENT_PARENT_ACCESS by running as a caller who can edit both
parents. Cites the engine-level #10170 pin
(capability-gate-update-verb.test.ts) that grounds the isolation
claim. Revision bumped 4 → 5 with a history entry.
Looked at the feeds side (FEEDS_DISABLED / thread_id re-thread in
records-forms.json) per triage's request: the create-side probe is
only a `negative` assertion with no driving step, and no fixture in
that area (or in stock showcase) declares enable.feeds: false, so
closing either half needs a new feeds-disabled fixture. Per triage's
explicit clause, reported rather than built — see the PR body and
final report.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding(qa): attachments-storage checklist quotes the pre-#10170 create-only enable.files wording, and appears to probe FILES_DISABLED on create only

2 participants

@yinlianghui@claude