Skip to content

finding(plugin-detail/spec): record:details honours three security keys the pinned spec REFUSES with unrecognized_keys — and they split two ways: requiredPermissions is a deliberate contract refusal, the other two are pin lag #10200

Description

@os-elon-musk

Restart-when: an installable @objectstack/spec release declares both enforceFieldSecurity and redactFields on RecordDetailsProps (check: npm pack @objectstack/spec@latest, then grep -c enforceFieldSecurity over its dist is non-zero; npm latest was 17.4.0 with 0 hits when this line was written)

Summary

record-details.tsx reads and honours three security keys that the @objectstack/spec build this repo is pinned to refuses. An author who goes through the contract has their document rejected at publish, while the renderer would have honoured it.

⚠️ The three do not have the same cause, and filing them as one would be wrong within a single version bump. Measured below: one is a real, deliberate contract refusal; two are pin-lag that a spec bump closes.

Measured — the pinned artifact, run rather than read

@objectstack/spec 17.4.0, resolved from this workspace's own node_modules, RecordDetailsProps.safeParse executed:

input verdict
{ enforceFieldSecurity: true } REFUSE — unrecognized_keys
{ redactFields: ['a'] } REFUSE — unrecognized_keys
{ requiredPermissions: ['a'] } REFUSE — unrecognized_keys
CONTROL { hideFields: ['a'] } PASS — so the shape is not refusing everything
CONTROL { zzzNonsense: 1 } REFUSE, same code — so the three are not special-cased

RecordDetailsProps is a strictObject, and an unrecognized_keys refusal takes the whole document, not the offending key.

⭐ The split, measured against objectstack's CURRENT source

Read at objectstack 04d639c659, packages/spec/src/ui/component.zod.ts, RecordDetailsProps (opens :851):

key in the pinned 17.4.0 in current objectstack source ⇒
enforceFieldSecurity refused DECLARED — z.boolean().optional() pin lag
redactFields refused DECLARED — z.array(z.string()).optional() pin lag
requiredPermissions refused deliberately NOT declared real refusal

For the third the spec says so in its own words, in the docblock above the block:

requiredPermissions — is deliberately NOT declared here. Its read is … the ADR-0066 capability set every other requiredPermissions in this spec … app.areas[].requiredPermissions in 17.0.0. The exit is the spec seat's …

⚠️ Note the reading hazard this seat walked into and is recording so the next reader does not: requiredPermissions appears five times inside that block. All five are prose explaining why it is absent. A bare grep count reads as 「declared」; the declaration list does not contain it. ⇒ ⛔ count declarations, never mentions.

What each half means

requiredPermissions — the durable defect. The renderer's block-level capability gate is reachable only by authoring a key the protocol refuses on purpose. Contract-first (AGENTS.md #0.1) says the fix is upstream or in the renderer, ⛔ never in objectui's mirror: declaring it there would publish a TypeScript face for metadata the platform rejects, which is worse than the gap — it would invite the document that gets refused at publish. The spec's own docblock names the exit as the spec seat's, so the first act is an objectstack card, not an objectui diff.

enforceFieldSecurity / redactFields — pin lag, ⛔ not a contract gap. The contract already declares both; this repo simply has not bumped to a build that carries them. ⇒ the action is a pin bump, and the field-level redaction path becomes author-reachable with no code change at all. ⛔ Do not file these upstream; ⛔ do not "fix" them in the renderer.

Provenance and the positive control

Surfaced by the objectui#9965 dev, whose run measured all three as refused by 17.4.0 with the same two controls. Independently re-run by the filing seat on the same installed artifact (the table above), and then extended: the dev did not have the current-source reading, which is what splits the three. Positive control on the spelling: record:quick_actions does declare requiredPermissions, so it is a name the platform knows and deliberately withheld from this block.

⛔ Not a defect in objectui#9965 or its PR objectui#10198, and ⛔ not a reason it should have gone further: that card's repair correctly stops at hideFields, which is the one key of the file's census that the mirror declares.

Acceptance

  1. Split on filing, ⛔ do not carry the three together. requiredPermissions goes to an objectstack card citing the docblock's own named exit. The other two are a pin bump on this repo.
  2. Re-run the safeParse table above against whatever build is pinned at the time of the work — ⛔ do not inherit this one. Two of these three rows are expected to flip, and a card acting on a stale row does the wrong repair.
  3. ⛔ Nothing in objectui's packages/types mirror moves for any of the three until the contract carries the key. The mirror follows the contract; it never leads it.

Filed by the domain:ui execution seat · session_01Xr7APep6jm1Zta3KUzPzZf · installed-artifact parse run and source reading both taken in this act, 2026-09-21T04:22Z


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Ruling: UI closure batch 15 item 1 · letter protocol (stop reading requiredPermissions; pin bump for the other two) · maintainer 「同意」 (chat, director seat summon #29, session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T13:37Z

    Director seat, summon #29. A class-1 self-adjudication under protocol first, presented and agreed. Read on objectui origin/main: packages/types/package.json still pins @objectstack/spec ^17.4.0, and packages/plugin-detail/src/renderers/record-details.tsx:200 still reads (schema as any).requiredPermissions.

    Ruled, and this replaces acceptance item 1 (⛔ no objectstack card):

    1. requiredPermissions: the protocol deliberately does not declare it on record:details, so the renderer stops reading it there, with a pin that a record:details document carrying the key no longer gates the block. If the spec later declares it under ADR-0066, the renderer reads it then, following the contract.
    2. enforceFieldSecurity / redactFields: pin lag. Bump @objectstack/spec to a build that declares both. ⛔ No renderer change and ⛔ no upstream card.
    3. ⛔ Acceptance items 2 and 3 stand: re-run the safeParse table against the pin at the time of the work, and nothing moves in the packages/types mirror ahead of the contract.

    Execution: pm:queue · priority:p2 · security · domain:ui stand.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1 — domain:ui execution seat 4
    Session: session_01BP8CMtACxTdLjqR6rhd33C
    Branch: claude/issue-10200-record-details-stop-reading-required-permissions
    Worktree: objectui-issue-10200
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: ruling item 1 only — the requiredPermissions read in packages/plugin-detail/src/renderers/record-details.tsx, its tests, one .changeset/10200-…md (stop on breach; explain in the report)
    Container & model: S, not mechanical (a security-gate removal with a pin), mode:subagent, model: opus — dispatch-gates.mjs --repo objectstack-ai/objectui --tier REFUSES from the objectstack checkout ⇒ no path-derived floor; default tier TIER_DEFAULT = 'opus'
    Clause-②: no
    Ruling-ref: 5815200174
    Thread-read: 5815200174
    Serial constraints cleared: open-PR file lists read 2026-09-24T14:49Z (18 open PRs) ⇒ none touches record-details.tsx (only pending changesets that name it, carried by the release PR objectui#5400). Live claims read 2026-09-24T14:50Z: seat 1 objectui#10247 / #10163 / #7867 / #6246 / #10062 / #7190 / #10184, seat 2 objectui#9853 / #4191 / #10190 / #10037 ⇒ none names packages/plugin-detail/src/renderers/. This seat's objectui#10183 (PR objectui#10266) edits DetailView.tsx only, and objectui#10186 edits RelatedList.tsx only ⇒ disjoint files.

    Scope of this claim: ruling item 1 only. Ruling item 2 (the @objectstack/spec pin bump for enforceFieldSecurity / redactFields) is not installable today. npm @objectstack/spec latest is 17.4.0 (published 2026-09-09), and its dist carries 0 occurrences of enforceFieldSecurity (read 2026-09-24T14:50Z). Control: RecordDetailsProps is present in that dist. ⇒ Once item 1 lands, this card goes to pm:on-hold with a Restart-when: naming an installable spec release whose RecordDetailsProps accepts both keys. ⛔ Item 2 is not a rider on this PR.

    Clause-②: no — stopping a read of a key the pinned protocol refuses narrows the renderer to the contract. It widens no accepted shape and adds no export. The change to runtime permission behaviour is ruled by the maintainer (5815200174), and it is the human-floor security class, ⛔ not clause ②.


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 10200,
    "status": "done",
    "branch": "claude/issue-10200-record-details-stop-reading-required-permissions",
    "pr": "#10279",
    "session": "session_01BP8CMtACxTdLjqR6rhd33C (subagent: the parent seat's harness-stamped id; container CLAUDE_CODE_REMOTE_SESSION_ID cse_01BP8CMtACxTdLjqR6rhd33C)",
    "premise_still_valid": true,
    "summary": "Ruling item 1 only. Removed the requiredPermissions read in record-details.tsx and the hasCapabilities block gate it drove (the 'Insufficient permissions to view details.' notice). The fold, the placeholder and the hook sequence are unchanged; usePermissions() is still read for getObjectApiOperations. Added a pin under record-blocks.requiredPermissions-gate.test.tsx. It mounts a real MePermissionsProvider with a reported-empty capability set, renders record:details with requiredPermissions:['crm.manage'], and uses record:highlights in the same tree as the lit control (it is still refused). A capability-spy detector and its wiring control complete it. The 8649 routed-key ledger moves record-details.tsx to a new retired-read ledger that asserts absence, the 9965 honest-cast ledger drops the key, and the rules-of-hooks flip pin now expects the body to stay. Mechanism assumptions: A1 confirmed (the only record:details read site is record-details.tsx; no producer and no generic node-level requiredPermissions read in the tree). A2 confirmed on the installed pin 17.4.0: the key is still refused on RecordDetailsProps, so the premise holds and no table row flipped. A3 respected: quick_actions, highlights and related_list are untouched. The claim's newest Claim: names this branch. The card's assignee read os-litant at start; this run never wrote it. Worktree removed after the PR opened.",
    "tests": "All at final head ed52015 unless noted. (1) Union: pnpm exec vitest run over 28 test files, derived by git grep as every test importing or reading record-details or the four touched tests (plugin-detail plus readers in app-shell, core, types, plugin-form, plugin-kanban) -> 'Test Files 28 passed (28) / Tests 352 passed (352)', lock VERDICT command-exit 0. (2) Baseline on BASE 88a4ef6, the four touched test files: 4 passed / 83 tests. After the change: 4 passed / 72 tests. The delta is accounted for: 12 describe.each rows dropped with record:details, 2 details-only discriminator pins removed, 4 inverse pins added, 1 routed ledger leg swapped for 1 retired leg, 1 honest-cast leg removed. (3) Ablation: fix committed first (b0451c5). Via objectstack scripts/ablation-replace.mjs in WRAP mode, the removed read and gate were re-planted in place of the new docblock (anchor 1 -> 0, replacement 0 -> 1, blob 9c4f2d35ad06 -> 410176e69d4a) and the same four files run: 'Test Files 3 failed | 1 passed (4) / Tests 5 failed | 67 passed (72)'. Red were the 3 record:details inverse pins, the rules-of-hooks flip pin and the retired-read ledger leg. Green as designed were the spy-wiring control and all sibling pins. Restore was proven by the tool (blob after restore == HEAD blob 9c4f2d35ad06, git diff HEAD empty) and independently (git diff HEAD 0 bytes, hash-object == rev-parse HEAD:path). No build or dist in the path: tests import the renderer by relative src path. (4) pnpm --filter @object-ui/plugin-detail run type-check (echoed 'tsc --noEmit && tsc -p tsconfig.test.json') exit 0, after turbo run build --filter='@object-ui/plugin-detail^...' --concurrency=2 (11/11, all cache hits, FULL TURBO). tsc -p tsconfig.test.json --listFilesOnly contains all 5 touched TS files. (5) eslint --format json on the 5 touched files (package config): 5 files, 0 errors, 51 pre-existing warnings. This is a declared narrowing. Population from eslint's API: 256 of 262 tracked plugin-detail files (6 ignored), touched 5/5 in it. Count read from the JSON output. Invariance: no type-aware linting in eslint.config.js (no parserOptions.project or projectService) and no eslint-rules/* rule reads the filesystem. (6) safeParse table on installed @objectstack/spec 17.4.0 RecordDetailsProps: requiredPermissions REFUSE unrecognized_keys; enforceFieldSecurity REFUSE; redactFields REFUSE; CONTROL hideFields PASS; CONTROL zzzNonsense REFUSE. Also ComponentPropsMap['record:details']===RecordDetailsProps is true, and RecordQuickActionsProps accepts requiredPermissions (spelling positive control). Table is in the PR body.",
    "mcp_calls": "0",
    "api_writes": "2 (1) POST /repos/objectstack-ai/objectui/pulls via fleet-write relay (repository_dispatch to objectstack-ai/objectstack, run 36018759026 success) -> draft PR 10279, body read back byte-identical (9051 bytes, no differing index). (2) POST /repos//issues/10200/comments via scripts/pm/post-stamped.mjs, this os-dev-report. git push x3 to the branch (empty probe, fix commit, changeset commit), not REST. Zero label writes: the brief named no label, and objectui's labels are labeler.yml-owned.",
    "gates": [
    "vitest 28-file union @ed5201527: exit 0 (352 passed)",
    "vitest ablation leg (mutated renderer): exit 1, 5 failed / 67 passed, expected direction; restore proven",
    "pnpm --filter @object-ui/plugin-detail run type-check @ed5201527: exit 0",
    "turbo run build --filter='@object-ui/plugin-detail^...': exit 0 (11/11 cached)",
    "eslint --format json, 5 touched files: exit 0, 0 errors",
    "node scripts/check-changeset-presence.mjs: exit 0",
    "node scripts/check-changeset-no-major.mjs: exit 0",
    "pnpm check:vi-mock-override-shape: exit 0",
    "pnpm check:vi-mock-inherit: exit 0",
    "pnpm check:vi-mock-specifiers: exit 0",
    "pnpm check:test-path-roots: exit 0",
    "pnpm check:control-bytes: exit 0",
    "pnpm check:new-line-citations: exit 0 (0 new citations)",
    "pnpm check:pending-changeset-literals: exit 0",
    "pnpm check:changeset-claims: exit 0 (report-only; named 7997, 8400, 8649 changesets as mentioning touched files; read, 8649 narrowed, see findings)",
    "node scripts/check-governed-queue-guard.mjs --test (6 paths): NOT GOVERNED",
    "NOT MEASURED: full plugin-detail suite and pnpm lint, reason: declared narrowing, CI farm owns them; CI on PR 10279 not awaited (in_progress at report time)"
    ],
    "deviations": [
    "Declared narrowing: the plugin-detail suite was not run in full locally. The behaviour delta is confined to record:details nodes authoring a non-empty requiredPermissions, the hook sequence is unchanged, and the only tests authoring that key on record:details are the ones edited (git grep).",
    "Declared narrowing: lint ran on the touched files only (three-part proof in tests (5)).",
    "The commit trailers use the role file's model-free pair (Claude-Session + Co-authored-by: Claude). The harness attribution reminder's model-named trailer was not used, per the role file and the brief.",
    "Pending changesets .changeset/10155-record-blocks-capability-gate.md and .changeset/8649-detail-renderer-undeclared-keys.md are outside the claim's file surface and were not edited. This PR's own changeset states the supersession instead."
    ],
    "files_changed": [
    "packages/plugin-detail/src/renderers/record-details.tsx",
    "packages/plugin-detail/src/renderers/tests/record-blocks.requiredPermissions-gate.test.tsx",
    "packages/plugin-detail/src/renderers/tests/record-details.test.tsx",
    "packages/plugin-detail/src/renderers/tests/detailRendererUndeclaredKeys-8649.test.ts",
    "packages/plugin-detail/src/renderers/tests/record-details.hideFieldsUncast-9965.test.ts",
    ".changeset/10200-record-details-stop-reading-required-permissions.md"
    ],
    "open_questions": [
    {
    "question": "Extend ruling item 1 to record:highlights and record:related_list? Both read requiredPermissions exactly as record:details did, and the installed spec refuses the key on both. For the seat and maintainer: it is a security-gate change, so the maintainer floor applies and this run did not touch them.",
    "options": [
    "A: extend the ruling and stop reading the key on both blocks, with the same inverse pins",
    "B: keep both gates and ask the spec seat to declare requiredPermissions on the three record blocks under ADR-0066",
    "C: leave as is"
    ],
    "recommendation": "A. On the four axes: business need is zero measured pull, with no in-tree producer authoring the key on any of the three blocks (git grep: tests only). Long-term fit: the spec docblock on RecordDetailsProps names the key deliberately undeclared on all three, so contract-first means the renderer follows. AI-error prevention: A removes a renderer-only dialect that honours metadata the contract refuses at publish, while B widens the contract with no pull. Startup focus: immediate retirement, no staged window, no new gate. C keeps the exact inconsistency item 1 was ruled against, now split across sibling blocks."
    }
    ],
    "out_of_scope_findings": [
    "class: b · record:highlights and record:related_list read requiredPermissions via (schema as any) and hide the block on it. Installed @objectstack/spec 17.4.0 refuses it on both: RecordHighlightsProps.safeParse({fields:['a'],requiredPermissions:['a']}) is REFUSE unrecognized_keys, the control without the key is PASS, and RecordRelatedListProps behaves the same. Contract text, objectstack packages/spec/src/ui/component.zod.ts, RecordDetailsProps family docblock: 'The THIRD key objectui reads on these three blocks — requiredPermissions — is deliberately NOT declared here.' Seam: spec:RecordHighlightsProps / RecordRelatedListProps (requiredPermissions deliberately undeclared) → renderer:record-highlights.tsx / record-related-list.tsx. Recommended as a sub-issue of objectui#10200, needing the ruling extended (see open_questions). Dedupe words: record:highlights requiredPermissions; record:related_list requiredPermissions undeclared; stop reading requiredPermissions sibling blocks; hasCapabilities record block gate",
    "carrier: domain:ui#4 seat, before release PR objectui#5400 publishes · noted, not filed. Two pending changeset bodies read differently once this lands. .changeset/10155-record-blocks-capability-gate.md has a headline naming record:details as capability-gated, and .changeset/8649-detail-renderer-undeclared-keys.md says the key is 'read by all three renderers'. Both are unreleased (plugin-detail CHANGELOG carries neither). This PR's changeset states the supersession; amending either body is the seat's call because it breaches this claim's file surface."
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    🔁 REWORK (patch round 1): PR objectui#10279 at ed52015, one item, prose only

    domain:ui seat #4, session_01BP8CMtACxTdLjqR6rhd33C. I read report os-dev-report on this card in full and reviewed it against the PR diff. ⛔ It has not been reviewed on CI yet: a new head is coming.

    Claim file surface amended in this round. .changeset/10155-record-blocks-capability-gate.md and .changeset/8649-detail-renderer-undeclared-keys.md are added, prose only, frontmatter untouched.

    The item. Both are pending changesets. Once this PR lands, each says something false about record:details:

    • 10155's headline names it among the three capability-gated blocks.
    • 8649 says requiredPermissions is "read by all three renderers".

    Both publish verbatim into the same CHANGELOG version as this PR's own entry, which says record:details stopped reading the key. That would be a permanent contradiction (the one-way-door class objectui#10030 closed). ⇒ Both are being narrowed in this PR.

    Accepted as it is:

    • Ruling item 1: the read and the block gate are removed from record-details.tsx, and the hook sequence is unchanged.
    • The inverse pin uses a real MePermissionsProvider and an empty capability set, with record:highlights as the lit control, an ablation proven by blob hash, and the routed-key and honest-cast ledgers moved.
    • The safeParse table was re-run on the installed 17.4.0 (item 3), and all three keys are still refused.
    • Part of #10200.

    Routed by the seat, not by this PR: record:highlights and record:related_list read the same undeclared key and hide the block on it. Extending ruling item 1 to them is a security-gate change, so it goes to a card of its own for triage and the maintainer. It is ⛔ not a rider here.


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 10200,
    "status": "done",
    "branch": "claude/issue-10200-record-details-stop-reading-required-permissions",
    "pr": "#10279",
    "session": "session_01BP8CMtACxTdLjqR6rhd33C (subagent: the parent seat's harness-stamped id)",
    "premise_still_valid": true,
    "summary": "Addendum, patch round 1 (REWORK 5816961914): prose only. New head 7ce2c53 (was ed52015). Commit 295dc56 changes three changeset bodies, with all frontmatter byte-unchanged. (1) .changeset/10155-record-blocks-capability-gate.md: the headline and body now name record:highlights and record:related_list only ('These two record blocks', 'Both now read', and the && objectName note is on record:highlights only), plus one clause: record:details carried it too and no longer reads the key at all (objectui#10200). The ADR-0066 fail-closed semantics, the object-read call that does not move, and the unreported-capability residual are intact. (2) .changeset/8649-detail-renderer-undeclared-keys.md: the one sentence now reads that enforceFieldSecurity and redactFields are read by all three renderers, and requiredPermissions by record:highlights and record:related_list (record:details stopped reading it, objectui#10200). The measured table is untouched. (3) This PR's own changeset drops its 'supersedes / narrows' sentence, because the text it pointed at is now corrected; it keeps only 'record:highlights and record:related_list are unchanged and still gate on the key, fail-closed' plus the server-side note. Merge 7ce2c53 brought in origin/main 4ab4f1b once, with no conflicts; the merge touched nothing under plugin-detail/src/renderers, permissions, or the three changesets. The claim surface amendment was read on the card before the push. Worktree removed again after the push. Routing of the sibling-block finding is left to the seat, as instructed.",
    "tests": "At head 7ce2c53, exit codes landed in a file before reading. node scripts/check-changeset-overwrite.mjs exit 0: report-only, lists 10155 and 8649 as modified with 'declared at base' == 'declares now', which is case 2 (deliberate prose correction). pnpm check:changeset-claims exit 0: born-false 0 line addresses in the 3 bodies; self-contradiction PASS; still names 7997 and 8400 for record-details.tsx, both paragraphs re-read and still true. pnpm check:pending-changeset-literals exit 0. node scripts/check-changeset-presence.mjs exit 0 ('5 source file(s) of 1 released package(s) changed ... declares 1 changeset(s)'). node scripts/check-changeset-no-major.mjs exit 0. pnpm check:new-line-citations exit 0 ('VERDICT new-cross-file-line-citations: 0 new citation(s)'). Extras: pnpm check:control-bytes exit 0. The same 28-file vitest union re-run under the lock on the merged head: 'Test Files 28 passed (28) / Tests 352 passed (352)', VERDICT command-exit 0.",
    "mcp_calls": "0",
    "api_writes": "1 this round: POST /repos//issues/10200/comments via scripts/pm/post-stamped.mjs (this addendum). git push x1 (ed52015..7ce2c53), not REST. PR body NOT patched, as instructed.",
    "gates": [
    "check-changeset-overwrite @7ce2c531e: exit 0 (report-only; 2 modified, declarations unchanged)",
    "check:changeset-claims @7ce2c531e: exit 0",
    "check:pending-changeset-literals @7ce2c531e: exit 0",
    "check-changeset-presence @7ce2c531e: exit 0",
    "check-changeset-no-major @7ce2c531e: exit 0",
    "check:new-line-citations @7ce2c531e: exit 0",
    "check:control-bytes @7ce2c531e: exit 0",
    "vitest 28-file union @7ce2c531e: exit 0 (352 passed)"
    ],
    "deviations": [
    "Also edited this PR's own changeset (.changeset/10200-...md, prose only): its supersession sentence quoted the 10155 and 8649 wording that this round removes, so it would have shipped false. This file is inside the original claim surface."
    ],
    "files_changed": [
    ".changeset/10155-record-blocks-capability-gate.md",
    ".changeset/8649-detail-renderer-undeclared-keys.md",
    ".changeset/10200-record-details-stop-reading-required-permissions.md"
    ],
    "pr_body_edits_for_the_seat": [
    "Heading 'Verification (final head ed52015)': the head is now 7ce2c53. The test union and the changeset gates re-ran green there; type-check and eslint were read at ed52015, and the round added prose-only .md edits plus a merge that touched no plugin-detail renderer or permissions file.",
    "'What changed' list: add a bullet saying the pending .changeset/10155-record-blocks-capability-gate.md and .changeset/8649-detail-renderer-undeclared-keys.md bodies are narrowed to record:highlights / record:related_list for requiredPermissions (prose only, frontmatter unchanged).",
    "Acceptance note 2 is now false. It says both files are outside the claim surface and the PR's own changeset states the supersession. Replace it with: both pending bodies are corrected in this PR (claim surface amended in patch round 1), and the own changeset's supersession sentence was dropped."
    ],
    "open_questions": [],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Blocked-by: #10281

    domain:ui seat #4, session_01BP8CMtACxTdLjqR6rhd33C, at 2026-09-24T15:25Z: pm:dispatched → pm:blocked in this stroke. The assignee stays, because this seat follows the card to its end.

    Why. While implementing ruling item 1, the seat found a contrary ruling in flight. objectstack-ai/objectstack#18159 (ruling batch #197 item 2 A, pm:dispatched on domain:spec) declares requiredPermissions on record:details, record:highlights and record:related_list, and its PR objectstack-ai/objectstack#19913 is open as a draft. Ruling 5815200174 here orders the renderer to stop reading the key on record:details because the spec does not declare it. Its text anticipates "if the spec later declares it", but it does not mention that a ruling to declare already exists and is being executed.

    What the seat did, per protocol for a contrary fact found during a ruled action:

    • The work is executed literally: PR objectui#10279 implements item 1, and its patch round 1 is done at 7ce2c531e (pending changesets 10155 / 8649 narrowed so they stay true).
    • ⛔ No auto-merge and no ready on objectui#10279: a dissent window stays open.
    • The conflict is filed as decision card objectui#10281 (options, recommendation and the four facets; recommendation A: the spec declaration wins, item 1 is withdrawn, objectui#10279 is closed unmerged).

    The review-tier record and the PR-body edits for objectui#10279 are deferred until objectui#10281 is answered. Under A the PR closes, so reviewing it now would be wasted work. Under B the seat runs the review, applies the dev's three named body edits, and lands it.

    Unlock-action: re-check #10281 when label needs-user-decision absent


    Generated by Claude Code

  7. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Release: session_01BP8CMtACxTdLjqR6rhd33C (domain:ui#4) · cause: ruling A on objectui#10281 withdraws item 1; item 2 is not installable · destination: pm:on-hold, assignee cleared in this stroke
    Restart-when: an installable @objectstack/spec release declares both enforceFieldSecurity and redactFields on RecordDetailsProps (check: npm pack @objectstack/spec@latest, then grep -c enforceFieldSecurity over its dist is non-zero; npm latest was 17.4.0 with 0 hits when this line was written)

    Item 1 is withdrawn. Ruling A on objectui#10281 (comment 5823922380): the protocol declaration wins. requiredPermissions on record:details is the ADR-0066 capability gate that objectstack-ai/objectstack#18159 declares (PR objectstack-ai/objectstack#19913), so the renderer keeps reading it. PR objectui#10279, which stopped the read, is closed unmerged in this stroke.

    Item 2 is on hold. It bumps @objectstack/spec to a build that declares enforceFieldSecurity / redactFields, which is still pin lag, as ruled in 5815200174. No installable release carries those keys yet: npm latest is 17.4.0. So this card holds on the install-surface criterion above, per the cross-repo rule that consumers wait for an installable release, ⛔ not an upstream merge.

    Restart shape. Bump the pin. Then re-run the ruling's safeParse table (acceptance item 2) against the new pin, and move nothing in the packages/types mirror ahead of the contract (acceptance item 3). The body's Blocked-by: #10281 line is replaced with the Restart-when: line in this stroke.


    Generated by Claude Code

  8. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Unlock scan: pm:on-hold → pm:queue. The install-face condition is met, because objectui main now resolves @objectstack/* 17.5.0 (PR objectui#11086, merged as 81f849852a, closing objectui#11073)

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-30T04:44Z. ⛔ Not a claim, ⛔ not a dispatch. The grade, route and ruling are unchanged.

    • The card's condition: an installable release declares both enforceFieldSecurity and redactFields on RecordDetailsProps.
    • The probe, run against the published @objectstack/*@17.5.0 from npm (the version objectui's pnpm-lock.yaml now resolves; the spec tag commit is objectstack 0f6dcac5e9): enforceFieldSecurity is in 4 dist files and redactFields in 36. The decision objectui#10281 is closed.
    • Next. The card goes to pm:queue. The dispatching seat re-reads the body against objectui main at claim. The probe above licenses the work; it does not replace that read.
  9. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Blocked-by: #8649

    pm:queue → pm:blocked: the remaining item is in flight on PR objectui#11184

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T09:55Z. ⛔ Not a claim.

    • What is left here. Item 1 is withdrawn (ruling A on objectui#10281, 5824127957). Item 2 was the pin lag: an installable spec declaring enforceFieldSecurity / redactFields on record:details. The bump landed in PR objectui#11086 (17.5.0; triage probe 5904216975), so the spec no longer refuses them. What remains is objectui declaring the keys its renderer already reads.
    • That is PR objectui#11184's diff (Fixes #8649, draft, spec seat): RecordDetailsComponentProps / RecordHighlightsComponentProps / RecordRelatedListComponentProps gain enforceFieldSecurity, redactFields and requiredPermissions; the nine (schema as any) reads in record-details.tsx, record-highlights.tsx and record-related-list.tsx lose their casts; packages/plugin-detail/src/index.tsx publishes the three inputs. Dispatching this card now would edit the same files for the same keys.
    • Unlock. When objectui#8649 closes, the unlock scan releases this card. The seat that reads it then re-checks record:details against main: if nothing is left, it closes completed naming the merged PR; if a residue remains, it goes back to pm:queue with the residue named.

    Unlock-action: re-check #8649 when label pm:dispatched absent

  10. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    Contributor

    Closed completed: delivered by PR objectui#11184 (64790868674)

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ. This executes the unlock instruction in 5908817178. That comment's Blocked-by: #8649 cleared when objectui#8649 closed. The label went back to pm:queue with no comment (around 2026-10-01T03:35Z, writer unrecorded), and this comment pairs that transition.

    Re-checked against origin/main (read 2026-10-01T07:56Z):

    • Item 2, the pin lag. objectui resolves @objectstack/spec 17.5.0 (PR objectui#11086), which declares enforceFieldSecurity and redactFields on RecordDetailsProps. The contract no longer refuses them.
    • What objectui owed. PR objectui#11184 (Fixes #8649, merged as 64790868674, an ancestor of main) declares the field-security triple, enforceFieldSecurity, redactFields and requiredPermissions:
      • on RecordDetailsComponentProps, RecordHighlightsComponentProps and RecordRelatedListComponentProps (packages/types/src/record-components.ts);
      • as registry inputs in packages/plugin-detail/src/index.tsx.
        record-details.tsx, record-highlights.tsx and record-related-list.tsx under packages/plugin-detail/src/renderers/ now read schema.enforceFieldSecurity and schema.redactFields un-cast. git grep finds no (schema as any) read of the triple outside the pin file detailRendererUndeclaredKeys-8649.test.ts.
    • Item 1 (requiredPermissions as a deliberate refusal) was withdrawn by ruling A on objectui#10281 (5824127957).

    Nothing is left on this card.

    domain:ui seat 1 · close · 2026-10-01T07:56Z

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2security

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions