Skip to content

docs: a system-elevated hook or action body is refused identity-assignment writes - #26501

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-3yv1gc
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-3yv1gc

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Fixes #26466

Clause-②: no
Metadata-protocol: none
Skills-docs: follow-up owed — skills/objectstack-automation/SKILL.md (the runAs: 'system' guidance at L164-191 never says these four writes are refused; it also owes an eval prompt per the package's convention; domain:skills, Tier H, triage 6434140653)

维护者速读

What changes

  • content/docs/automation/hooks.mdx, the runAs table's 'system' row: drops "full-access" and adds one sentence. Elevation stops at identity assignment. An insert, update, delete, transfer, restore or purge of sys_user_position, sys_user_permission_set, sys_invitation or sys_member from an app-authored hook's system context (runAs: 'system', an inherited system context, or ctx.api.sudo()) is refused with PERMISSION_DENIED. A runAs: 'system' hook whose language: 'js' body writes one of them by name is refused at save. The sentence gives the remedies the refusal names: runAs: 'user' for positions and permission sets, so the delegated-administration gate judges the user; the organization endpoints for invitations and memberships. It links system-context.mdx row 1b.
  • content/docs/ui/actions.mdx, "Authorization inside an action": the same sentence for an action body and a registered handler. A type: 'script' action whose body names such a write is refused at save. The assignment remedy is the one the action refusal names: a flow whose runAs is 'user', run by an action of type: 'flow'. The next sentence now reads "The other consequence is…" so the caller-specific-rule guidance still follows.

The pages describe the refusal and its remedy only. They name no way around it.

Why

Both pages told authors that system elevation bypasses every check. Since #25653 the data middleware refuses these four writes from app-authored system automation. Since #26430 (merged 2026-10-27T04:43Z) HookSchema and ActionSchema also refuse a body that names one at save. system-context.mdx row 1b already states the rule. These two pages contradicted it and left out the remedy.

Tests

Docs only: no behaviour changed, so no test and no ablation.

Acceptance notes

Wording was read against origin/main 00a4593a:

  • Run-time refusal and remedy text: packages/plugins/plugin-security/src/flow-system-identity-write-refusal.ts (SUBJECT, ASSIGNMENT_PRESCRIPTION, MEMBERSHIP_PRESCRIPTION).
  • Who carries the mark: packages/runtime/src/action-execution.ts#buildActionExecutionContext serves every handler an action door dispatches, a host code handler included. That is why the actions sentence says "either".
  • Save-time half: packages/spec/src/identity/identity-assignment-body-writes.ts, hook.zod.ts#refuseElevatedIdentityAssignmentBodyWrite (only runAs: 'system' + language: 'js') and action.zod.ts#refuseIdentityAssignmentBodyWrite (only type: 'script' + language: 'js'). The pages claim save-time refusal only for those shapes.

Not done here, by the claim:

  • skills/objectstack-automation/SKILL.md: see the Skills-docs: line.
  • The card's two "Also carried" items: FlowSchema has no save-time twin of the body check, and the four-object set and prescription text are duplicated between the spec leaf and plugin-security. Both are reported to the seat as out-of-scope findings and are not built here.

Verification

Readings are at head a5d2534c.

Derived gate families
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 43 commands derived for the 2 changed paths (16 changed lines).
  • On the first pass, 42 exited 0. check:skill-examples exited 3 (PREREQUISITE NOT MET: the client-react dist was missing). After pnpm --filter '@objectstack/client-react...' build under os-verify-lock (VERDICT command-exit 0), it exited 0: "265 prose examples type-check across 3 surface(s)".
  • dispatch-gates --ran with every exit code recorded: "43 derived, 43 run, 0 NOT-MEASURED, 0 UNRUN" (a DERIVED zero).
Card acceptance
  • pnpm check:doc-authoring: exit 0 (in the derived set).
  • docs-audit: pnpm check:docs-audit-scope and pnpm check:docs-transcript-drift: exit 0 (in the derived set).
  • Doc links: pnpm check:doc-anchors: exit 0. Negative control: after the actions.mdx link fragment was changed to #1-authorization-and-scopingX, it exited 1 and named content/docs/ui/actions.mdx:455 ("renders no heading with id"). The file was restored with git checkout HEAD --, and git diff HEAD is empty. The lychee lane (check-links.yml) is CI's run.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (No schema touched.)
  • 2. Every name I added uses the casing for its kind. (No names added.)
  • 3. No formatter ran; pnpm lint passes. (No code touched; the repo-wide run is CI's.)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Docs only, nothing publishes: skip-changeset.)
  • 6. packages/spec touched: its generated artifacts are regenerated and committed. (Not touched.)
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ADHkmQoXzgoMtkwN9diP2g


Generated by Claude Code

…signment writes

The hooks runAs table and the actions authorization section said elevation
is full-access / bypasses every check. Writes to sys_user_position,
sys_user_permission_set, sys_invitation and sys_member from app-authored
system automation are refused at run time, and a sandboxed body naming one
is refused at save. State the refusal and the remedy it names, and link
system-context row 1b.

Claude-Session: https://claude.ai/code/session_01ADHkmQoXzgoMtkwN9diP2g
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · devx seat 2 · 2026-10-27T05:47Z

Seat domain:devx#2 (#20163) · session_01Q4MDXRbEJCNdPAP4SiXwp9 · reviewed head a5d2534c · card #26466 (claim 6434462498, branch claude/project-thread-3yv1gc), wave 10 delta S. Not governed; +13/−3 in two content/docs/** pages.

Landing: ready + auto-merge once CI on this head is green. The card closes on Fixes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants