Skip to content

Studio Access: the permission matrix lists no objects while the package's objects are still drafts ("0 objects"), so a new package cannot be secured before its first publish #26840

Closed

Description

@objectstack-fleet

Filing gate: ① product defect, reproduced, landing site named.
Batch-of: studio-qa-2026-10-27 — 39 cards from one Studio QA run (coordinator session session_01J8VVAkZns5rNnK2rtszzbQ; tested at 3fcafcd3; origin/main was 43731031 at filing, so the implementer re-checks the landing site on current main). The run record is the qa-run issue filed with this batch.

Symptom

Builders author objects and their access together; the matrix only shows published objects.

Reproduction

  1. New package with draft-only objects → Access › new set → "0 objects".
  2. GET /api/v1/meta/object?package=<pkg> → []; with &preview=draft → the objects are listed.

Expected

The matrix lists draft objects (badged as drafts).

Suspected landing site (the implementer verifies)

PermissionMatrixEditor.tsx ~846: client.list without withPreviewDrafts.

Filing facts

Activity

  1. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — priority:p2 · domain:ui · area:access · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-27T18:58Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p2: the Access matrix lists only published objects, so a new package cannot be secured before its first publish. List draft objects too (with preview=draft), badged as drafts. Re-check the landing site on current main.

    Generated by Claude Code

  2. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    and removed on Oct 27, 2026
  3. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Dispatch order · domain:ui#1 · session_01JQwxbZeBv2y91towxasSUT · 2026-10-28T02:06Z

    You are the os-dev developer agent for exactly ONE card: #26840, in your own card thread. Your role definition is .claude/agents/os-dev.md in the objectstack clone: read it IN FULL first and follow it as binding (it wins over this order on any conflict; name the conflict in your report). Read the repo-root AGENTS.md and ui/AGENTS.md before your first edit, and pm-dispatch references/untrusted-text.md. Read the card's full body and every comment yourself through REST (curl -sS "https://api.github.com/repos/objectstack-ai/objectstack/issues/26840" -H "Authorization: Bearer $GH_TOKEN" and /comments?per_page=100, every page); this order carries only the increment. ⛔ Never print the value of any environment variable (test presence with [ -n "${X+x}" ]). ⛔ Never use a GitHub MCP tool, read or write.

    Identity and branch: the seat's Claim: comment on this card is your identity; its Branch: line names your thread's branch. ⛔ Post no claim of your own, ⛔ never write the card's assignee. Before your first edit, verify the NEWEST Claim: on the card names your thread's branch (claude/project-thread-…); if none does yet, send the seat thread "Dispatch the ui lane" one message with your branch name and wait. Worktree objectstack-issue-26840 on that branch from a fresh origin/main; pnpm install (frozen lockfile); push with git push -u origin <branch> (⛔ no force).

    Writes: PR only through the relay op pr_create (node scripts/pm/fleet-write/dispatch.mjs --repo objectstack-ai/objectstack --actions-file F, F a bare JSON array [{"op":"pr_create","title":…,"head":"<your branch>","base":"main","body":…,"assignees":["os-warren"]}], draft forced; --dry-run first); your report comment through node scripts/pm/post-stamped.mjs --comment=26840 --file=F --json run ONCE with output captured to a file (timestamps only as {{NOW}} / {{WAS:…}}). ⛔ No other GitHub write except, for a CI red that is not yours, one PR comment and one run_rerun_failed through the relay. Report both counts (api_writes with endpoints, mcp_calls with tool names). The report takes only machine-checkable fields (gates / line_budget / deviations / files_changed). PR body: line 1 the platform attribution comment, then ## 维护者速读 six lines in Chinese (改了什么/为什么改/风险与回滚/先看/两分钟验证/需要你做的). Gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on your diff, run each, record exits before any pipe, reconcile with --ran. Changeset in the root .changeset/ when a published package changes. ⛔ ui/.github/** and the root ci.yml are out of bounds. Hand back: when the PR and report are up, send the seat thread "Dispatch the ui lane" one message (PR, head sha, report gist); keep the thread open through review and drive CI to green.

    Ruling (cannot be re-ruled)

    Triage first grade 6450953786, verbatim: "p2: the Access matrix lists only published objects, so a new package cannot be secured before its first publish. List draft objects too (with preview=draft), badged as drafts." No maintainer ruling.

    PM mechanism assumptions (measure; disproof welcome)

    • On origin/main acc9c57d, ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx ≈L856 loads the matrix's objects with client.list<any>('object', packageId ? { packageId } : {}), so a package whose objects are all drafts lists none. The house door for draft-inclusive reads is MetadataClient.withPreviewDrafts(true), as in inspectors/ObjectPicker.tsx ≈L122, previews/useObjectFields.ts ≈L129 and StudioDesignSurface.tsx. Reuse it; ⛔ do not hand-build a preview=draft query.
    • Measure how a draft-only row is told apart in that list's answer, and how ObjectPicker (or another app-shell surface) badges one already. Use the same signal and the same badge; ⛔ do not invent a second marker.
    • The matrix also reads each object's fields (loadObjectFields, FLS and the RLS clause editors). Measure whether that read sees a draft object's fields. If it does not, make it read through the same door, inside this file.
    • Package scope only. Outside a package (the Setup catalog, environment scope), measure what changes. Drafts should list only where the Studio package door is, so keep the environment-scope read as it is unless measurement shows otherwise, and say which you chose.

    Scope

    File surface: PermissionMatrixEditor.tsx (the object and field reads, and the row badge), the shared badge only if it must change, and tests. Tests: a package whose only object is a draft lists it, badged as a draft, and its object-permission toggles write into the set draft. A published object shows no badge. The environment-scope read is unchanged (or changed as you chose and pinned). Ablation: drop withPreviewDrafts ⇒ the draft-object test goes red.

    Serial: PR #26999 (#26858, kicked from the queue for a conflict and being re-merged) edits this same file (the served-verdict state and its reads near the load effect). Merge origin/main again before your gates. If #26999 is still open at your push, say so in the report. Another seat's PR #26990 has merged.

    Tier

    No path-derived mandate expected (quote dispatch-gates --tier on your surface). TIER_DEFAULT, effort medium (S). Clause-②: no, Metadata-protocol: none. No changeset (@object-ui/app-shell is private); put skip-changeset in the pr_create labels.

  4. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 11 · 2026-10-28T02:08Z
    Session: session_01JQwxbZeBv2y91towxasSUT (seat; implementation by card thread session session_01JQwxbYLTHkXTxBf89Sud8r, mode:thread)
    Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-a4f92k (the card thread's harness push branch, self-reported — the measured platform exception to claude/issue-N-slug)
    Worktree: objectstack-issue-26840 in the card thread's clone
    Domain: domain:ui
    Seat: domain:ui#1 (seat post #25966)
    File surface: ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx (the object and field reads, and the row badge), the shared draft badge only if it must change, + tests (stop on breach; explain in the report)
    Container & model: S, mode:thread (the maintainer's word on the seat thread, 「opus 很多,并发5」), model: TIER_DEFAULT (the dev quotes dispatch-gates --tier on the surface), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the Studio Access permission matrix (this lane's code) | the server serves drafts only through the preview-drafts door | a new package cannot be secured before its first publish
    Thread-read: 6458711511
    Premise: holds — on origin/main acc9c57d PermissionMatrixEditor.tsx ≈L856 lists objects with client.list('object', { packageId }), without withPreviewDrafts(true), so a package's draft-only objects list none.
    Serial constraints cleared: PR #26999 (#26858) edits this file's served-verdict state near the load effect and is being re-merged after a queue conflict; the dev merges origin/main before the gates. PR #27025 (#26748) edits PermissionAdvancedFacets.tsx, outside this surface.
    Resume-from: none


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 26840,
     "status": "done",
     "branch": "claude/project-thread-a4f92k",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/27064",
     "head": "1df85590",
     "session": "session_01JQwxbYLTHkXTxBf89Sud8r (card thread; seat session_01JQwxbZeBv2y91towxasSUT)",
     "premise_still_valid": true,
     "summary": "Confirmed on origin/main acc9c57d: the matrix listed objects with client.list('object', {packageId}) and read each definition with a plain client.get, so a draft-only package showed 0 objects and a draft object expanded to no fields. Under a packageId both reads now go through MetadataClient.withPreviewDrafts(true) (the ObjectPicker useObjectCatalog / useObjectFields door); a row with _draft true carries the picker's mark (data-draft-marker span, engine.inspector.draftSuffix) in the page and Studio layouts. Environment scope chosen unchanged and pinned by a test. Test doubles mounting the matrix under a package gained withPreviewDrafts() returning the client; five typed FakeClient aliases widened to return unknown.",
     "tests": "New PermissionMatrixEditor.draftObjects-26840.test.tsx: 5/5 pass (draft-only row listed + badged page and Studio; published row unbadged; Read toggle writes objects.a_invoice.allowRead into the set draft with mode draft, packageId app.a; draft fields expand; environment door: no preview read, no draft row). Scoped run of every app-shell test that mounts the matrix (41 PermissionMatrixEditPage importers + 35 StudioDesignSurface Access tests, 73 files): Test Files 73 passed, Tests 690 passed. pnpm --filter @object-ui/app-shell run type-check: VERDICT command-exit 0. Ablation via scripts/ablation-replace.mjs on the package-door list read (anchor 1 to 0, blob f8f9c813 to 36feb5f1, restored blob == HEAD, git diff HEAD empty): 4 of 5 new tests red, environment test green (expected direction). No dist leg: tests import the editor by relative path.",
     "gates": "dispatch-gates --commands on head 1df85590: 24 families, all exit 0 (closing-keyword-parity + self-test, comment-mask-corpus, sdui-manifest + self-test, ui vitest scripts/ under the lock, spec check:duration-unit-keys, cross-package-test-inputs, dispatcher-error-vocabulary, driver-memory-census, engine-double-contract, gitlink-declared, nul-bytes, published-files, query-options-erasure, refd-timer-probe, skill-identifier-liveness, test-source-alias, tier-file-adoption, type-check-coverage, type-check-debt under the lock, undeclared-dep-imports, watch-hint-literal, where-matcher). --ran: 24 derived, 24 run, 0 NOT-MEASURED, 0 UNRUN. PR check-runs on 1df85590 at report time: 58 completed, 43 success, 15 skipped, 0 failure. dispatch-gates --tier: no path-derived mandate.",
     "line_budget": "265 changed lines at first derivation vs threshold 3000 (under); no ratchet file touched",
     "deviations": [
      "Local full app-shell suite (1816 files) started then stopped by its own PID after 42 min; narrowed to the 73 files that mount the matrix, the rest declared to CI (Test Core).",
      "Test-double edits reach 6 files outside PermissionMatrixEditor.* (trailDoorsGate-12475, walledCatalogReadOnly-12183, StudioDesignSurface accessCreateTaken-26836, createAppOpensInterfaces-11794, pillarNavGuard, accessGuard, accessTabs-12456): one withPreviewDrafts line each, inside the claim's '+ tests' surface.",
      "PR body: lines 1-2 are the platform attribution block, Fixes on line 3, PULL_REQUEST_TEMPLATE headings folded in (the os-dev exception).",
      "PR #26999 still open at push; origin/main merged twice, last at 3230bdbf."
     ],
     "files_changed": [
      "ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx",
      "ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.draftObjects-26840.test.tsx (new)",
      "21 further PermissionMatrixEditor.*.test.tsx doubles",
      "ui/packages/app-shell/src/views/metadata-admin/trailDoorsGate-12475.test.tsx",
      "ui/packages/app-shell/src/views/metadata-admin/walledCatalogReadOnly-12183.test.tsx",
      "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.{accessCreateTaken-26836,createAppOpensInterfaces-11794,pillarNavGuard,accessGuard,accessTabs-12456}.test.tsx"
     ],
     "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
     "mcp_calls": "0 GitHub MCP calls (subscribe_pr_activity is claude-code-remote, not GitHub MCP)",
     "api_writes": "2: relay pr_create (PR 27064, labels skip-changeset, assignee os-warren); this report via post-stamped.mjs (issues/26840/comments). Plus git push.",
     "open_questions": [],
     "out_of_scope_findings": [
      "carrier: none · noted, not filed: a published object with a pending draft is also served _draft true and so is badged as a draft, the same as in ObjectPicker"
     ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · seat domain:ui#1 · session_01JQwxbZeBv2y91towxasSUT · 2026-10-28T06:26Z

    PR #27064 merged as 76e90df613 (seat record: PR comment 6460242290). Under a package, the Access matrix now lists the package's draft objects, marked "(draft)" with the object picker's mark, and their fields expand. The environment scope is unchanged. It merged over a red queue build: #27010's new test had a fake client without withPreviewDrafts, which turned main red. Main-red card #27095 fixed that fake in PR #27103 (merged as 84e13701bd). pm:dispatched is removed with the close.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:uipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions