Repository navigation
feat(cli)!: kind:'react' pages are off unless the deployment turns them on - #25789
Conversation
…m on WIP: console serving reads OS_PAGE_REACT_ENABLED (legacy OS_PAGE_REACT), defaults the tier off, and writes the capability global in both directions. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
…e opt-in Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
… default Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
… by default Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
📓 Docs Drift CheckThis PR changes 2 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 151 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 10fd61e0704ba33b718493556db0cf47ff768d52 && git checkout 10fd61e0704ba33b718493556db0cf47ff768d52
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e2a4b6a06315959625748b44ed91b1f9731c67ee 3d66e796cb1f06767d75fea87de9587f5762bff7 && git checkout -B drift-repro e2a4b6a06315959625748b44ed91b1f9731c67ee && git merge --no-ff 3d66e796cb1f06767d75fea87de9587f5762bff7
node scripts/docs-audit/affected-docs.mjs --json e2a4b6a06315959625748b44ed91b1f9731c67ee
|
|
Full dogfood on head
Generated by Claude Code |
… only `utils/console.ts` is behind the published `./console` subpath, which the packed-tarball pin runs with no other package installed, so the import of `@objectstack/types` failed there with ERR_MODULE_NOT_FOUND. The legacy `OS_PAGE_REACT` fallback is now spelled in the module, and its deprecation warning goes through the plugin logger once. The reader and its constants are no longer exported, so the module's export census is unchanged. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
…translation/flows.screens row The same ledger edit as #25751, carried here because `check:liveness` and `check-liveness.test.ts` are red on main for every PR that reaches packages/spec. The hunk is identical, so either landing order merges clean. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
|
CI on e6df92d, and what 87ff23f changes:
Generated by Claude Code |
main's #25796 rewrote the `translation/flows.screens` evidence to cite the seam modules, superseding the ledger hunk this branch carried from #25751; the conflict resolves to main's row, so this branch no longer touches the ledger. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc
…on (#13526) <!-- claude-projects-attribution: {"github_login":"os-tesla"} --> _Requested by **Tesla** · [project thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6JaoBY54KcuzDWcTYXW18gG3bJ)_ ## What changes The `react-pages` capability in `@object-ui/core` (it gates `kind: 'react'` pages, whose source runs in the application with no sandbox) now defaults to **off**. A host turns it on explicitly. - `packages/core/src/runtime/capabilities.ts`: the default flips to `false`. The two page globals keep their meaning: `__OBJECTUI_CAPABILITIES__` turns a capability on, `__OBJECTUI_CAPABILITIES_DISABLED__` turns it off and wins over a stale enable list. - `ReactKindPage` (`packages/components/src/renderers/layout/react-page.tsx`) already drew a named notice instead of a blank page while the capability is off. Its text now says the tier is off unless the deployment turns it on and names the switch, `OS_PAGE_REACT_ENABLED=true` (or `enableCapability('react-pages')` for a host that embeds the renderer). The title "React pages are disabled on this deployment" is unchanged. - Studio's new-page dialog (`offeredPageSourceKinds`) already offered `react` only while the capability is on; only its comment changes. - `apps/console/src/sdui-workbench-preview.tsx` (a dev preview harness) now sets the enable global itself, the way the server does, and `?disable=1` leaves it unset. - `content/docs/guide/react-pages.md`: the security-gate section states the new default and how the server and an embedding host turn it on. ## Landing order The ObjectStack server half is #25789: it reads `OS_PAGE_REACT_ENABLED` and writes the enable global when on and the disable global when off, so the Console follows the server whichever default its build carries. Land that first. After it, this PR changes nothing a server-hosted Console does; it changes the default for a host that embeds the renderer without saying either way, and for a Console served by an older server, where react pages stay off until the server is upgraded. This PR does not move `.objectstack-sha`: nothing here reads an objectstack symbol the current pin lacks, and the pin move before the merge window is already in flight on its own card. ## Known side effect until a follow-up lands With the tier off, the server's content-security-policy refuses `eval`, and zod's one-time `eval` probe at Console boot is reported as one violation per load (nothing breaks). objectui#13511 sets zod `jitless` in the Console boot and removes it. ## Tests - New `packages/components/src/__tests__/react-page-capability-gate.test.tsx`: a real react page through the real `type: 'home'` PageRenderer draws the notice naming `OS_PAGE_REACT_ENABLED=true` by default and never runs its source; with the capability enabled the same source runs; disabled again, it is closed. - `packages/core/src/runtime/__tests__/capabilities.test.ts`, rewritten to load a fresh module per case (the default is only observable before any override): default off; the enable global turns it on; the disable global wins over an enable list; host enable and disable; unknown capabilities off. - Nine test files that render react pages relied on the old default and now enable the capability at module scope: `react-page-adapter`, `react-page-content-identity`, `react-page-invalidation`, `react-page-scope`, `react-page-state` (components), `interfaceCreate` and `StudioDesignSurface.interfacesCreatePage-11823` (app-shell), `ListView.objectProviderBinding-7477` (plugin-list), `sdui-workbench-preview-listview-binding-8510` (console). Measured: before the opt-in those nine files failed (27 tests) and nothing else failed, in a run of 695 files across core runtime, components, app-shell studio-design and previews, console, and the two plugin files. - After: `pnpm exec vitest run packages/core/src/runtime/ packages/components/src/__tests__/react-page …` (the eleven files above plus the gate test) → `Test Files 11 passed (11)`, `Tests 73 passed (73)`. - Ablation: with the default put back to `true`, the default-off cases in the gate test and the capabilities test go red (2 failed, 6 passed); restored, `git diff HEAD` is empty. - `turbo run type-check --filter=@object-ui/core --filter=@object-ui/components` → 10/10 tasks. `turbo run type-check --filter=@object-ui/app-shell --filter=@object-ui/plugin-list --filter=@object-ui/console` → 38/38 tasks. Head `f2792aa`. - `eslint --no-inline-config` on every changed `.ts`/`.tsx` → 0 errors. `check-changeset-presence`, `check-changeset-no-major`, `check:new-line-citations`, `check:control-bytes` → exit 0. `check-governed-queue-guard --test` on the file list → NOT GOVERNED. ## Changeset `.changeset/react-pages-default-off.md`: `minor` for `@object-ui/core`, `@object-ui/components`, `@object-ui/app-shell`, `@object-ui/console` (a published default changes; `minor` under this repository's version policy), with the FROM → TO for an embedding host. --- _Generated by [Claude Code](https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: os-zhuang <jack@objectstack.ai>
…1, WIP) Brings the branch up to main abebc4e for the cutover sitting. Clean merge; main's #25789 (cli console.ts), #25757 (spec vitest.repo-tests.json) and #25780 (dispatch-gates) overlap files this PR touches and are re-checked after it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0149BHSXfCdQywGaLdpRAtWe
Requested by Tesla · project thread
Clause-②: no
Metadata-protocol: none
What changes
The
kind:'react'page tier, whose page source runs in the Console with no sandbox, is now off unless the deployment turns it on. ADR-0081 is amended to match.packages/cli/src/utils/console.tsreadsreadReactPagesTier()once per Console document. It is on forOS_PAGE_REACT_ENABLED=true(also1,on,yes,enabled) and off when the variable is unset orfalse,0,off,no,disabled. Any other value leaves it off and logs one warning naming the variable and the accepted values. The earlier name,OS_PAGE_REACT, is still read throughreadEnvWithDeprecationwhile the new one is unset, with its one-time deprecation warning. The new name follows theOS_{DOMAIN}_{FEATURE}_ENABLEDrule for an opt-in flag (AGENTS.md Prime Directive 9).__OBJECTUI_CAPABILITIES__) when on, the disable list when off. So the served Console follows the server's setting whichever default its build carries. That makes this PR safe to land before the objectui half, which flips the renderer's own default.'unsafe-eval'stays tied to the same per-document read (unchanged logic from the nonce-CSP change), so by default the Console document refuseseval.examples/app-showcase/.envsetsOS_PAGE_REACT_ENABLED=true.os dev,os serveandos startload that file from the project root (dotenv-flow), sopnpm dev, the showcase smoke andos startin that example keep running its three react pages.content/docs/ui/react-pages.mdx,content/docs/ui/pages.mdx,content/docs/protocol/objectui/layout-dsl.mdx, thePageSchema.kinddescription inpackages/spec(and the regeneratedcontent/docs/references/ui/page.mdx), the published skill ruleskills/objectstack-ui/rules/pages.md, and the platform-checklist itemstudio-authoringfor the react tier (revision 4) all state the new default and switch.Landing order
react-pagesdefault flips to off in@object-ui/coreand the disabled notice namesOS_PAGE_REACT_ENABLED=true(separate draft PR, linked from the thread).Known side effect until a follow-up lands
With the tier off, the Console's schema library probes for
evalonce at boot and falls back without it. Under this policy that probe is refused, so a browser that reports content-security-policy violations logs onescript-srceval refusal per Console load. Nothing on the page is affected. Before this PR that happened only on deployments that setOS_PAGE_REACT=off; after it, on every deployment that leaves the tier off. objectui#13511 removes the probe (one line in the Console boot). The changeset says this to operators.Tests
Run on head
e6df92d2:pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 src/utils/console→Test Files 7 passed (7),Tests 142 passed (142).console.content-security-policy.test.ts(real plugin on a real Hono app): default document refuses'unsafe-eval'and carries the disable global under the nonce;OS_PAGE_REACT_ENABLED=trueallows it and carries the enable global; legacyOS_PAGE_REACT=on/offin both directions; the new name wins over the legacy one; an unrecognized value stays off and warns exactly once over two documents.console.branded-head.test.ts: the served-unchanged shell now includes the capability script (off by default).pnpm --filter @objectstack/spec check:generated:check:docsregenerated (content/docs/references/ui/page.mdx).check:livenessis red on the base commit too, fortranslation/flows.screens(a citation this PR does not touch).Derived gates (
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 130 families,--ranreconciles all 130):check-plugin-teardown-shape --self-test,check:skill-examples,check:i18n,check:i18n-walk-parity,check:type-check-debt.check:liveness(andcheck:generated, which reports only that row) exit 1 ontranslation/flows.screens. The same command on the base commitf0cf33833exits 1 with the same row.check:i18n-coverageandcheck:dual-build-cjs-loadsNOT MEASURED locally: both need a full workspace build. CI runs them.Ablation: with
readReactPagesTierreturning on for an unset value, four cases inconsole.content-security-policy.test.tsgo red; restored,git diff HEADis empty.Full dogfood (title carries
!): in progress one6df92d2; the result goes in a comment.Governed surfaces
This diff touches
docs/adr/0081-trusted-react-page-tier.mdandskills/objectstack-ui/rules/pages.md, so it is Tier H and stays in draft for an authorized approval. ADR-0081's decision named the old default, so the default does not move without the amendment (Prime Directive 13).skills/**readings:skills/objectstack-ui/rules/pages.md428 → 428 lines; allskills/**/SKILL.mdtogether 4383 → 4383 lines (unchanged; the edit rewords three lines in place).维护者速读(草稿)
kind:'react'页面(页面源码在 Console 里直接执行、无沙箱)从「默认开」改为「默认关」。部署方设OS_PAGE_REACT_ENABLED=true才开;旧变量OS_PAGE_REACT=on/off仍可用(带一次弃用提示)。服务端把开/关两个方向都写进 Console 文档,CSP 的'unsafe-eval'跟随同一开关。app-showcase 用自己的.env显式开启。ADR-0081 加修订说明。OS_PAGE_REACT_ENABLED=true(changeset 写明迁移)。默认关时,每次加载 Console 会多一条 zod 的 eval 探测 CSP 违规上报,不影响页面,objectui#13511 消除。回滚:revert 本 PR,或部署侧设该变量。Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01X4d6XVfcfxL17bMpptytcc