Repository navigation
fix(cli,rest)!: os package install takes -u/--url and -t/--token; the /meta permission refusal is localized - #30792
Conversation
-r/--runtime is retired with no alias; --url keeps OS_RUNTIME_URL, and --token (OS_RUNTIME_TOKEN) sends a bearer token instead of signing in with --email/--password. Docs and scaffold templates follow. Claude-Session: https://claude.ai/code/session_016WV4cxrNurGFU9PsE6NwNT Co-authored-by: Claude <noreply@anthropic.com>
…'s locale An app, dashboard or list view the caller may not open is refused with the operation catalog's permission_denied sentence in ExecutionContext.locale, as plugin-security's refusals are; REST hands in the errors.* override lookup. Adds the changeset for both halves of this change. Claude-Session: https://claude.ai/code/session_016WV4cxrNurGFU9PsE6NwNT Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4cxrNurGFU9PsE6NwNT Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 4 package(s): 23 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 9 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 51 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 e7a773d00ccaef5e6816046e132a7db30420efa4 && git checkout e7a773d00ccaef5e6816046e132a7db30420efa4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 612468cc20e4d4adeba047d2416126ec9a8cc077 6a2119cc920c077d610923e9fa7dceece3005f50 && git checkout -B drift-repro 612468cc20e4d4adeba047d2416126ec9a8cc077 && git merge --no-ff 6a2119cc920c077d610923e9fa7dceece3005f50
node scripts/docs-audit/affected-docs.mjs --json 612468cc20e4d4adeba047d2416126ec9a8cc077
|
|
domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4 Contract review for card #30126 (rows 12, 13) · narrowing face ( Contract reviewServed-tier: ① Derived judgments
② Semver levelThe changeset names ③ Boundary flags
④ Design judgmentThe narrowing. It takes away exactly the declared Attempts to break it:
Findings: none must-fix. Should-fix, all as follow-ups:
Check-runs at review time: no failure. Several jobs were still in progress; Implemented-by: VERDICT: PASS |
|
domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4 维护者速读
席位意见:ACCEPT(#30126 第 12、13 行)。 席位核对Head-sha:
|
|
domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4 Maintainer's per-PR word (BREAKING) · 2026-11-06T03:50Z Elon: 「同意」, in the #30126 card thread, 2026-11-06T03:50:14Z, for this PR at head |
Requested by Elon · project thread
domain:server#4 · os-elon-musk · session_016WV4cxrNurGFU9PsE6NwNT
Fixes #30126
Clause-②: yes (narrowing)
Metadata-protocol: none
维护者速读
os package install的服务器参数从-r/--runtime改名为-u/--url(无别名),并新增-t/--token,与os package export等命令写法一致;打开无权访问的应用、仪表盘、列表视图时,403 拒绝文案改为按调用者语言输出(中文控制台显示「您没有执行此操作的权限,如需访问请联系管理员。」)。com.objectstack.setup这种 API 名)。-r/--runtime的脚本,会被当作未知参数拒绝;只设OS_RUNTIME_URL的脚本不受影响。拒绝文案不再含条目名,两条 meta apps by-name route: answer an explicit permission-denied envelope for an unauthorized session, instead of being indistinguishable from "not published" (backend half of objectui#4252) #8013 断言随之改写,请在合约评审中确认。回滚即撤本 PR。packages/cli/src/commands/package/install.ts的url/token参数;packages/rest/src/meta-item-read-gate.ts的permissionDeniedMessage。pnpm --filter @objectstack/cli exec vitest run test/package-install-url-token-flags.test.ts(8 条全绿);pnpm --filter @objectstack/rest exec vitest run src/meta-permission-refusal-locale.test.ts(9 条全绿)。!,入队前需要你对本 PR 点头,并完成合约评审(收窄面)。落地由席位负责。What changes
@objectstack/cli(BREAKING).os package installnames its server-u, --url(envOS_RUNTIME_URL, defaulthttp://localhost:3000, both unchanged) in place of-r, --runtime, with no alias. A script that passes-ror--runtimeis refused as an unknown flag. A new-t, --token(envOS_RUNTIME_TOKEN) sends a token the target runtime issued asAuthorization: Beareron the install request, with no sign-in round trip;--email/--passwordstill work. Passing a token together with--email/--passwordis refused before any request. These are the spellingsos package exportand about twenty other server-talking commands use.packages/clihas no shared flag helper to reuse, so the two flags are declared inline with the same shape asexport's.content/docs/deployment/cli.mdx(example, flag table, credential paragraph),content/docs/deployment/publish-and-preview.mdx,packages/cli/README.md, and thecreate-objectstackscaffold'sAGENTS.mdand blankREADME.mdnow say--url. The scaffold's two lines were outside the claimed surface but would have become false, so they are fixed here, with acreate-objectstackpatch in the changeset.@objectstack/rest. The/metaread gate's three403 PERMISSION_DENIEDrefusals (app, dashboard, list view) rendered fixed English sentences naming the item's API name. They now render the operation catalog'spermission_denied(renderOperationMessage,@objectstack/spec/system) in the caller'sExecutionContext.locale. That is the catalog and key plugin-security's object and capability refusals already use. The REST door also hands in theerrors.*override lookup, so a deployment'serrors.permission_deniedtranslation applies here as it does there. The runtime dispatcher calls the same gate and gets the built-in catalog in the caller's locale; it hands no override lookup, becausepackages/runtimeis outside this claim. Status, code and envelope are unchanged.Tests
packages/cli/test/package-install-url-token-flags.test.ts(new, 8):--url/-ureach the request URL;--runtimeand-rare refused before any request;--token,-tandOS_RUNTIME_TOKENsendAuthorization: Bearer; no token sends no header; token plus email/password is refused with exit 1 before any request.--urlwhere they passed--runtime, including seven integration files that spawn the CLI.packages/rest/src/meta-permission-refusal-locale.test.ts(new, 9): azh-CNcaller reads the Chinese sentence on all three refusals; a caller with no locale reads the English one, which carries no API name; a deployment override wins; a lookup that echoes the key is no override; a lookup that throws keeps the built-in sentence and the 403.meta-app-publish-gate.test.tsandmeta-item-absent-404.test.ts: the two meta apps by-name route: answer an explicit permission-denied envelope for an unauthorized session, instead of being indistinguishable from "not published" (backend half of objectui#4252) #8013 assertionsmessage toContain('finance')now assert the catalog sentence. Status and code assertions are unchanged.scripts/ablation-replace.mjs, each restored with blob == HEAD: the token/email refusal guard disabled → 1 of 8 failed; the locale dropped fromrenderOperationMessage→ 6 of 9 failed.Acceptance notes
permission_deniedkey takes no placeholders on purpose (operation-message.ts), and the name the gate had was the API name (com.objectstack.setup), which is what row 12 reported. Keeping a name would need a new catalog key inpackages/spec, which this claim forbids. The Console's "You don't have access" page shows the server sentence (ui/packages/app-shellCHANGELOG notes it named the item); it now shows the localized sentence. This is the point for the contract review to confirm.createMetaItemReadGate'snameparameter is now read by no gate. It is kept (as_name) so neither transport's call changes.Out of scope
skills/objectstack-platform/references/operations.md:106still says--runtimeforos package install. The seat files it as a skills-lane card, serial behind this PR.Verification
Derived gates and suites
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat6a2119cc: 97 commands, each run with its exit code captured before any pipe. 95 exit 0 on the first pass; two exit 3 (prerequisite) and exit 0 after their named builds:check:skill-examples(after building@objectstack/client-react: 283 prose examples type-check) andcheck:dual-build-cjs-loads(after building the six packages it named).dispatch-gates --ran: 97 derived, 97 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Changed lines: 470 (+421 / -49, 30 files).check-adr-0087-registration: one declared-breaking changeset, dispositionnot-required (no-migration-prescription).pnpm --filter @objectstack/cli typecheck,pnpm --filter @objectstack/rest typecheck: exit 0.@objectstack/cliunit layer: 388 files / 5415 tests passed. The seven touched integration files: 7 files / 77 tests passed.@objectstack/restfull suite: 396 files. The first run failed the two meta apps by-name route: answer an explicit permission-denied envelope for an unauthorized session, instead of being indistinguishable from "not published" (backend half of objectui#4252) #8013 assertions above; after updating them, those two files pass 53/53.@objectstack/runtimeread-gate parity, app package-id and dispatcher tests: 3 files / 381 tests passed.!):pnpm --filter @objectstack/dogfood teston6a2119cc, 422 files passed / 3 skipped, 3527 tests passed / 41 skipped.origin/mainbefore the gate sweep; the incoming commits touch neitherpackages/cli,packages/restnorpackages/spec.Generated by Claude Code