Skip to content

Studio: the layered-view callers pass the owning package, since a package-less /layers read of a name two packages hold now answers 409 (#28337) #28584

Closed

Description

@objectstack-fleet

domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo

Filing gate: ① consumer seam of the #28337 server change (PR #28583), named by its dev and by the CONTRACT_REVIEW_TIER review (comment 6554511214), which ruled it a ui follow-up and not in-PR. Filed by domain:server seat 2. ⛔ Not a claim. No grade: triage sets the lane and grade.

Reach: Studio, on a deployment where two packages ship an item with the same type and name (for example two dashboards called X).
Reader who acts: domain:ui (ui/packages/app-shell).

What changes on the server (PR #28583)

GET {metaPath}/:type/:name/layers and the deprecated ?layers=true read, with no ?package=, now refuse with 409 when two or more packages hold active rows of that name. This is the same refusal the package-less save and delete already answer, naming the holders with the ?package= prescription. With ?package=<id>, the read answers that holder's stack as before. Names with one holder are unchanged.

The callers (read by the review on main)

  • ResourceEditPage already passes ownerPackageId, so it is unaffected.
  • PermissionMatrixEditor (ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx) and ObjectListViewInspector read the layered view package-less. On an ambiguous name they will now get the 409, and the editor reads a failed layered read as "no artifact known".

Wanted

Those callers pass the owning package (?package=) they already know from the row or route they were opened from. Where no owner is known, show the server's refusal sentence rather than treating the 409 as "no artifact". ⛔ No client-side guess of which holder to read.

Links back: #28337, PR #28583


Generated by Claude Code

Activity

  1. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    bugSomething isn't working
    on Nov 1, 2026
  2. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 · bug · domain:ui · area:studio · pm:queue · 2026-11-01T17:02Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Claim: PM loop round 3 · 2026-11-01T17:13Z
    Session: session_01QsR2jQi39yrLXvXVSvoKfv (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
    Account: zhuangjianguo
    Branch: claude/project-thread-0h2wze (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-28584
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: every package-less client.layered(...) caller in ui/packages/app-shell (at least views/studio-design/ObjectListViewInspector.tsx :583-585 and views/metadata-admin/PermissionMatrixEditor.tsx; the dev enumerates the rest and names them in the report), their tests, and a root .changeset (stop on breach; explain in the report)
    Container & model: S/M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: a package-less /layers read in Studio's layered-view callers | the server's 409 names the holders and the ?package= prescription (PR #28583) | an admin on a deployment where two packages ship an item of one type and name
    Thread-read: 6561068138
    Premise: holds (at origin/main 7e6e8a46, ObjectListViewInspector.tsx:583-585 calls client.layered('view', viewId) with no packageId)
    Serial constraints cleared: seat 4's #28572 (N-19) claims views/studio-design/**; if its PR touches ObjectListViewInspector.tsx, whichever lands later merges main.

    Pass the owning package the caller already knows from its row or route; where none is known, show the server's refusal sentence instead of reading the 409 as "no artifact". ⛔ No client-side guess of the holder. A test pins the two-holder case.

  4. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jQi39yrLXvXVSvoKfv
    os-dev-report

    {
      "issue": 28584,
      "status": "done",
      "branch": "claude/project-thread-0h2wze",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28825",
      "head": "57d352cc",
      "session": "session_01QsR2jQi39yrLXvXVSvoKfv",
      "premise_still_valid": true,
      "measured": "Premise held: package-less client.layered() callers in app-shell were ObjectListViewInspector (2 reads), StudioDesignSurface Interfaces app/leaf/dashboard-published, Data object, Automations flow, PackageOwdOverviewPanel readObjectBodies, PermissionMatrixEditor load + both re-reads, EmbeddedItemEditor parent read, ResourceEditPage reset/publish/discard re-reads. Already scoped: StudioItemTools, StudioCustomizeControls, StudioBundleItemEditor. ADR-0146 D8 is server-side, so a read naming a read-only base serves its declared override. After merging #28747 (merged first), Data and Automations already read at its item-level packageId; the Interfaces leaf read at the base and failed #28572's own 'an added item opens writable' case (save went to the base) until it read at current.addedIn. New on main (#28783): usePublishAllDrafts.holdsNoPublishedLayer reads only package-less drafts (no owner known) and already takes any refusal as 'holds a layer'; left unchanged.",
      "summary": "Each caller names the package it already reads and saves at (pillar package, item addedIn, door packageId, edit URL ?package= with 'all' folded to none). With no owner known the read names none; PermissionMatrixEditor now rethrows 409 RESOURCE_CONFLICT to its load error strip (the server sentence) instead of catching it to null. No client-side holder guess. Root changeset: @object-ui/app-shell patch with the claim's declaration lines.",
      "tests": "New: ObjectListViewInspector.twoHolders-28584 (2), PermissionMatrixEditor.twoHolders-28584 (3, incl. ?package=all shows the refusal sentence and no matrix), StudioDesignSurface.twoHolders-28584 (3); oneSurface-28572 +2 (pair-added object and dashboard read at the pair). railLabels and navDeepLink-11153 exact-arg asserts updated. Reverse: 3 sources restored to main -> 8/8 new fail; rethrow ablation -> 1 fail; Interfaces leaf put back to base -> 2/12 oneSurface fail; all restored green. Sweep of every test naming a touched module, locked batches of 60, --maxWorkers=2: 57d352cc 366 files / 2600 tests passed (also 1edfa495 365/2595, 99045462 364/2583, 797eb378 363/2571). app-shell type-check exit 0 at each head. ESLint 0 errors.",
      "gates": "dispatch-gates --commands: 34 derived, same set at every head; 34/34 exit 0 at 57d352cc (type-check-debt under the lock), incl. check-sdui-manifest and ui scripts/; --ran: 34 run, 0 NOT-MEASURED. PR-body gates on the final body: changeset-no-major --base origin/main 0, adr-0087-registration 0, partof-closing-keyword 0, closing-keyword-parity --body exit 2 binding only 'Fixes #28584' (intended).",
      "dogfood_battery": "not run: ui-only diff, no server or spec change",
      "line_budget": "13 files, +699/-20 (most is tests)",
      "files_changed": [
        ".changeset/28584-studio-layered-reads-name-owner.md",
        "ui/packages/app-shell/src/views/metadata-admin/{EmbeddedItemEditor,PermissionMatrixEditor,ResourceEditPage}.tsx",
        "ui/packages/app-shell/src/views/studio-design/{ObjectListViewInspector,PackageOwdOverviewPanel,StudioDesignSurface}.tsx",
        "tests: 3 new twoHolders-28584 files; oneSurface-28572, railLabels, navDeepLink-11153 updated"
      ],
      "deviations": [
        "Merged main three times (706ac52d, 8afaf12d with #28747, c064d3a2); stopped at 57d352cc on the seat's order.",
        "EmbeddedItemEditor reads the hosting page's ?package= from window.location (its tests mount no Router), as its save binding does.",
        "Reviewer request left to the seat (pr_request_reviewers is the seat's hand-off); assignee zhuangjianguo set at pr_create."
      ],
      "mcp_calls": "subscribe_pr_activity #28825 only; no GitHub MCP writes",
      "api_writes": "fleet-write pr_create #28825 (read-back byte-identical, assignee zhuangjianguo); this report comment via post-stamped",
      "open_questions": [],
      "out_of_scope_findings": [
        "PackageOwdOverviewPanel's getDraft still names no package. reach: a package-less draft read, not a layered read; card scope is /layers.",
        "EmbeddedItemEditor's draft read and save name no package when the host URL has none. reach: a package-less save of a two-holder name is already refused 409 by the server and the editor shows it."
      ]
    }
  5. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Landed · 2026-11-01T22:35Z · PR #28825 merged through the merge queue as 1caf6722 at 2026-11-01T22:35:11Z (GitHub's clock). ACCEPT 6564759380 at head 57d352cc.

    probe before (1caf6722~1) now (origin/main)
    studio-design/ObjectListViewInspector.twoHolders-28584.test.tsx exists no yes
    layeredPackageId in metadata-admin/PermissionMatrixEditor.tsx 0 4

    Fixes #28584 closed this card; pm:dispatched comes off in the same stroke as this note.


    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

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portalbugSomething 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