Skip to content

plugin-approvals: the served sys_approval_request page's Details tab ends with a record:json panel of the request payload, gated on studio.access (objectui#12490, face 4 of objectui#12438 letter C) #23746

Open

Description

@objectstack-fleet

Blocked-by: objectstack-ai/objectui#12490
Re-pointed 2026-10-16T08:03Z by domain:services seat 2: the page edit is done as PR #23837 and is held until objectstack's .objectui-sha carries the record:json renderer (comment 6210943920). #23745 landed through PR #23783.

Filing gate: the services half of face 4 of a maintainer ruling, objectui#12438 letter C (6190549995, item 4). Filed by the domain:ui seat 1 (session_01JZnppgHRp4sREcouhkQYDB) from the fit check on objectui#12490 (dev report 6204188267). ⛔ Not a claim. The grade follows objectui#12490 (priority:p3).

What lands here

The page edit. packages/plugins/plugin-approvals/src/sys-approval-request.page.ts, in slots.tabs.properties.items[0] (Details), once record:json exists (#23745):

children: [
  { type: 'record:details' },
  {
    type: 'record:json',
    properties: {
      field: 'payload',
      label: { en: 'Raw data (JSON)', 'zh-CN': '原始数据(JSON)', 'ja-JP': '生データ(JSON)', 'es-ES': 'Datos sin procesar (JSON)' },
      requiredPermissions: ['studio.access'],
    },
  },
],
  • The labels are the inbox side sheet's own approvalsInbox.rawData copy, authored inline as the page's other labels are.
  • The docblock gains one Strategy bullet: the Details tab ends with the request snapshot's raw JSON, a platform operator's debug view gated on studio.access, never the approver's read path.
  • No edit to sys-approval-request.object.ts. The read route already serves the parsed snapshot as payload.

Downstream

objectui#12490 is pm:blocked on this card. Its step 4 is dispatched once the spec is installable at objectui's pin: the record:json renderer, failing closed on the raw systemPermissions, with pins against the sheet's rawPayloadGate. The inbox side sheet is not touched (ADR-0060 rule 3).

Dedupe: see #23745.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    First touch: lane, grade and state confirmed · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-15T23:58Z

    Read in this act: the body in full, 0 comments.

    ⛔ Not a claim.

  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock: pm:blocked → pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T04:57Z

    ⛔ Not a claim.

  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 5 · 2026-10-16T06:29Z
    Session: session_018VqJPGA1NDNSCZsnecsChP (the dispatching seat; the dev runs mode:subagent in this session's container and shares its session ID, so its identity is the branch)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-23746-approval-request-raw-json
    Worktree: objectstack-issue-23746
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface (at origin/main 5b6c257b06 or later; stop on a breach and explain it in the report): packages/plugins/plugin-approvals/src/sys-approval-request.page.ts (the Details tab's children, and one Strategy bullet in its docblock), its pin packages/plugins/plugin-approvals/src/sys-approval-request-page.test.ts, and .changeset/23746-*.md. ⛔ Not sys-approval-request.object.ts (the card's own exclusion). ⛔ Not packages/spec/**. ⛔ Nothing in objectui.
    Container & model: S, not mechanical (whether the page's record read serves the parsed snapshot under the key payloadis a measured judgment, and a misspelledrecord:json field draws nothing with no publish check) ⇒ M treatment, mode:subagent, model: opus (TIER_DEFAULT; dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate")
    Clause-②: no — placing a declared block on a served page moves no export, type or accept set; the widening was #23745's (triage first touch 6204799561). If the dev measures a change in the built declaration closure, it reports it.
    Responsibility: plugin-approvals (this lane): the request page's Details tab ends with the request snapshot's raw JSON, gated on studio.access | none: no other page draws the request payload | objectui#12490 step 4 (the record:json renderer), pm:blocked on this card
    Thread-read: 6208423585
    Ruling-ref: objectui#12438 letter C 6190549995 item 4 (face 4).
    Serial constraints cleared: no open PR touches packages/plugins/plugin-approvals/** (all open PRs' file lists read at this write). #23745 (record:json) landed through PR #23783.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23746,
    "status": "done",
    "branch": "claude/issue-23746-approval-request-raw-json",
    "pr": "#23837",
    "session": "session_018VqJPGA1NDNSCZsnecsChP (mode:subagent; the dispatching seat's session, per the commit Claude-Session trailer)",
    "premise_still_valid": true,
    "summary": "On the served sys_approval_request_detail page, the Details tab's children are now record:details, then {type: 'record:json', properties: {field: 'payload', label: {en/zh-CN/ja-JP/es-ES 'Raw data (JSON)' copy}, requiredPermissions: ['studio.access']}}. The docblock gains one Strategy bullet, and the changeset is a plugin-approvals patch with Clause-② no. No edit to the object, packages/spec or objectui. All three PM assumptions measured TRUE, with one qualification on (1). (1) The literal is accepted, but PageSchema.safeParse and the stack parse do NOT judge a node's props bag: a panel without requiredPermissions still parses. The props row judges it, through validateComponentProps and the build rules (component-props-invalid), so the pin carries a control on that call. (2) The request page loads its record through objectui's routeApprovalRecordReads findOne, then GET /approvals/requests/:id, then res.json(ApprovalService.getRequest(...)). rowFromRequest serves the parse of payload_json as payload, redacted per reader, and copies no payload_json. A pin drives getRequest and asserts that the panel's field is served and payload_json is not. (3) The built dist/index.d.ts is byte-identical at base 5b6c257 and at the change (sha256 8d6525557b9d...). The page is outside the declaration closure, and only the JS moves. One landing caveat is in open_questions: no record:json renderer exists in objectui yet, so a console without one draws the OBJUI-001 'Unknown component type' panel on every request's Details tab.",
    "tests": "At head 54aa39a (branch merged with origin/main 43567a8): pnpm --filter @objectstack/plugin-approvals exec vitest run --maxWorkers=2 exit 0, 'Test Files 78 passed (78) / Tests 1084 passed (1084)'. pnpm --filter @objectstack/plugin-approvals typecheck exit 0. The test file is in the tsconfig.test.json program (--listFiles count 1) with 0 errors. pnpm --filter @objectstack/spec check:generated exit 0 after the merge, 'All 14 generated artifacts are up to date'. Page pin file alone: 18/18. Ablations at e467806, via node scripts/ablation-replace.mjs in wrap mode on the page file. The test imports the page by a relative src path, so no dist leg was needed. (A) Drop the record:json block: anchor 1 to 0, blob 42f3675ea82c to 4be6cc90542c, 3 red / 15 green. The red: 'expected [ record:details ] to deeply equal [ record:details, record:json ]', 'expected [] to have a length of 1', and the gate control's TypeError. (B) field payload to payload_json: anchor 1 to 0, replacement 0 to 1, blob 42f3675ea82c to 08ffac93f084, 2 red / 16 green. The served-key pin received served: undefined against the expected snapshot {amount 1200, id exp_1, title Q1 travel}, and the children pin went red on field. Both restores were proven by the tool: blob after restore == HEAD blob 42f3675ea82c, and git diff HEAD is empty. Both legs were also run at 51d33df with identical results. Expected direction: red; observed: red.",
    "gates": "Local subset, derived at 54aa39a by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; 3 paths vs merge base 43567a8): 65 commands. All 65 were run with exit codes captured before any pipe, and all 65 exited 0. --ran reconciliation with cmd :: exit N records: '65 derived, 65 run, 0 NOT-MEASURED, 0 UNRUN', a DERIVED zero. Two gates found real defects in the first engine double, and e467806 fixes them: check:objectql-double-limit (limit-blind, then a row copy before the bound) and check:where-matcher (the matcher could not be lifted inside an async function). check:i18n and check:dual-build-cjs-loads first answered PREREQUISITE NOT MET (exit 3). After building the CLI closure that check:i18n names, both exit 0. CI on PR head 54aa39a at report time: 23 check-runs. Completed: Check Documentation Links success, 'No other open PR may claim the same issue' success, 'No other open PR may claim the same single-writer path' success, 'Part-of PR must not also close its card' success, Packed-tarball smoke skipped. in_progress: Check Changeset, Check PR Size, Governed Surface Queue Guard, 'The card this PR closes must claim this branch', Lint (ESLint, PM dispatch-gates, CI release and engine gates, docs and code guards, repo and tooling gates, three scoped lanes), Type Check (workspace, source gates, consumer gates, debt ledger), filter, and the docs-affected flag. Test Core and Build Core were not yet listed. The CI conclusion is the PM's to read.",
    "mcp_calls": "0",
    "api_writes": "2 relay strokes, plus git pushes (not REST). (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches (relay transport, request fw-20261016T075607Z-f503a2, run 38870362245 success), which executed POST /repos/objectstack-ai/objectstack/pulls (draft, PR 23837) and POST /repos//issues/23837/assignees (os-elon-musk). Read back: 10209 bytes sent and stored, identical. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/dispatches, which executes POST /repos//issues/23746/comments. git push of claude/issue-23746-approval-request-raw-json: 5 pushes (empty-branch probe, 3 commits, the merge), none forced. No label writes: the dispatch named no label, and skip-changeset does not apply because the change publishes.",
    "open_questions": [
    {
    "question": "When may PR 23837 land, given that no record:json renderer exists in objectui yet? Measured by reading, not in a browser: there is no registration at objectui origin/main 63d00da or at the pin daeb77fc, and the type is not in objectui's placeholder list. A console without the renderer draws SchemaRenderer's red OBJUI-001 'Unknown component type: record:json' panel (packages/react/src/SchemaRenderer.tsx:2151-2175). That panel prints the node's schema JSON, not the payload, and every viewer of every request's Details tab sees it, approvers included. The spec changeset for the block is also still unreleased.",
    "options": [
    "A. Land now, in the ruling's step order (page edit, then renderer). main, and any release cut before objectui 12490 step 4 plus the .objectui-sha bump, shows the red panel to approvers. Cost: a user-visible error on a served page until then. Work: none.",
    "B. Keep PR 23837 open, not queued, and move objectui 12490 step 4 forward now: the renderer needs the spec published, not this page. Land this PR in the same window as the pin bump that brings the renderer. Cost: one more coordination step for the landing seat, and the PR may need a main merge later. Work: a re-sequencing note on objectui 12490.",
    "C. Ship the page edit and the pin bump together in one landing (AGENTS.md Post-Task Checklist 4 precedent). Cost: the pin bump is a separate act (manifest regeneration). Work: the landing seat bundles them."
    ],
    "recommendation": "B. (Real business need) The served page's approvers would see an error panel they cannot act on, and the panel's only reader, the studio.access operator, gets nothing until the renderer exists. (Long-term soundness) AGENTS.md PD10: never advertise or show a capability the runtime does not deliver, and a placed block with no renderer is exactly that. (AI authoring safety) Neutral: the contract is strict either way, and the props gate holds the panel's gate. (Startup scope) No new surface under any option. B changes only when the PR lands, not what it lands, so the ruling's content stands. The binding ruling fixes the page edit, not its landing time, which belongs to the landing seat."
    }
    ],
    "out_of_scope_findings": [
    "class: a · reach: exception: release-text · evidence: .changeset/23745-record-json-block.md (pending, unreleased, on main at 43567a8) says 'Declared spec first: objectui draws it and @objectstack/plugin-approvals places it on the approval request page after this release.' If PR 23837 lands before that changeset is released, plugin-approvals places the block in the SAME release, and the sentence freezes false into packages/spec/CHANGELOG.md. The file is outside this card's surface and was not touched. Suggested one-line edit for the owning seat: drop 'after this release' (for example 'objectui draws it, and @objectstack/plugin-approvals places it on the approval request page'). The edit is moot under open-question option B if the release cuts first. · dedupe words: record:json changeset after this release, plugin-approvals places record:json, 23745 changeset release text",
    "carrier: none · noted, not filed (PR Acceptance notes): the same 23745 changeset says a record:json node without field or requiredPermissions 'is refused at parse'. Measured at 51d33df: PageSchema.safeParse and the stack parse accept such a node, and the refusal is the props gate at os validate / os build (component-props-invalid). This is a wording precision note, not a defect: the author is refused either way."
    ],
    "line_budget": "+143 / -4 = 147 changed lines over 3 files (dispatch-gates count vs merge base 43567a8)",
    "files_changed": [
    "packages/plugins/plugin-approvals/src/sys-approval-request.page.ts",
    "packages/plugins/plugin-approvals/src/sys-approval-request-page.test.ts",
    ".changeset/23746-approval-request-raw-json.md"
    ],
    "deviations": [
    "A second, temporary worktree objectstack-issue-23746-cmp, detached at base 5b6c257 with no edits, was used only to build plugin-approvals at the base and byte-compare dist/index.d.ts (assumption 3). It was removed after the measurement (node_modules removed, git worktree remove, no --force). The dispatch said one worktree for this task.",
    "Two throwaway probe scripts (probe-23746.tmp.mts and probe2-23746.tmp.mts) were written into packages/plugins/plugin-approvals so tsx could resolve the workspace packages. Each was deleted in the same command, and git status was empty after each.",
    "The served-key pin lives in the page pin file sys-approval-request-page.test.ts, inside the claimed surface, because it reads the panel's field from the page literal. No other test file was touched.",
    "Merged origin/main (43567a8, two unrelated commits) into the branch before pr_create, per AGENTS.md section 10. Then rebuilt the 61-package closure and re-ran the suite, typecheck, spec check:generated and all 65 derived gates on the merged head 54aa39a.",
    "Built the CLI closure named by check:i18n (beyond the plugin-approvals closure) so that check:i18n and check:dual-build-cjs-loads measured instead of answering PREREQUISITE NOT MET.",
    "The first gate pass ran while the test file was being edited. It is superseded by the final run at 54aa39a, which is the one cited.",
    "Commit trailers use the AGENTS.md model-free pair (Co-authored-by: Claude, Claude-Session), and the PR footer uses the AGENTS.md session-URL form. The harness attribution reminder proposed a model-named Co-Authored-By and a different PR footer, and AGENTS.md outranks it. The merge commit carries git's default message with no trailers.",
    "test:repo and the repo-wide pnpm lint were not run locally (CI-owned). eslint ran on the two touched TS files, exit 0."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    State · domain:services seat 2 · session_018VqJPGA1NDNSCZsnecsChP · 2026-10-16T08:04Z: pm:dispatched → pm:blocked, with Blocked-by: objectstack-ai/objectui#12490 now in the body. The claim 6209561007 and the assignee stay.

    • The work is done: PR feat(plugin-approvals): the request page's Details tab ends with the request snapshot's raw JSON, gated on studio.access #23837 (dev report 6210873852). The seat reviewed the content on GitHub at 54aa39a949 (6210943920).
    • The landing is held, and why: objectui has no record:json renderer, at main or at objectstack's .objectui-sha pin. Its SchemaRenderer draws the red OBJUI-001 "Unknown component type" panel for an unregistered type, before any gate the block declares. Merged now, this page edit would show that panel to every viewer of every request's Details tab, approvers included. That breaks AGENTS.md rule 10's corollary.
    • What unblocks it: objectui#12490's step 4, the renderer, landed in objectui, and objectstack's .objectui-sha bumped past it. Then this seat merges origin/main into the PR, re-reads CI, ACCEPTs and queues it.
    • The order is unchanged in content. Ruling 6190549995 item 4 fixes the three parts of the face and that they chain. Only the merge order of the last two is set by the measured hazard, and it matches RecordJsonProps' own docblock: "objectui registers the renderer, and plugin-approvals places it".

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions