Skip to content

feat(console): an admin can open a read-only package's app in Studio to look at it - #28076

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-9nt6x7
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-9nt6x7

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

维护者速读

  • 改了什么:只读软件包(代码包或已安装包,例如 HotCRM)的应用,管理员现在在顶栏能看到一个眼睛按钮「Open app in Studio」,在应用切换器里能看到「在 Studio 中查看 {app}」,打开的是 Studio 的只读浏览;可写包仍是铅笔「Edit」。
  • 为什么改:Setup and Studio: suggestions from a full HotCRM browser pass on 18.2.0: user onboarding, packaged automation state, run-now for scheduled flows, admin lists, and Studio entry, field table, flow inspector wording and one designer per item #27356 第 12 行,按你的裁决 B(评论 6520616687):「ai写完代码,人类需要进去确认啊」。objectui#12615 的理由只排除铅笔,不排除入口。
  • 风险与回滚:只多画一个入口,不放开任何写权限;同一批管理员、同一道门;内核包、清单里没有的包、清单未读到时仍什么都不画。回滚就是 revert 本 PR。
  • 先看:hooks/useStudioDesignGate.ts 的 useStudioEntryGate(同一次 writable 读出 edit / view 两种姿态),AppHeader.tsx 顶栏按钮,AppSwitcher.tsx 的 Studio 行。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/layout/__tests__/AppHeader.editAppFollowsPackagePosture-12615.test.tsx packages/app-shell/src/layout/__tests__/AppSwitcher.homeMenu-12605.test.tsx,应见 2 files passed。
  • 需要你做的:无,席位落地。

Part of #27356 (row 12, hotcrm#2320 Studio S1: a read-only package's app opens in Studio to look at it; maintainer-ruled B, comment 6520616687)
Clause-②: no
Metadata-protocol: none

What changes

  • The gate answers a posture. useStudioEntryGate(path) (new, hooks/useStudioDesignGate.ts) reads the same two halves as before (a workspace admin holding manage_metadata; the package as Studio's package list carries it) and answers { path, posture }: edit for a package the list carries writable, view for one it carries read-only, null otherwise. The posture comes from the server's writable verdict read once, in packageStudioPosture; no second derivation. useStudioDesignGate is now the edit half of that answer, so the sidebar ⋯ menu's Design entry and a page's Edit in studio pencil are unchanged.
  • App bar. edit keeps the pencil, 「Edit app」. view draws an eye in the same slot, 「Open app in Studio」 (data-testid="app-view-in-studio-button"), to the same Studio path, which Studio opens in its read-only posture.
  • App switcher. A new studioPosture prop (default edit): view turns the last row into 「Open APP in Studio」 with an eye (app-switcher-view-in-studio); edit keeps 「Edit APP in Studio」 with the pencil.
  • Kernel packages still draw nothing. A manifest-scoped kernel package is already left out of the list. A kernel package the registry half serves flat (its scope top level) stays in the list read-only, because the list's visibility filter reads the manifest's scope only; parsePackages now marks such a row kernel: true (visibility unchanged), and the gate answers null for it. Without this the Setup app would have got the eye.
  • i18n. Two keys added in all ten locales: topbar.openAppInStudio (en 「Open app in Studio」, zh 「在 Studio 中查看应用」) and layout.appSwitcher.openAppInStudio (en 「Open {{app}} in Studio」, zh 「在 Studio 中查看 {{app}}」). No key renamed, no en value changed.
  • The surface grew, as the ruling grants, by layout/** and hooks/**; none of the files open PRs hold (UnifiedSidebar.tsx, ConsoleLayout.tsx and the rest of the seat's list) is touched. views/studio-design/packages-io.ts is in the order's Studio surface.

Tests

  • AppHeader.editAppFollowsPackagePosture-12615.test.tsx (real AppHeader, router and MePermissionsProvider, packages served at fetch): its reading now carries the eye and the switcher's posture too. The read-only package (HotCRM, writable: false) case changes from "nothing" to "no pencil, the eye to /studio/app.objectstack.hotcrm/interfaces?surface=dashboard:pipeline, the switcher row to the same target in view, named 「Open app in Studio」". The writable CONTROL reads the pencil with posture edit and no eye. Setup, the unlisted package, the flat-served system package, the in-flight read and the failed read each read no pencil, no eye and no switcher row.
  • AppSwitcher.homeMenu-12605.test.tsx gains two cases: view draws 「Open HotCRM in Studio」 with the eye glyph and no Edit row; edit keeps 「Edit HotCRM in Studio」 with the pencil (the file's first case already reads the row with no posture passed).
Readings (head 6f086f6, branch rebuilt from origin/main bc496bf after #27978 merged; install and app-shell closure rebuilt)
  • The two pinned files: 2 passed.
  • Every ui test file naming useStudioDesignGate, AppHeader, AppSwitcher, SidebarItemMenu, parsePackages, fetchPackages or packages-io, plus the whole packages/i18n/: 326 files, 3011 passed / 13 skipped.
  • pnpm --filter @object-ui/app-shell --filter @object-ui/i18n run type-check: exit 0 (lock VERDICT command-exit 0).
  • Ablation 1, through scripts/ablation-replace.mjs: return pkg.writable ? 'edit' : 'view'; to ... : null (the read-only package gets nothing, as before): 1 failed / 8 passed (the HotCRM case red); restored blob = HEAD blob df9f158d1490, git diff HEAD empty.
  • Ablation 2: if (!pkg || pkg.kernel) return null; to if (!pkg) return null; (the flat-served kernel row gets the eye): 1 failed / 8 passed (the flat system package case red); restored, git diff HEAD empty.
  • vitest resolves @object-ui/* to source, so neither ablation needed a rebuild.
  • pnpm --dir ui run check:i18n-drift: 0 en values changed (2 keys added, all ten packs).

Acceptance notes

  • Row 14 is answered C (will not do), per the ruling. The Data pillar's grid columns, its Form canvas and the one field inspector are the object's field designer; objectui#5813 ("fields ARE the grid's columns, so a separate fields tab would ADD a surface") and the seven-tab ruling of objectui#12450 (decision B of objectui#12446) stand. No change for row 14.
  • Row 19 (Delete flow in Studio, ruled A1) follows as its own PR after this one.
  • The eye opens Studio where the pencil would have (appStudioRoutePath's deep link). Studio's own read-only posture (row 13, fix(studio): the read-only header offers an overlay only for a type that takes one #27927) is what the viewer then sees; this PR promises a look, not an edit, and the server's write gate is unchanged.
  • The kernel mark reads a flat row's top-level scope, the position the registry half serves; it changes no visibility. Whether a real server serves Setup flat was not measured here; the existing pin says it does.

Verification

On head 6f086f63: dispatch-gates --commands derived 34 families for this diff; all 34 were run locally, each exit 0, and --ran reconciled 34 run, 0 NOT-MEASURED, 0 UNRUN. check:new-line-citations: 0 new. CI check-runs were in progress when this was opened.


Generated by Claude Code

…to look at it

The app bar and the app switcher drew their Studio entry only for a writable
package's app. useStudioEntryGate answers the same gate with a posture: edit
for a writable package (the pencil, unchanged), view for a read-only one (an
eye, "Open app in Studio"). Kernel packages, including a flat-served kernel
row, an unlisted package and an unread list draw neither. useStudioDesignGate
is the edit half, so the sidebar Design entry and a page's pencil are as
before. Two keys added in all ten locales.

Claude-Session: https://claude.ai/code/session_01Utp6CZrsFMFmWFsxTaq2Bu
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 30, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

席位核对

ACCEPT · head 6f086f6300f5a5a7419ec49cc8c28e682ffa3717 · 2026-10-30T11:59Z

  • Shape: draft → main, Part of #27356 (row 12; row 19 follows in its own PR, so the card stays open). Clause-②: no and Metadata-protocol: none match the claim. The change is @object-ui/app-shell plus i18n only, so no contract review is owed.
  • Ruling held (6520616687, B): useStudioEntryGate answers { path, posture } from the single writable read. useStudioDesignGate is now its edit half, so the sidebar Design entry and the page pencil are unchanged, and nothing derives writable a second time. On a read-only package, the app bar shows an eye with "Open app in Studio" and the switcher shows "Open {app} in Studio", both pointing at the same target, for the same admins behind the same gate. A writable package keeps the pencil and "Edit". A kernel package and an unread list still draw nothing.
  • Kernel guard: the registry serves a kernel package (Setup) with its scope flat at the top level, and the list reads only the manifest's scope. parsePackages now marks that row kernel: true without changing its visibility, and the gate answers null for it. Dropping the guard turns the existing objectui#12615 flat-shape pin red, which is how the gap was found.
  • Tests: 326 files (3011 passed). There are two ablations, view → null and the kernel guard dropped; each gives 1 failed / 8 passed and was restored. Type-check passes for app-shell and i18n. check:i18n-drift reports 0 en changes; the 2 new keys are in all ten packs.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure; mergeable_state clean. 34/34 derived gates exit 0 locally. check-governed-merges --pr 28076: NOT governed, 272 changed lines.
  • Accepted deviations: layout/** and hooks/** are granted by the ruling and the claim addendum (6520664956). views/studio-design/packages-io.ts is inside the claimed Studio surface. None of the held files are touched.
  • Row 14 (C): answered "will not do" in the Acceptance notes, citing objectui#5813 and Once #11999 lands, a GREEN test in packages/rest asserts a rationale that is no longer true — plus the projectResolution omit it was written to justify #12450.
  • Landing: non-governed, all checks green, mergeable_state clean ⇒ the seat lands it (pr_ready + automerge_enable).

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 12:00
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 6b125a7 Oct 30, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-9nt6x7 branch October 30, 2026 12:24
os-bill added a commit that referenced this pull request Oct 30, 2026
M1: name the ADR-0126 §9 first-bullet lift (badge, customization list,
revert on served facts; diff-vs-base and the upgrade skip-report stay
deferred; clone provenance untouched) and stop saying §9 "stands in
full". S1: state the ADR-0070 D3 amendment for the paired case. S2: own
the greyed-with-source presentation; cite ADR-0029 D7 for the
contribution only. S3: correct the Context readings (directory hides
field/package and shows the active package's types; dataset has a
create dialog, no designer; the charter sentence is the file's doc
comment; queue membership has no Setup section at this head, ADR-0142).
S4: reachable provenance (ruling record 6520616687; the D1–D3 quotes
have no GitHub record), restore the verbatim quote and mark the
editorial note. S5: the ledger switch's authority and its disabled
shape under a walled posture. S6: cite ADR-0141. S8: export "as
ADR-0070 D4 lands". Note #28076 landing D5 ahead of the record.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CaRN6wdrRyLKJSCMYH
os-bill added a commit that referenced this pull request Oct 30, 2026
S9: the paired package is exported, duplicated and deleted as any
writable package is; the export door is on the runtime route ledger.
S10: the ledger switch's disabled shape reads the two served posture
facts the walled catalog doors read; no client copy of the gate's
sentence; "naming the platform operator". S11: D4's quote is on the
card in part, D5 and D6 in full. S12: #28076 merged; ADR-0141 marked
Proposed with its mechanisms on main; "the row-20 cards"; the create
door sets the base's namespace explicitly.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CaRN6wdrRyLKJSCMYH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant