Repository navigation
Commit 5e7cf63
feat(cli)!: kind:'react' pages are off unless the deployment turns them on (#25789)
<!-- claude-projects-attribution: {"github_login":"os-tesla"} -->
_Requested by **Tesla** · [project
thread](https://claude.ai/code/project/chan_01AXsQkLFKRdQCqQ3RTr6Jao?thread=cmsg_01AXsQkLFKRdQCqQ3RTr6JaoBY54KcuzDWcTYXW18gG3bJ)_
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.
- **The switch.** `packages/cli/src/utils/console.ts` reads
`readReactPagesTier()` once per Console document. It is on for
`OS_PAGE_REACT_ENABLED=true` (also `1`, `on`, `yes`, `enabled`) and off
when the variable is unset or `false`, `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
through `readEnvWithDeprecation` while the new one is unset, with its
one-time deprecation warning. The new name follows the
`OS_{DOMAIN}_{FEATURE}_ENABLED` rule for an opt-in flag (AGENTS.md Prime
Directive 9).
- **What the document carries.** The server now writes the Console's
capability global in both directions: the enable list
(`__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.
- **The content-security-policy.** `'unsafe-eval'` stays tied to the
same per-document read (unchanged logic from the nonce-CSP change), so
by default the Console document refuses `eval`.
- **app-showcase opts in.** `examples/app-showcase/.env` sets
`OS_PAGE_REACT_ENABLED=true`. `os dev`, `os serve` and `os start` load
that file from the project root (dotenv-flow), so `pnpm dev`, the
showcase smoke and `os start` in that example keep running its three
react pages.
- **Docs and contract text.** `content/docs/ui/react-pages.mdx`,
`content/docs/ui/pages.mdx`,
`content/docs/protocol/objectui/layout-dsl.mdx`, the `PageSchema.kind`
description in `packages/spec` (and the regenerated
`content/docs/references/ui/page.mdx`), the published skill rule
`skills/objectstack-ui/rules/pages.md`, and the platform-checklist item
`studio-authoring` for the react tier (revision 4) all state the new
default and switch.
- **ADR-0081 amendment.** Status line and an amendment block: decision 3
/ TL;DR 4 are superseded on the default only; the tier, the gate and its
host-only control stand.
## Landing order
1. This PR (server side). With it merged, a deployment's setting
decides, against the Console build objectstack currently pins and
against the next one.
2. objectui: the `react-pages` default flips to off in `@object-ui/core`
and the disabled notice names `OS_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 `eval` once
at boot and falls back without it. Under this policy that probe is
refused, so a browser that reports content-security-policy violations
logs one `script-src` eval refusal per Console load. Nothing on the page
is affected. Before this PR that happened only on deployments that set
`OS_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=true` allows it and
carries the enable global; legacy `OS_PAGE_REACT=on` / `off` in 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:docs`
regenerated (`content/docs/references/ui/page.mdx`). `check:liveness` is
red on the base commit too, for `translation/flows.screens` (a citation
this PR does not touch).
Derived gates (`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`, 130 families, `--ran` reconciles all 130):
- 126 exit 0, five of them after building the prerequisite they named
(cli and client-react dists, the pinned teardown control commit):
`check-plugin-teardown-shape --self-test`, `check:skill-examples`,
`check:i18n`, `check:i18n-walk-parity`, `check:type-check-debt`.
- `check:liveness` (and `check:generated`, which reports only that row)
exit 1 on `translation/flows.screens`. The same command on the base
commit `f0cf33833` exits 1 with the same row.
- `check:i18n-coverage` and `check:dual-build-cjs-loads` NOT MEASURED
locally: both need a full workspace build. CI runs them.
Ablation: with `readReactPagesTier` returning on for an unset value,
four cases in `console.content-security-policy.test.ts` go red;
restored, `git diff HEAD` is empty.
Full dogfood (title carries `!`): in progress on `e6df92d2`; the result
goes in a comment.
## Governed surfaces
This diff touches `docs/adr/0081-trusted-react-page-tier.md` and
`skills/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.md` 428 → 428
lines; all `skills/**/SKILL.md` together 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 加修订说明。
- **为什么改**:作者是否可信是每个部署自己的判断,平台默认不应替所有部署做这个判断;默认关、显式开,把这个决定交给运维方。
- **风险与代价(含回滚)**:已在用 react 页面的部署升级后,这些页面显示「已禁用」提示,直到设置
`OS_PAGE_REACT_ENABLED=true`(changeset 写明迁移)。默认关时,每次加载 Console 会多一条 zod
的 eval 探测 CSP 违规上报,不影响页面,objectui#13511 消除。回滚:revert 本 PR,或部署侧设该变量。
- **席位意见**:
- **你要做的**:审阅并批准本 PR(受管面:ADR 与 skills),然后看 objectui 那半的 draft PR。
---
_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>1 parent f2a870e commit 5e7cf63
13 files changed
Lines changed: 231 additions & 74 deletions
File tree
- .changeset
- content/docs
- protocol/objectui
- references/ui
- ui
- docs
- adr
- qa/platform-checklist/areas
- examples/app-showcase
- packages
- cli/src/utils
- spec/src/ui
- skills/objectstack-ui/rules
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
43 | | - | |
44 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
215 | 215 | | |
216 | 216 | | |
217 | 217 | | |
218 | | - | |
| 218 | + | |
219 | 219 | | |
220 | 220 | | |
221 | 221 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
111 | | - | |
112 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
113 | 114 | | |
114 | 115 | | |
115 | 116 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
62 | | - | |
63 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
64 | 64 | | |
65 | | - | |
| 65 | + | |
66 | 66 | | |
67 | 67 | | |
68 | | - | |
| 68 | + | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
75 | 82 | | |
76 | 83 | | |
77 | 84 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| |||
0 commit comments