Skip to content

docs(adr-0056): reconcile Consequences with the P2/P4 pure model - #5970

Merged
os-trump merged 1 commit into
mainfrom
claude/issue-3794-adr0056-consequences
Aug 25, 2026
Merged

docs(adr-0056): reconcile Consequences with the P2/P4 pure model#5970
os-trump merged 1 commit into
mainfrom
claude/issue-3794-adr0056-consequences

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#3794

This PR is docs/adr/** — a governed path. It must be merged by a human and must NOT reach the merge queue. It stays a draft: not marked ready, not enqueued, no auto-merge. Human merge is the review record.

What changed

docs/adr/0056-permission-editing-studio.md, prose only, two bullets in Consequences. Nothing else in the repo.

Both bullets still described the ADR's original Option B (system_permissions editable in Setup as an exception) — the model this ADR's own Status line records as superseded by the pure model. Direction was settled by triage on 2026-08-09: "the later, specific rulings win over the earlier summary sentence". P2/P4 stay as they are.

1. The bullet the card names (the target of #3794)

Capabilities are authored once, in Setup, through the sys_capability picker.

→ Capabilities are designed once, in Studio, through the sys_capability picker (P2); Setup only assigns permission sets to users (P1b) and shows every facet read-only (P1).

Verified still present before editing, with control probes so a zero-hit would have read as real rather than mis-pathed:

proberesult
One authoring path per concern (control — known present)hit, line 223
P2 — Studio: System Capabilities editor (control — known present)hit, line 203
authored once, in Setup (target)hit, line 225

2. A second contradiction found by the audit — same defect class, same section

Studio becomes load-bearing for permission ops. An admin who can assign sets but lacks studio.access can no longer design them. … hence P2 keeps that grant in Setup and first-class.

This is Option-B residue twice over, and it is contradicted by four settled statements inside this same file:

  • P2 — "Capabilities are now designed here, not authored in Setup."
  • Decision 3 — "No exception for system_permissions. … The bootstrap concern (granting studio.access shouldn't require Studio) is resolved by the editor's env-scope entry point living inside Setup (/apps/com.objectstack.setup/metadata/permission/:name, setup.access), not by keeping a JSON/authoring field on the record."
  • Decision 1 — "reached from the Studio Access pillar (package scope, studio.access) and from Setup's env-scope metadata route (setup.access) … the same component, two entry points."
  • A2 (revised, ADOPTED) — "so capability design is available to an operator without a separate Studio entry".

The replacement text says only what those four already decide, plus what the code shows. A reviewer who prefers the audit bounded strictly to the one sentence #3794 names can drop this hunk on its own — it is a separate, self-contained hunk.

Evidence — every Consequences bullet audited against P1–P4 and against the code

#BulletVerdictHow it was checked
1One authoring path per concernFIXEDCapabilityMultiSelectField is rendered by Studio's packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx:980, bound to draft.systemPermissions. Setup stamps permission-facet-link on all six facets including system_permissionspackages/data-objectstack/src/index.ts:3397-3402.
2Setup/Studio audience split is honoredaccurate"operators assign" — RecordPermissionAssignmentsRenderer renders AssignedUsersSection on the Setup record page (P1b). "makers design" — Studio Access pillar → PermissionMatrixEditPage. A statement about audience, not about which surface hosts the editor; no tension with Decision 1's two entry points.
3AI-authoring safety improves — no security concern reachable as a free-text blobaccurateAll three Setup surfaces short-circuit to the read-only renderer: detail read (DetailSection.tsx:261), inline edit (InlineFieldInput.tsx:248), record form (ObjectForm.tsx:664-669, widget || type). PermissionFacetLink.tsx contains noonChange, input, or textarea. The raw-JSON escape hatch contemplated in open question 5 was never shipped.
4aRendering changed objectui-side; storage columns untouchedaccurateapplyFieldWidgetOverrides is invoked from getObjectSchema (packages/data-objectstack/src/index.ts:3361) — the ADR names exactly that choke point. It sets only widget, never type; the framework object definition is unchanged.
4bEditors "read RowLevelSecurityPolicySchema / tabPermissions enum / AdminScopeSchema from @objectstack/spec — the editors couple to those shapes"left as-is; measurement reportedMeasured: those two symbols are imported nowhere in this repo — the only repo-wide occurrence is a comment at packages/app-shell/src/views/metadata-admin/clientValidation.ts:526 explaining that RowLevelSecurityPolicySchema is deliberately not substituted. PermissionAdvancedFacets.tsx declares local mirror interfaces and says the shapes were "checked against the spec schemas rather than sampled from live data (objectstack#7130)". So the bullet's trailing clause — "the editors couple to those shapes" — is exactly right, and it is the sentence's own gloss on "read". Under that reading the bullet is not wrong, so the fix would be a wording preference, not a direction correction. Not touched. If a reviewer wants it sharpened: "mirror RowLevelSecurityPolicySchema, the tabPermissions enum and AdminScopeSchema — checked against the spec schemas rather than importing them."
4cQ7 — env-scope metadata saves don't project onto the queryable data recordleft as-is; not falsifiable from this fenceSelf-labelled an open framework follow-up; P1–P4 are all objectui-side and none of them touches the projection, so nothing in this repo can close or contradict it. Not a Consequences↔P1–P4 mismatch.
5Studio becomes load-bearing for permission opsFIXEDSee section 2 above. Also measured: PermissionFacetLink.tsx:71-78 builds the deep-link from the currentappName (useParams), so from a Setup record page it targets /apps/com.objectstack.setup/metadata/permission/:name and never cross-navigates into Studio — i.e. what shipped is the "Setup-hosted route that reuses the component" branch of open question 1, which is what makes Decision 3's setup.access entry point real.

Audit outcome: 6 Consequences claims (5 bullets, the 4th having three sub-bullets). 2 fixed, 2 accurate, 2 deliberately left with the measurement reported.

Verification

Gate union re-run at the final commit c18be84e8, working tree clean, each verdict quoted from the gate's own output (not from $?):

gateverdict line
node scripts/check-changeset-presence.mjs✅ No source of a released package changed in this range, so no changeset is owed. (1 file(s) changed, 0 of them under the src/ of a package the release covers)
node scripts/check-control-bytes.mjs✅ check-control-bytes: OK (scanned 4950 tracked text file(s); skipped 85 binary).
node scripts/check-doc-links.mjsLinks are valid across 13 scan roots.
node scripts/check-doc-component-types.mjs✅ Every documented component type is registered.

No changeset — the presence gate itself says none is owed for this range.

Declared narrowings (CI runs the full farm regardless):

  • check:doc-snippetsoutside its scan surface, by the script's own constant: check-doc-snippet-types.mjs:208 sets DOCS_ROOT = 'content/docs'; this diff is under docs/adr/. (It also cannot run in this worktree — ERR_MODULE_NOT_FOUND: typescript, no node_modules installed for a docs-only change.)
  • eslint — the changed file is outside the linted population by eslint's own configuration, not by my judgement: lint:root is eslint . … --ignore-pattern 'docs/**', and lint is turbo run lint (per-package) while docs/adr belongs to no workspace package (no docs/package.json). File count: 1, from the changeset gate's own output. Invariance: the diff is prose inside one Markdown file — no eslint config, tsconfig, or package.json changed, so no untouched file's verdict can move.

Manual on-disk confirmation of the edit, anchored in both directions rather than trusting an editor exit code:

authored once, in Setup: 0 (removed)
P2 keeps that grant in Setup: 0 (removed)
designed once, in Studio: 1 (injected)
structured editor becomes load-bearing: 1 (injected)

Generated by Claude Code


Generated by Claude Code

Two bullets in ADR-0056's Consequences still described the original
Option B (capabilities editable in Setup as an exception), contradicting
P2, P4, and Decision 3/4 of the same file:
- "Capabilities are authored once, in Setup, through the `sys_capability`
picker" — P2 says capabilities are designed in the structured editor,
"not authored in Setup", and the code agrees: the picker
(CapabilityMultiSelectField) is rendered by Studio's
PermissionMatrixEditor, while Setup stamps the read-only
`permission-facet-link` widget on all six facets including
`system_permissions`.
- "hence P2 keeps that grant in Setup and first-class", preceded by "an
admin who ... lacks `studio.access` can no longer *design* them" —
Decision 1/3 and A2 (revised) settle the opposite: the same editor has
two entry points, and Setup's env-scope metadata route runs under
`setup.access`, which is what dissolves the bootstrap knot.
Prose only; no code, no schema, no other file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSoz9uGhaaSgiq3hshtN7L
@os-trumpClaude

Copy link
Copy Markdown
Collaborator

Merging on the maintainer's direct instruction. Provenance: the maintainer, PM chat session 2026-08-25, batch-2 governed-PR review including this PR (both hunks presented; the second — the same Option-B residue one bullet over — recommended and accepted as part of the batch): 「同意」. Audit record for the governed-merges checklist. Checks verified at head c18be84e8: 19 runs, all success/skipped. Executed by PM session session_01H9StxQgG2DPA26XzZZqnJB.


Generated by Claude Code

@os-trump
os-trump marked this pull request as ready for review August 25, 2026 11:10
@os-trump
os-trump added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 090927fAug 25, 2026
20 checks passed
@os-trump
os-trump deleted the claude/issue-3794-adr0056-consequences branch August 25, 2026 11:28
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentation

Projects

None yet

3 participants

@yinlianghui@os-trump@claude