docs(ui): the flow face of recordLoadDenied is populated since #15168 (#15303) - #15583
Conversation
… (#15303) The "Flow actions" paragraph under "Authorization inside an action" still carried the honesty clause the contract's TSDoc carried before #15168: that on the flow face `recordLoadDenied` is "declared but not yet populated" and a guard on it is "inert (never `true`), never wrong". That is false on `main`. `dispatchFlowAction` spreads `actionRecordLoadSignal(subject)` into the context it hands `automation.execute` (`packages/runtime/src/action-execution.ts:904`), and both action doors reach it through that one function — the REST `/actions` route (`packages/runtime/src/domains/actions.ts:732`) and the MCP `run_action` bridge (`packages/runtime/src/action-execution.ts:1758`), each passing the whole `ActionSubjectRecordLoad` rather than a bare record. The direction of the defect is the inverted form of the Prime Directive #10 corollary: not a doc advertising a capability the runtime does not deliver, but a doc denying one it now does — so an author reading it would not write the `runAs: 'system'` guard the two-card sequence exists to enable, and no gate reports it. The replacement transcribes the sentence that landed on the contract (`packages/spec/src/contracts/automation-service.ts:56`), adapted to docs voice by naming the two doors, which that page's readers otherwise cannot resolve. The surrounding `runAs: 'user'` / `runAs: 'system'` prose and the `ctx.record.id` table are untouched. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
|
ACCEPT — PM seat Reviewed against the three-dot diff
Dev's verification quoted: derived family 37 commands, all exit 0 at Flipping ready + enabling auto-merge. Fixes #15303. Generated by Claude Code |
Fixes #15303
What changed
One paragraph in
content/docs/ui/actions.mdx— the Flow actions paragraph under "Authorization inside an action". It still carried the honesty clause the contract's TSDoc carried before #15168:That sentence is false on
main. It is replaced by a transcription of the sentence that landed on the contract under #15168 (packages/spec/src/contracts/automation-service.ts:56), adapted to docs voice by naming the two doors — a docs reader has no other way to resolve "both doors", and the page's audience is app authors rather than spec readers:The surrounding
runAs: 'user'/runAs: 'system'prose and thectx.record.idtable are untouched. Diff: 1 file, 6 insertions, 5 deletions (5 of the 6 inserted lines are the rewrapped tail of the same paragraph).The direction of the defect is the inverted form of the Prime Directive #10 corollary: not a doc advertising a capability the runtime does not deliver, but a doc denying one it now does — an author reading it would not write the
runAs: 'system'guard the two-card sequence exists to enable, and no gate reports it.Premise verification — the runtime half IS on
main, on BOTH doorsVerified on a worktree cut from
origin/mainat0c5e97368, not from the card.One flow dispatcher, and it spreads the signal —
packages/runtime/src/action-execution.ts, insidedispatchFlowAction, in the object handed toautomation.execute(line 904):Door 1 — the REST
POST /api/v1/actions/...route,packages/runtime/src/domains/actions.ts:732:Door 2 — the MCP
run_actionbridge,packages/runtime/src/action-execution.ts:1758:Both doors pass the whole
ActionSubjectRecordLoad(recordandrecordLoadDenied,action-execution.ts:1290) into the one dispatcher, andactionRecordLoadSignal(action-execution.ts:1373) turns that verdict into{ recordLoadDenied: true }or{}. So the flow face is populated, on both doors, exactly when a handler face would be. ⇒premise_still_valid: true.Census — every other copy of the claim in
content/docs/**Three greps over the whole docs corpus (
not yet populated,declared but not,recordLoadDenied):content/docs/ui/actions.mdx:382content/docs/ui/actions.mdx:341,345,350,357,373,380ctx.record.idtable — true, and fenced out by the card. Untouched.content/docs/automation/hook-bodies.mdx:241ctx.recordLoadDenied". It says nothing about the flow face and stays true. No change, as the card said.content/docs/permissions/permissions-matrix.mdx:155content/docs/protocol/objectql/query-syntax.mdx:912,content/docs/data-modeling/queries.mdx:374,content/docs/api/wire-format.mdx:413501 NOT_IMPLEMENTED/ datasource-not-connected error strings. Same three words, unrelated subject. Out of scope.content/docs/releases/v17.mdx:4796⇒ Exactly one copy of the falsehood existed, and it is the one fixed.
Verification
Gate family derived mechanically, never hand-listed:
node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack, exit 0, 37 runnable families. The whole union re-run at the final commit368722879, clean tree. Every exit code captured by redirect-then-capture, never after a pipe.dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack37 command(s) — 25 pnpm, 12 direct node (30 matched by path, 0 by change KIND, 7 declared WHOLE-TREE ...)node scripts/docs-audit/check-affected-docs.mjsnode scripts/docs-audit/check-drift-comment.mjscheck-drift-comment: 56 cases pass across 5 fixture diff(s).pnpm check:nul-bytescheck-nul-bytes: OK (scanned 7551 text file(s) ... no raw ASCII control bytes)pnpm check:doc-anchors306 internal #fragment link(s) across 410 source file(s) all resolve to a real headingpnpm --filter @objectstack/spec run check:docspnpm --filter @objectstack/spec run check:skill-examples257 prose examples type-check across 3 surface(s)node scripts/check-doc-frontmatter.mjs(+--self-test)node scripts/check-docs-section-name.mjs(+--self-test)pnpm --filter "@objectstack/spec..." build(under the shared lock)os-verify-lock: VERDICT command-exit 0 · held the lock 148sturbo run build --filter=@objectstack/{formula,lint,client-react,client}(under the lock)os-verify-lock: VERDICT command-exit 0 · held the lock 372s·34 successful, 34 totalBoth gates the card names run green over this change, and that is the point rather than a reassurance:
check:affected-docsandcheck:drift-commentare exactly the two gates that would be expected to carry a stale-docs claim, and neither does. No gate carries this defect in either direction — it could only ever be found and fixed by reading.Three families were NOT MEASURED on the first pass and then measured.
check:doc-formula-expressionsandcheck:doc-security-postureexited 3 (Nothing was measured: this gate exited before running a single check) andcheck:skill-examplesexited 1 on the same prerequisite class — all three refusing because a package they read was unbuilt, none of them a finding. After the builds above, all three re-ran at exit 0. They are reported as measured only on the second run.Grep control (the change is asserted in both directions, not just forwards):
Staleness discharged. A re-derivation on the branch warned that
origin/mainhad moved and that four files the derivation reads had changed across the range. Rather than trust it, the family set was re-derived in a throwaway worktree detached at the currentorigin/main(954cb0bbf) with this change applied: byte-identical, 37 families. No family appears or disappears at currentmain.Not runnable locally (CI only), named for completeness — 3 families whose argv takes a value from the workflow (
$RUNNER_TEMP,matrix.shard), matched viaci.yml'scontent/**filter on the Test Core shards:check-cross-package-test-inputs.mjs --union-into ...,check-shard-attestation.mjs --emit ...,check-test-completeness.mjs ....Changeset
None.
content/docs/**publishes nothing from any package, so this PR declares no release of its own;changeset-checkinpr-automation.ymlhas no path exemption, and its declared instrument for that case is theskip-changesetlabel, applied to this PR.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code