fix(plugin-detail): record:quick_actions.requiredPermissions publishes the contract's shared describe (objectui#10224) - #11329
Conversation
…s the contract's shared describe (objectui#10224) The registration described the key as "Hide the whole bar unless the user holds these permissions". The renderer reads the ADR-0066 capability set (hasCapabilities, objectui#10058), draws an insufficient-permissions notice in place of the bar, and fails open when capabilities are unreported. @objectstack/spec 17.5.0 carries one describe for this key on all four record blocks; objectui#8649 published it on the other three, and this input now publishes the same text, verbatim. The gate pin re-reads the installed describe every run, adds rows for the clauses it did not yet cover (read/update as capability names, fail-open with no provider and with an unreported systemPermissions), and its prose and test names now say what it asserts. The console parity file's MEMBER_PINS row and its slice-4 note stop describing the retired perms.can() read and a bar that is hidden. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
…rect the pending objectui#10058 changeset (objectui#10224) check:installed-pin-claims read "Through 17.4.0" in the gate pin's header as a present-tense claim about the installed spec and failed it. The new prose now names objectstack#18159 instead of a version, in the pin header and in the registration comment, so the next spec bump has nothing to restamp. The pending objectui#10058 changeset says an unheld capability "hides the whole bar" and quotes the contract's retired wording. It ships in the same release as this change, which publishes the notice behaviour, so it gets a dated, append-only correction in the shape objectui#8649 gave the sibling objectui#10155 changeset. Its frontmatter and every earlier byte are unchanged. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…a notice, not that they hide (objectui#10224) Round 2, comment and test-title text only. The record:quick_actions gate docblock said an unheld capability "hides the whole bar", directly above the code that renders a role=status insufficient-permissions notice in the bar's place. It now says that, cites the shared record-block describe the registration publishes, and points at its existing paragraph on the fail-open for unreported capabilities. The sibling pin record-blocks.requiredPermissions-gate.test.tsx carried the same "hides" wording in its header and two test titles for blocks that draw the notice. Those texts now name the notice. No assertion, fixture or helper moves, and no ledger or locator reads either title. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Read, over REST and ① Derived judgments
② Semver level
③ Boundary flagsFrom the round-1
Check-runs on this head, read 2026-10-01T04:27Z: 42 — 29 success, 3 skipped ( Implemented-by: VERDICT: PASS Rendered 2026-10-01T04:33Z by the isolated at-tier reviewer running inside the seat session named above; posted through |
…hed text (objectui#10224) Round 3, from the at-tier review. The 10224 changeset said the new description is carried by sdui.manifest.json "and the JSX authoring types". The manifest carries it: manifestFromConfigs copies each input's description. generateDts in sdui-parser's codegen.ts reads no description, so the generated intrinsics carry none, before or after this change. The sentence now names the manifest and the runtime registry inputs only. The gate pin's docblock made the same pairing about the registration's inputs; it now says the manifest carries descriptions and the JSX types take only names and value types. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Delta record on round 3. The PASS record ① Derived judgments
② Semver level
③ Boundary flags
Check-runs on this head, read 2026-10-01T04:40Z: 42 — 22 success, 3 skipped ( Implemented-by: VERDICT: PASS Rendered 2026-10-01T04:41Z by the isolated at-tier reviewer running inside the seat session named above; a delta on |
|
What failed: job The cause: objectstack What happens next: the repair is filed as objectui#11330. Under the standing ruling objectui#10916 |
…missions-text for the Spec Main Shape Gate repair (objectui#11343) Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Delta record on the landing head. The PASS records ① Derived judgments
② Semver level
③ Boundary flags
Check-runs on this head, read last. Implemented-by: VERDICT: PASS Rendered 2026-10-01T07:12Z by the isolated at-tier reviewer running inside the seat session named above; a delta on |
…jectui#11168 slice 3, round 3, second merge) origin/main advanced to 2124d04 after the first round-3 merge (25901fc), bringing #11329 (fd6f5da) and seven more. No conflict. The guard auto-merged: main's side is MEMBER_PINS prose only (record:quick_actions.requiredPermissions, object-calendar.navigation, object-kanban.navigation) and one comment, kept as main has them. The census of the merged ledgers is unchanged: unjudgedBlocks 2, offSpecInputs 0, unpublishedKeys 3, refusedArms 0, memberPins 0; objectui#11168 owns 5, 8652 and 8649 own 0. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
Fixes #10224
Clause-②: no
What changes
packages/plugin-detail/src/index.tsx: therecord:quick_actionsinputrequiredPermissionsnow publishes the contract's shared record-block describe, verbatim. It is the textrecord:details,record:highlightsandrecord:related_listhave published since objectui#8649. It replaces "Hide the whole bar unless the user holds these permissions". The input's name, type and shape stay the same, and no rendering or gating behaviour changes.packages/plugin-detail/src/renderers/__tests__/record-quick-actions.requiredPermissions-gate.test.tsxis the pin file the console row points at. Its header prose and two test names now say what the assertions check: the notice in place of the bar, not a hidden bar. Six rows are added for clauses the published text makes and the file did not pin yet:readandupdateas capability names (DISCRIMINATOR 4a / 4b);systemPermissions;apps/console/src/__tests__/registry-inputs-spec-parity.test.ts: theMEMBER_PINSrow forrecord:quick_actions.requiredPermissionsand the slice-4 note in that row's neighbourhood no longer describe the retiredperms.can(objectName, p)read or a hidden bar. The row now lists what the pin file asserts. No other row changes..changeset/10224-quick-actions-permissions-text.md:@object-ui/plugin-detailpatch..changeset/10058-quick-actions-capability-gate.md(pending): a dated, append-only correction. See the file-surface note below.105cddc65), comment and test-title text only:record-quick-actions.tsxnow says the gate draws arole="status"insufficient-permissions notice in the bar's place rather than hiding the bar, and that unreported capabilities fail open.record-blocks.requiredPermissions-gate.test.tsx, the header and two test titles now name the notice.Premise, measured before the edit (base
0c6f9bbd7)In the installed
@objectstack/spec17.5.0,RecordQuickActionsProps.shape.requiredPermissionscarriesRECORD_BLOCK_REQUIRED_PERMISSIONS_DESCRIPTION. The three record blocks use the same constant. The registration said "Hide the whole bar unless the user holds these permissions".A one-off probe (not committed) read every clause through the real
SchemaRenderer, the realrecord:quick_actionsregistration and the real permission providers. The object declares one action, Approve:crm.manageheld,crm.manage+crm.exportrequiredreadrequired,allowRead: true, capability set reported emptyupdaterequired,allowEdit: true, capability set reported emptysystemPermissionsPermissionProvider"Presentation only: it authorises nothing" was read from the gate code: the gate is a render branch and makes no request. Every clause of the shared describe holds on this block, so it is published here unedited.
Ablations (one-off, from committed state)
Each mutation went through
../objectstack/scripts/ablation-replace.mjs: the anchor hit once, and the blob hash moved. Each restore was checked: the blob hash equals HEAD's andgit diff HEADis empty. The subject resolves by relative path (../../index,../record-quick-actions) to source, so nodistis in the resolution path.perms.can(objectName, p)over every member: 10 failed / 12 passed. The failures include 4a and 4b, alongside the objectui#10058 rows.Gates (local; CI runs the full farm)
Commits on this branch:
50214f307(the change),4e45246a3,105cddc65andeb65af7bd.Round 3,
eb65af7bd, is text only. The 10224 changeset now namessdui.manifest.jsonand the runtime registryinputsas what carries the description. That is becausegenerateDtsreads nodescription, so the generated intrinsics carry none. The pin docblock that made the same pairing is corrected the same way.check:changeset-claims,check-changeset-presence,check:pending-changeset-literals,check:new-line-citationsandcheck:control-bytesall exit 0. The gate pin passes 22/22.Round 2 is text only. Its checks: plugin-detail type-check exit 0; the two gate pins plus the console parity file, 298 passed;
check:new-line-citations,check:control-bytesandcheck:installed-pin-claims, each exit 0.About
4e45246a3: The second commit is comment-only inpackages/: a diff filter that drops comment lines prints nothing. It also adds the changeset note.Closure build:
turbo run build --filter='@object-ui/plugin-detail^...' --concurrency=2. 11/11 tasks, all restored from the turbo cache, with everydist/index.d.tspresent.@object-ui/plugin-detailtype-check: exit 0 at4e45246a3.--listFilesontsconfig.test.jsonlists the pin file.@object-ui/plugin-detailfull suite: 228 files passed, 1 skipped; 2276 tests passed, 8 skipped, at50214f307.At
4e45246a3, 7 files / 354 tests passed:record-blocks.requiredPermissions-gate.test.tsx;record*Inputs.spec-parityfiles;recordQuickActionsInputs.actionNamesFallback.test.tsx;apps/console/src/__tests__/registry-inputs-spec-parity.test.ts(230 tests).Manifest consumers, because the published description moved:
sdui-intrinsics-compile-11075,public-contract,html-tier-manifest,ga-honoured-inputs-author-reach,component-input-union-specimensandrecord-block-record-reachinapps/console. 6 files / 80 tests passed.check:*gates at4e45246a3, all exit 0:control-bytes,new-line-citations(0 new),changeset-claims,pending-changeset-literals,installed-pin-claims,spec-symbols,vi-mock-specifiers,vi-mock-inherit,vi-mock-override-shape,test-path-roots,phantom-deps. The changeset scriptscheck-changeset-presenceandcheck-changeset-no-majoralso exit 0.installed-pin-claimsfailed once, on50214f307. The pin header said "Through 17.4.0", and the gate read that as a claim about the installed spec. The new prose now names objectstack#18159 instead of a version.Lint, narrowed to the three touched code files, plus the evidence that narrowing excludes nothing:
eslint --print-configresolves a config for each file (none is ignored);--format jsonlists 3 files, 0 errors;parserOptions.projectandprojectServiceare unset, so linting is not type-aware and this diff cannot move a verdict on any untouched file. The repo-widepnpm lintbelongs to CI.NOT MEASURED:
@object-ui/consoletype-check. The console edit is a string literal and comments inside an existingMemberPinobject literal, and the check needs a whole-workspace build. Declared to CI.check:sdui-registration-pins, which exits 2 (PREREQUISITE NOT MET: no consoledist). Its subject is thesideEffectsarrays, which this diff does not touch.File-surface note: the pending objectui#10058 changeset
The claim named one changeset. The pending
10058-quick-actions-capability-gate.mdships in the same release as this one. It says an unheld capability "hides the whole bar" and that the gate "is published as" the contract's retired wording. With this change in that release, the registration publishes the notice behaviour, so those sentences become false in that release.It therefore gets a dated, append-only correction, in the shape objectui#8649 gave the sibling
10155-record-blocks-capability-gate.md. Its frontmatter and every earlier byte are unchanged:cmpof the original length against the pre-edit copy prints nothing. This applies the dispatch's standing pending-changeset clause. If the seat reads it as outside the claim, the note is one paragraph to drop. The seat ruled A (keep the note) at round 2.Acceptance notes (not filed)
105cddc65): the two "hides" texts this section used to list.check:changeset-claimslists three other pending changesets that name a file this change touches:8067-component-input-member-kind.md,9280-record-highlights-entry-icon-retired.mdandrecord-alert-cta-label-i18n-4998.md. All three were read. None describes this input's text, and none is made false.Generated by Claude Code