Repository navigation
fix(app-shell): Studio and Setup read an item's layered view at the package that owns it - #28825
Merged
Merged
Conversation
…wning package A layered read naming no package is refused 409 RESOURCE_CONFLICT for a name two packages hold. Each caller now names the package it already reads and saves at; where none is known, the server's refusal is the load's error. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jQi39yrLXvXVSvoKfv
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jQi39yrLXvXVSvoKfv
… tests Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jQi39yrLXvXVSvoKfv
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jQi39yrLXvXVSvoKfv
The Interfaces leaf baseline and the dashboard's published-layer read now name the leaf's owner: the pair for an item it adds, else this package. A test pins both pillars reading a pair-added item at the pair. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jQi39yrLXvXVSvoKfv
Contributor
Author
|
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu 席位核对 · ACCEPT · 2026-11-01T22:22ZHead-sha:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Steedos · project thread
Fixes #28584
Clause-②: no
Metadata-protocol: none
维护者速读
GET /meta/:type/:name/layers)的调用,现在都带上调用方本来就知道的所属包(?package=):Studio 各柱所在的包、权限矩阵的包门(packageId)、或编辑页 URL 上的?package=。实在不知道所属包时仍不带包,服务端的 409 拒绝原句作为加载错误显示;权限矩阵不再把这个 409 当成「没有这个权限集」。客户端不猜持有方。RESOURCE_CONFLICT拒绝。Studio 的列表视图检查器、Interfaces 的 app 与叶子、Data 的对象、Automations 的流程、包 OWD 总览、权限矩阵、嵌入条目编辑器,以及条目页的重置/发布/丢弃后的重读,都还在不带包地读,在这种部署上会加载失败或误判。ui/packages/app-shell的 6 个源文件(只是给已有的读取补第三个参数,外加权限矩阵对 409 的一处改判)和测试;服务端与 spec 零改动。只读基座上带基座包读,服务端按 ADR-0146 D8 返回其声明的.custom覆盖。回滚 = revert 本 PR。ui/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx的layeredPackageId与readLayered的.catch(唯一改变错误处理的地方);再看views/studio-design/ObjectListViewInspector.tsx的layeredAt。cd ui && pnpm exec vitest run packages/app-shell/src/views/studio-design/ObjectListViewInspector.twoHolders-28584.test.tsx packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.twoHolders-28584.test.tsx packages/app-shell/src/views/studio-design/StudioDesignSurface.twoHolders-28584.test.tsx packages/app-shell/src/views/studio-design/StudioDesignSurface.oneSurface-28572.test.tsx,应 4 个文件 20 个用例全部通过。What changes
Each package-less
client.layered(...)caller inui/packages/app-shellnow names the package it already reads and saves at:useObjectListViewDraft): the published layer, and the copilot-marks read beside a draft, at the hook'spackageId. On a read-only base that is the base, whose read serves its declared override (ADR-0146 D8,servedOverlayRowCandidates'servedOverride).packageId. The leaf's baseline, and the dashboard's published-layer read for served titles, at the leaf's owner:current.addedInfor an item the customization pair adds (Studio: a base and its <base>.custom as one surface — "customized" / "added" marks, "only customizations", the pair folded under its base, New lands in the pair #28572), elsepackageId(the effect now depends onleafPackageId).packageId(current.addedIn ?? railPackageIdsince Studio: a base and its <base>.custom as one surface — "customized" / "added" marks, "only customizations", the pair folded under its base, New lands in the pair #28572). Automations pillar: the flow's atdraftPackageId, and none when the pillar has no package.readObjectBodiestakes the panel'spackageId.layeredPackageIdis the door'spackageId, else the edit URL's?package=(all, the list's every-package scope, is not a package). The load, the package door's pre-save re-read and the environment door's post-save re-read all read there. With no owner known, a409 RESOURCE_CONFLICTfrom the load's read is rethrown to the load's error strip, which shows the server's sentence, instead of being caught tonull("no set known").?package=(read when the save runs, as that page's own save binding is).ResourceEditPage): the load already passedownerPackageId; the reset, publish and discard re-reads passed only the member, and now pass the same scope as the load.Unchanged:
StudioItemTools(every mount passes the pillar'spackageId) andStudioCustomizeControls(reads at the base) already named a package.usePublishAllDrafts'holdsNoPublishedLayer(new on main, #28783) reads only drafts that carry no package, so no owner is known; it already takes any refusal as "holds a layer", never as "no artifact", and writes no navigation entry for it. Where no owner is known (an item page with no?package=, an Automations pillar with no package, the embedded editor with none), the read still names none and every one of those callers already shows a thrown refusal's message as its error.Tests
ObjectListViewInspector.twoHolders-28584.test.tsx(new, 2): the real hook over a realMetadataClient, a server holding the view in two packages (the holder's stack with?package=, the 409 without). Open in each package: the one layered read names it, nothing is refused, the buffer holds that holder's view.PermissionMatrixEditor.twoHolders-28584.test.tsx(new, 3): the package door reads its own package's stack and shows its grants; the routed page reads the URL's owner and shows that holder's grants; with?package=allthe read names no package and the server's refusal sentence is shown, with no matrix rows.StudioDesignSurface.twoHolders-28584.test.tsx(new, 3): Interfaces (app and dashboard leaf, this package's nav), Automations (flow) and Data (object), each read at this package, none refused.StudioDesignSurface.oneSurface-28572.test.tsx(+2): on a read-only base, the pair's own object (Data) and dashboard (Interfaces) read their layers at the pair.StudioDesignSurface.railLabels.test.tsx,StudioDesignSurface.navDeepLink-11153.test.tsx: the exact-argument assertion on the app's layered read now includes{ packageId: PKG }.Reverse verification
ObjectListViewInspector.tsx,PermissionMatrixEditor.tsx,StudioDesignSurface.tsx) restored toorigin/mainwith the new tests in place: 3 files, 8 of 8 failed. Restored to HEAD (git diff HEADempty): 8 of 8 passed.scripts/ablation-replace.mjs, deleting the permission matrix's rethrow line: 1 failed (the no-owner case), 2 passed; restored, blob equal to HEAD.{ packageId }(the base) after the main merge:oneSurface-285722 of 12 failed (the new dashboard case, and Studio: a base and its <base>.custom as one surface — "customized" / "added" marks, "only customizations", the pair folded under its base, New lands in the pair #28572's "an added item opens writable", whose save went to the base); restored, 12 of 12 passed.Acceptance notes
409by the server, and both show that refusal; a package-less draft read is not this card.current.addedInwhen the pair adds the item. Without that, the merged branch failed Studio: a base and its <base>.custom as one surface — "customized" / "added" marks, "only customizations", the pair folded under its base, New lands in the pair #28572's own "an added item opens writable" case (its save went to the base).Verification
oneSurface-28572: 20 of 20 passed (--maxWorkers=2, underscripts/pm/os-verify-lock.sh).ObjectListViewInspector,PackageOwdOverviewPanel,PermissionMatrixEditor,EmbeddedItemEditor,MetadataDetailDrawer,ResourceEditPage, the three pillars,StudioDesignSurface, the metadata-admin index), in locked batches of 60: at57d352cc(main merged atc064d3a2; afterpnpm installand a rebuild of the console closure) 366 files, 2600 tests passed; at1edfa495(main at8afaf12d, which carries feat(studio): a read-only base and its customization pair as one surface #28747) 365 files, 2595; at99045462(main at706ac52d) 364 files, 2583; at797eb378, before any merge, 363 files, 2571. CI's Test UI runs the rest of app-shell.turbo run type-check --filter=@object-ui/app-shell: exit 0 at57d352cc,1edfa495,99045462(65 tasks) and797eb378.react-hooksadvisories).node scripts/pm/dispatch-gates.mjs --commands): 34 of 34 run, each exit 0 (check:type-check-debtunder the lock), includingnode scripts/check-sdui-manifest.mjsandpnpm --dir ui exec vitest run scripts/;--ranreconciles 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. Run at57d352cc(and earlier at1edfa495and99045462, each 34 of 34).🤖 Generated with Claude Code
https://claude.ai/code/session_01QsR2jQi39yrLXvXVSvoKfv