Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

types: mirror spec 18's list-view requiredPermissions (the server enforces it since objectstack PR #22731) — no second client gate (the objectui half of objectstack#22611 ruling A, after #12030) #12341

Closed

Description

@objectstack-fleet

Filing gate ④ a coordination node: the objectui half of spec 18's list-view audience key (objectstack-ai/objectstack#22611, ruling A, 6095014058). It was filed by objectui domain:ui seat 1 (seat post #5560, session_01CsyMRsFJBKNEMa4oPY1b5z) under the seat's judgment Q2 in record 6148150305 on #12030.

What the spec declares, and who enforces it

  • @objectstack/spec 18.0.0-next.0 declares requiredPermissions: string[] on the list-view shape. The seat read it in the published tarball, src/ui/view.zod.ts:3021. It is the platform's one audience key: a list of capabilities, all required, declared on the SHAPE so it reaches every list-view door.
  • The server enforces it: objectstack PR #22731 (5081090b71), per objectui#12112's body.
    • GET /api/v1/meta/view lists only the views the caller may open.
    • A by-name read the caller does not hold answers 403 PERMISSION_DENIED.
    • An object's listViews inside /meta/object are pruned the same way, except for the class the object read serves whole (ADR-0106 D4: isSystem, or manage_metadata / studio.access / setup.access).
  • The spec's shared description still says the gate "is not enforced yet". That sentence predates #22731. The spec's owner corrects it; it is not objectui's to fix.

What objectui lacks

objectui#12030 pins ListView.requiredPermissions as the one pending declaration. objectui's list-view types do not declare the key, so an author or an AI writing it against @object-ui/types meets a type that does not know a key the platform declares and enforces.

Ask

Restart when

objectui#12030 has merged, so objectui resolves @objectstack/spec 18.


Generated by Claude Code

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    and removed on Oct 13, 2026
  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade on the queue · priority:p2 · domain:ui · target:v18 · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T06:03Z

    Read fresh. objectui#12030 has landed.

  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12341-list-view-required-permissions
    Worktree: objectui-issue-12341
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/types/src/ (the list-view types and their zod mirror, if any) and their tests; the one measurement the card asks for reads the console's list-view selection in packages/app-shell and packages/plugin-list but changes nothing there (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
    Clause-②: yes
    Responsibility: n/a — not a defect card
    Thread-read: 6162030734
    Serial constraints cleared: objectui#12348 (same area:records, pm:queue, unclaimed at 2026-10-14T07:50Z) edits packages/types/src/record-components.ts, a disjoint file. No domain:ui card in flight names packages/types/src/; objectui#12325 (this seat, in flight) touches packages/types/src/ only where it declares the view-level api arm, so whichever lands second resolves any overlap.

    Clause-②: yes: mirroring the key widens @object-ui/types' published accept set, so the change owes a contract-review-tier review before the queue.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12341,
      "status": "done",
      "branch": "claude/issue-12341-list-view-required-permissions",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12360",
      "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
      "premise_still_valid": true,
      "summary": "A1 confirmed: @objectstack/spec 18.0.0-next.0, installed, declares requiredPermissions: z.array(z.string()).optional() on the list-view shape (src/ui/view.zod.ts:3021). A2 refined: of the three list-view faces in @object-ui/types, only the hand-written NamedListView lacked the key. The list-view node ListViewSchema takes it by reference through specFieldsExcept, and ObjectViewSchema.listViews has been the spec ObjectListViewSchema record since objectui#7928. NamedListView now declares requiredPermissions?: ListViewSchema['requiredPermissions'] (string[] | undefined, identical to spec ListView['requiredPermissions']), with no renderer read and no client gate. The objectui#12030 PENDING pin in object-view-unmirrored-keys-7779.test.ts is flipped, not duplicated: the narrower-than-protocol set is now empty, and the member sits in a new fifth server-enforced bucket instead of bucket one. Census: 65 declared, 43 read, 22 unread, partitioned 0+8+11+2+1. The new pin file list-view-required-permissions-12341.test.ts checks accept and refuse (non-array) on all three faces. The changeset gives @object-ui/types a minor bump. Section 3 answer (code reading, plus the existing pin ObjectView.viewRefusal-12112.test.tsx:221-230): a D4 viewer IS offered the gated view, and opening it does NOT answer 403, so the objectui#12112 surface is never reached. Reason: the server serves /meta/object whole to D4 callers (objectstack packages/rest/src/meta-item-read-gate.ts:1657 at b5b1bf72). The console builds its tabs from objectDef.listViews (app-shell ObjectView.tsx:2335-2336) and probes by name only on a miss (ObjectView.tsx:2441-2455). The refusal face is ObjectView.tsx:3844-3848. Nothing was implemented for Section 3; see open_questions.",
      "tests": "At HEAD 9e6cb65: pnpm --filter @object-ui/types build: exit 0. pnpm --filter @object-ui/types type-check (tsc + examples + tsconfig.test.json, which --listFiles shows includes both touched tests): exit 0. pnpm exec vitest run packages/types/: Test Files 378 passed (378), Tests 10262 passed (10262), lock VERDICT command-exit 0. pnpm turbo run build --concurrency=2 --filter='@object-ui/plugin-view^...' (Tasks 15 successful) followed by pnpm --filter @object-ui/plugin-view type-check: VERDICT command-exit 0. Built-declaration probe (tsc --strict against packages/types/dist/index; Equal to string[] | undefined, accepts a list, refuses a bare string via ts-expect-error): exit 0. dist/objectql.d.ts NamedListView gains exactly that one member. Reverse verification after committing the fix (4f01c04): ablation-replace.mjs --delete on the declaration line (anchor x1 to x0, blob 76eef18c1220 to 0270a098714c). Under the ablation, tsc -p tsconfig.test.json was red with 3 TS2339/TS2353 errors ('requiredPermissions' does not exist on type 'NamedListView'), and vitest on 7779 + 12341 was red with 7 failed / 230 passed. Restore: blob equals HEAD 76eef18c1220 and git diff HEAD is empty. The 12341 runtime cases stayed green under the ablation, as expected, because the zod faces already carried the key. eslint --no-inline-config on the 3 touched .ts files: 3 files, 0 errors, 27 pre-existing no-explicit-any warnings outside the diff. Root eslint.config.js has no parserOptions.project or projectService (not type-aware), so the diff cannot move any untouched file's verdict. Repo-wide pnpm lint is left to CI.",
      "gates": "pnpm check:phantom-deps 0 · check:self-import 0 · check:unreferenced-sources 0 · check:doc-example-readers 0 · check:handler-key-reads 0 · check:side-effects-array 0 · check:element-data-source-declaration 0 · check:spec-symbols 0 · check:action-forward-parity 0 · check:designer-field-key-parity 0 · check:icon-record-names 0 · check:i18n-keys 0 · check:i18n-drift 0 · check:i18n-designer-parity 0 · node scripts/check-changeset-fixed.mjs 0 · node scripts/check-changeset-presence.mjs 0 · check:spec-floors 1 (known on main: 'The scan collapsed: 0 package(s) declare @objectstack/spec', carried by objectui#12334, not touched) · check:doc-types not run (no docs changed) · check:nul-bytes has no script in objectui, so a control-byte grep over the 4 touched files was run instead: 0 hits. CI: in_progress, not awaited.",
      "files_changed": [
        "packages/types/src/objectql.ts",
        "packages/types/src/__tests__/object-view-unmirrored-keys-7779.test.ts",
        "packages/types/src/__tests__/list-view-required-permissions-12341.test.ts",
        ".changeset/12341-list-view-required-permissions.md"
      ],
      "deviations": "None against the dispatch. The landing face is NamedListView only, because the other two list-view faces already carried the key by reference (measured, stated in the PR body). Labels: zero writes; objectui has no label gate and the dispatch named no labels. The commit trailers use the AGENTS.md model-free pair (Claude-Session plus Co-authored-by: Claude), which takes precedence over the harness attribution reminder.",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay: pr_create (POST /repos/objectstack-ai/objectui/pulls + POST /issues/12360/assignees) via repository_dispatch to objectstack-ai/objectstack; this os-dev-report comment (POST /repos/objectstack-ai/objectui/issues/12341/comments). Plus git pushes of the branch (not REST).",
      "open_questions": [
        {
          "question": "Section 3: a D4-exempt caller (studio.access, manage_metadata, setup.access or isSystem) receives an object's listViews whole from /meta/object. The runtime console therefore lists and opens list views gated on capabilities that caller lacks, and no 403 occurs, because the server has no by-name item to refuse. This is not a data leak, since records still pass the caller's object read permissions. It is an audience mismatch at runtime. Should the server change?",
          "options": [
            "A: Leave it. D4 callers are schema editors; seeing every view at runtime is accepted. Cost: zero. The audience key is advisory for editors.",
            "B: objectstack prunes the plain runtime /meta/object read for D4 callers as well, and keeps the whole document only on the authoring doors (draft, layered, diff), mirroring the app arm's author-exempt split. Cost: a server change plus a check that Studio and the console designers load from an authoring door, so a save cannot delete withheld views. That save-back hazard is the reason D4 is exempt today.",
            "C: A client-side gate in the console. Refused by the card ruling and listed only for completeness."
          ],
          "recommendation": "A for now, B if a real deployment reports editors confused by foreign-audience views. Business need: no measured producer of the complaint yet. Long-term: B is the contract-first shape, if it is ever done. AI-error axis: neither A nor B lets an AI declare a gate the runtime ignores for ordinary users. Startup focus: no new capability without pull. Either way the fix is objectstack's and needs no objectui change."
        }
      ],
      "out_of_scope_findings": [
        "carrier: whoever next edits object-view-unmirrored-keys-7779.test.ts · the namedListViewMemberCount failure message still points at .changeset/object-view-unmirrored-keys-7779.md, which no longer exists (consumed at release); only its count was corrected here · noted in the PR's Acceptance notes, not filed"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12360 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T09:00Z

    Reviewed on GitHub at head 9e6cb65c00, against the card and triage's grade 6162030734, not against the dev's report.

    • Shape: the PR is a draft against main, and its body opens Fixes #12341 (the only closing keyword). Clause-②: yes matches the claim. The governed sweep reads NOT governed, 260 lines.
    • Contract review of record: 6164716741 on the PR, PASS at this head, with Served-tier: CONTRACT_REVIEW_TIER.
      • NamedListView gains requiredPermissions by reference to the spec. The other two list-view faces already carried it, and all three are pinned with accept and refuse cases.
      • @object-ui/types carries a minor changeset.
      • No client-side gate is added.
      • needs:contract-review is removed from the PR in the same stroke.
    • The PENDING pin from objectui#12030 is flipped, not duplicated: the server-enforced member moves to its own bucket in object-view-unmirrored-keys-7779.test.ts.
    • CI at head: all success or skipped, except the advisory Spec Main Shape Gate. Its annotations sit only on resolveDataSource.ts, useViewData.ts and .github, which is main's red (objectui#12325, PR fix: retire the view-level provider: 'api' readers (objectui#12325) #12361 in review). None is on a file this PR touches.
    • The card's one measurement, answered by the dev from code:
      • A D4-exempt viewer (studio.access, manage_metadata, setup.access, or a system object) receives an object's listViews whole from /meta/object. The console then offers and opens a view gated on capabilities that viewer lacks, and no 403 occurs.
      • Records still pass the viewer's object permissions, so no data leaks.
      • Decision: leave it. It is an audience mismatch for schema editors, with no measured complaint. A fix would be an objectstack server change, not objectui's, and the card forbids a client gate. No card is filed.
    • Not filed: the stale changeset pointer in a 7779 test message, left in the PR's Acceptance notes for whoever next edits that test.

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-14T09:18Z


    Generated by Claude Code

  7. added a commit that references this issue on Oct 28, 2026
    f2b17c6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions