Skip to content

Commit f00e8d5

Browse files
feat(spec,plugin-auth,runtime,cli): demoStaff, the demo accounts an application declares and the development boot creates (#25830)
<!-- claude-projects-attribution: {"github_login":"marchtian"} --> _Requested by **田騏** · [project thread](https://claude.ai/code/project/chan_01VmuUhXU9SSUzqJYyXSmYSi?thread=cmsg_01VmuUhXU9SSUzqJYyXSmYSiY9uaapuEYV5dehBVG6QqMr)_ Fixes #25777 Clause-②: yes Metadata-protocol: added ## 维护者速读(草稿) **改了什么** 应用现在可以在 stack 里声明演示账号:`demoStaff: [{ name, email, position?, permissionSets? }]`。本地开发启动(`os dev`)时,平台在开发管理员之后,用同一条注册通道把这些账号建出来,邮箱直接记为已验证,密码统一用开发种子密码(`os dev --admin-password`,默认 `admin123`);再在默认组织里给每个账号挂上声明的岗位和权限集;然后才跑应用的种子数据,所以种子里写 `owner_id: 'Legal Counsel 1'` 的记录第一次启动就能指到真人。重复启动不重复建号,已有的账号原样不动,只补缺的岗位/权限集。应用自己不建号,只声明(遵循裁定"demo accounts are the platform's to create; the app only declares them")。 **为什么改** 今天每个演示应用(HotCRM 等)都得自己写脚本建演示账号、挂岗位、重算共享规则,种子里的 `owner_id` 第一次启动还指不到人。这张卡把这件事收回平台。 **风险与代价(含回滚)** - 这是能登录的账号,所以只在本地开发启动生效。其余启动一律不建号并说明原因(ADR-0112 码):非 `NODE_ENV=development` 或 migrate-and-exit 运行,`PERMISSION_DENIED` 403,记 `info`;开发启动下若是组织隔离(walled)姿态、或认证基址不是回环地址,`PERMISSION_DENIED` 403;库里还没有任何非演示账号能登录(演示账号会被提升成平台管理员),`PRECONDITION_REQUIRED` 428;凭据库读不了,`SERVICE_UNAVAILABLE` 503;这几种记 `warn`。每种都有带 code+status 的测试。 - `os build` 写出的 `objectstack.json` 里没有这个键,部署从产物启动时无号可建(有构建输出测试)。但应用有函数(callable)时,`objectstack-runtime.*.mjs` 会把整份 config 代码打包进去,演示账号的名字和邮箱文字会出现在这个模块里(它只导出 `functions` 和 `meta`,运行时读不到这份列表)。`data`、`devLogins` 今天也是同样情况。 - 声明了演示账号的开发启动,种子推迟到 `kernel:bootstrapped` 才跑,plugin-security 会在 `kernel:ready` 打一行 "PROVISIONAL … 1 seed source(s) were still writing" 的 WARN(与种子超时同一路径)。 - 没声明 `demoStaff` 的应用,启动、种子、构建都与之前完全一样。回滚即 revert 本 PR:无迁移,只有开发库里已建的演示账号会留着。 **席位意见** **你要做的** 请批准或改动以下取舍(都是 shape 决定,代码已按左侧实现): 1. 键名 `demoStaff`(顶层,与 `devLogins` 并列),而不是卡上草拟的 `demo.staff[]`。 2. 不满足条件时跳过并记日志,而不是让启动失败。 3. 演示账号统一用开发种子密码,schema 拒收 `password` 字段(仓库里不落凭据)。 4. 种子推迟带来的那行 WARN 可以接受。 5. runtime 模块里带着 config 文字:接受(同 `data`/`devLogins`),还是另开卡把开发专用键从打包里剥掉。 6. walled 姿态一律拒绝。 7. 启动横幅里列出演示账号不在本 PR 范围。 本 PR 动了 spec 和 `skills/**`(Tier H),落地需要你的批准。 ## What changed **`@objectstack/spec`** - `packages/spec/src/system/demo-staff.zod.ts` (new): `DemoStaffSchema`, a strict entry `{ name, email, position?, permissionSets? }` with aliases and guidance for `password` and `organization`. - `stack.zod.ts`: `demoStaff` in the stack shape (compose disposition `concat`, an assembled-package envelope key). `validateCrossReferences` refuses an entry naming a position or permission set the stack does not declare, and two entries with one name or one address (case-insensitive): `StackCrossReferenceError`, `STACK_CROSS_REFERENCE_INVALID` / 422. - `kernel/unmanaged-install.ts`: `demoStaff: 'deployment'`. Generated surfaces, reference docs and the strictness-ledger count regenerated; the hand-kept schema counts in `llms.txt` and `getting-started/quick-reference.mdx` follow (system 37). **`@objectstack/plugin-auth`** - `src/demo-staff.ts` (new): `decideDemoStaffEnvironmentGate` (pure), `probeDemoStaffPriorLogin`, `provisionDemoStaff`. - `auth-plugin.ts`: `AuthPluginOptions.demoStaff`; the gate is decided in `init()` and published as the `demo-staff` service (`{ armed }`); a `kernel:ready` hook registered right after the dev-admin hook signs each account up through the operator provisioning ticket (`stageOperatorProvisioning` → `signUpEmail` → `clearOperatorProvisioning`), stamps `email_verified`, and writes `sys_user_position` / `sys_user_permission_set` rows in `tenancy.defaultOrgId()`. It never writes a membership (ADR-0093 D2); an account the membership policy left outside the Default Organization is reported in `failed` and gets no assignment (an organization-less row applies nowhere, ADR-0131 D1). No `sys_user` row goes through datasets (ADR-0092). - `walled-owner-verification-path.ts`: `devSeedAdminPassword()`, shared with `maybeSeedDevAdmin`. **`@objectstack/runtime`** - `app-plugin.ts`: when the `demo-staff` service reports `armed: true`, the inline seed runs at `kernel:bootstrapped` instead of inside `start()`. The seed source is declared as before, so the settlement tally and `app:seeded` take the existing over-budget path. **`@objectstack/cli`** - `serve.ts` hands `config.demoStaff` to `AuthPlugin`; `compile.ts` deletes it from the bundle before `objectstack.json` is written. - `test/option-b-reader-acceptance.pin.test.ts`: `demoStaff` joins the pinned artifact envelope keys. **Repo** - `scripts/check-stack-collection-maps.mjs`: `demoStaff` is a non-collection array key (like `devLogins`). - `skills/objectstack-platform/SKILL.md`: `demoStaff` in the top-level key list (`check-skill-top-level-keys` requires it). Readings: the file 488 → 488 lines (23301 → 23314 bytes); the package (sum of all SKILL.md) 4383 → 4383 lines. - Tenant-audit census: the three new elevated writes are counted (240 → 243 sites); census and its prose page updated. - `scripts/engine-double-contract.pinned.json`: records the new test double whose `update()` is pinned to `assertEngineUpdateDispatch`. - `scripts/check-single-authz-resolver.mjs` (7a2e7a8): an ALLOW entry for `packages/plugins/plugin-auth/src/demo-staff.ts`, with its reason. The file queries both `sys_user_position` and `sys_user_permission_set`, which the gate reads as a second authz resolver. It is not one: it reads each grant table only to ask whether the one literal row it is about to insert (one user, one declared position or permission set, the Default Organization, limit 1) is already there, so a second boot adds nothing. It aggregates no grants and builds no context; a demo account's grants resolve through `resolveAuthzContext` like any other account's. `pnpm check:authz-resolver` runs in lint but is not in the derived gate list, so CI caught it, not the local run. - `content/docs/getting-started/quick-start.mdx` (465b6c2): `demoStaff` joins `devLogins` in the "Not in the table, and why" paragraph, which lists every top-level key the stack-key table leaves out, with one clause on what it does: a local `os dev` boot creates the accounts, and `os build` leaves the key out of `objectstack.json`. ## PM assumptions, measured - "Seeded rows carry no sharing grants until a rule is re-evaluated (the `plugin-sharing` write hook returns early for `isSystem`)": **no longer true.** `packages/plugins/plugin-sharing/src/rule-hooks.ts` retired the `isSystem` materialisation skip (its header, "RETIRED"), and `recipient-membership-recompute.ts` re-evaluates rules on a `sys_user_position` write. So a separate "re-evaluate every sharing rule" step is not added: the position write and the seed's own inserts drive it. #16712 is no longer open; its work was re-cut as #20292. - HotCRM `scripts/demo-staff.ts` four steps, as covered here: create accounts (sign-up door), assign positions (and permission sets), sharing re-evaluation (above), sign in as each (real-kernel test 1 signs in through `/api/v1/auth/sign-in/email`). ## Acceptance notes - Tests: spec `src/stack-demo-staff.test.ts` (14); plugin-auth `src/demo-staff.test.ts` (14, every gate clause asserts code + status + reason) and `src/demo-staff-provisioning.test.ts` (real kernel on SQLite: first boot creates, joins the Default Organization, assigns there, signs in; only the dev admin holds `admin_full_access`; idempotent; an existing account untouched; no membership reported and nothing written; production 403 at `info`; migrate-and-exit 403; non-loopback 403; no prior login 428); runtime `src/app-plugin.seed-demo-staff.test.ts` (6); cli `test/build-demo-staff-artifact.test.ts` (integration tier: no key or address in `objectstack.json`, exactly one runtime module, `loadArtifactBundle` reads no `demoStaff` and no address outside `functions`, positions and the callable survive as controls) and `src/commands/serve-auth-demo-staff.contract.test.ts`. - Smoke run on `examples/app-todo` (temporary edit, reverted): first `os dev` boot, the seeded task "Fix Server bug" has `owner` = Todo Helper 1's id; `helper1@todo.example` signs in with `admin123`, address verified; `os build` output has 0 hits for the key. - Out of scope, for the maintainer: the runtime module carries dev-only config text (`demoStaff`, `devLogins`, `data`) whenever a stack has callables; it is not exported or loaded. No carrier yet. - Not done here: listing the demo accounts in the `os dev` banner. ## Gates and tests - `node scripts/pm/dispatch-gates.mjs --commands` on the final diff derives 153 commands. All 153 ran on ed03f3f (after merging `main`), each exit code recorded before any pipe: 153 exit 0. `--ran` reconciliation: "153 derived famil(ies) accounted for — 153 run, 0 NOT-MEASURED (a DERIVED zero — all 153 recorded an exit code and none of them is 3)". The build prerequisites were built first, so `check:skill-examples`, `check:dual-build-cjs-loads` and `check:i18n-coverage` measured instead of refusing. - Found by earlier full runs and fixed in this PR: the hand-kept schema counts (`check:llms-txt`, `check:quick-reference-counts`), the new test doubles (`check:objectql-double-limit`, `check:engine-double-contract`, with `check:where-matcher` kept clean), and the three new elevated write sites (`check-tenant-audit-census`). - Tests on ed03f3f: spec 721 files, 21835 passed; plugin-auth 195 files, 3704 passed (10 skipped); runtime 445 files, 7106 passed (19 skipped); cli `--project unit` 332 files, 4848 passed; cli integration `test/build-demo-staff-artifact.test.ts` 1 passed. `pnpm typecheck` for spec, plugin-auth, runtime and cli: exit 0. `check:generated`: exit 0. - Dogfood battery: not run locally (no `!` in the title and no `(narrowing)` arm). - Where these readings come from: the gate and test counts above were measured on ed03f3f. The commits after it (465b6c2 docs, 7a2e7a8 the ALLOW entry, and the d354551 merge of `main`) were not re-measured locally. CI on d354551 is the current reading: all 47 check runs completed, each with success or skipped. Success includes Lint and Repo Gates (with `check:authz-resolver`), the TypeScript and Type Check jobs, Build Core, Build Docs, Check Changeset, all eight Test Core shards and the Test Core summary, Type Check UI, and Build and E2E UI. Skipped by their own conditions: Lint UI, Test UI, Dogfood Verify CLI, the Dogfood Regression Gate shards, Temporal Conformance, and the two opt-in jobs. ## Independent review A full independent review of the whole diff (isolated subagent on the `fable` model) and re-reviews of each later commit: REQUEST-CHANGES, then APPROVE-WITH-NITS, APPROVE, APPROVE. The verdicts are quoted in a comment on this PR. The last Fable pass read 67953e8. Four commits came after that pass and were not Fable-reviewed: 465b6c2 (the quick-start key list), 7a2e7a8 (the `check:authz-resolver` ALLOW entry), and the `main` merges ed03f3f and d354551. The seat's contract review at d354551 (PASS, no must-fix, in its comment on this PR) read them: the two PR-authored commits in full, and the net diff against `main`, which carries what both merges resolved. --- _Generated by [Claude Code](https://claude.ai/code/session_01SHjswg4gueCJQMHKteQQJ4)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent cb0a2fc commit f00e8d5

38 files changed

Lines changed: 2014 additions & 44 deletions

‎.changeset/25777-demo-staff.md‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/plugin-auth': minor
4+
'@objectstack/runtime': minor
5+
'@objectstack/cli': minor
6+
---
7+
8+
feat: `demoStaff` — an application declares the demo accounts its seed data is dealt to, and the development boot creates them
9+
10+
Clause-②: yes
11+
Metadata-protocol: added
12+
13+
A stack may now declare `demoStaff: [{ name, email, position?, permissionSets? }]`. On a local development boot (`os dev`), `@objectstack/plugin-auth` creates each entry right after the development admin, through the same sign-up pipeline, with the development seed password (`os dev --admin-password`, default `admin123`); assigns the declared position and permission sets in the Default Organization (an account the membership policy left outside it is reported and gets none); and the application's seed then runs, so a seed row naming one of these people (`owner_id: 'Legal Counsel 1'`) resolves on the first boot. Idempotent: an address that already has an account is left exactly as it is, and only its missing assignments are added.
14+
15+
Development only. `os build` leaves the key out of the artifact (`objectstack.json`), so a deployment booted from one has nothing to provision. Every other boot creates nothing and says why, with an ADR-0112 code: a boot that is not `NODE_ENV=development`, or a migrate-and-exit run (`PERMISSION_DENIED`, logged at `info` — the intended outcome there); and, on a development boot, logged at `warn` because the developer loses the accounts: a walled tenancy posture or an auth base URL that is not a loopback address (`PERMISSION_DENIED`), a database where nothing but a demo account could sign in, so a demo account would be promoted to platform admin (`PRECONDITION_REQUIRED`), or a credential store that could not be read (`SERVICE_UNAVAILABLE`).
16+
17+
`defineStack` refuses an entry that names a position or permission set the stack does not declare (a platform set such as `admin_full_access` is never one), and two entries with one name or one address (`STACK_CROSS_REFERENCE_INVALID`).
18+
19+
`@objectstack/runtime`: when the boot will create demo accounts, `AppPlugin` runs its inline seed at `kernel:bootstrapped` instead of inside `start()`. The seed source is declared as before, so the settlement tally and `app:seeded` behave as they do for a seed that overran its budget.
20+
21+
What to do: nothing. A stack that declares no `demoStaff` boots, seeds and builds exactly as before. An application that creates its demo accounts with its own script can declare them here and delete the script.

‎content/docs/getting-started/quick-reference.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Plugin architecture, manifests, and kernel runtime.
8585
| **[Metadata Loader](/docs/references/kernel/metadata-loader)** | `metadata-loader.zod.ts` | MetadataLoaderContract | Metadata loading |
8686
| **[Package Registry](/docs/references/kernel/package-registry)** | `package-registry.zod.ts` | InstalledPackage, InstallPackageRequest | Package resolution |
8787

88-
## System Protocol (16 of 36 schemas)
88+
## System Protocol (16 of 37 schemas)
8989

9090
Runtime environment, logging, jobs, caching, and observability.
9191

‎content/docs/getting-started/quick-start.mdx‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,11 @@ schema page is the authority until one lands.
233233
at all (`viewItems` is `z.never()`, the machine-assembled channel for
234234
runtime-assembled manifests; `runtimeModule` is written by `objectstack build`);
235235
`manifest`, `i18n`, `api`, `server`, `appName`, `email`, `sms`, `requires`,
236-
`tiers`, `plugins`, `devPlugins`, `devHint` and `devLogins` configure the stack
237-
rather than declare metadata items (`email` and `sms` carry no credentials —
238-
those stay in the environment or in Settings); and
236+
`tiers`, `plugins`, `devPlugins`, `devHint`, `devLogins` and `demoStaff` configure
237+
the stack rather than declare metadata items (`email` and `sms` carry no
238+
credentials — those stay in the environment or in Settings; `demoStaff` names the
239+
demo accounts a local `os dev` boot creates, and `os build` leaves it out of
240+
`objectstack.json`); and
239241
`functions` and `onEnable` are code the runtime calls, not metadata it stores.
240242

241243
## How you verify

‎content/docs/permissions/tenant-audit-census.mdx‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ are reported as `undecidable` rather than assumed either way.
132132

133133
The same holds twice over for the context. An options argument spelled as a
134134
literal can be read; one spelled `options`, `{ ...opts }`, or handed through a
135-
forwarding shim cannot, and **51 of the 240 sites are spelled that way**. A
135+
forwarding shim cannot, and **51 of the 243 sites are spelled that way**. A
136136
context resolved from an inline literal or a local `const` can be tested for
137137
`isSystem`; one arriving from a helper call cannot.
138138

@@ -197,10 +197,10 @@ reproduce them. Where it disagrees, it disagrees on the page:
197197

198198
| carried figure | where it survives | this census |
199199
| :--- | :--- | ---: |
200-
| 175 write call sites | quoted in the merged changeset | **240** |
200+
| 175 write call sites | quoted in the merged changeset | **243** |
201201
| 24 carrying no tenant context | quoted in the merged changeset | **2** provable and tenancy-enabled; **29** more whose options argument is unreadable |
202-
| 127 of 175 statically decidable, 48 runtime-parameter-name sites | restated on the `isSystem`-scoping card | **163 of 240** decidable, **77** undecidable |
203-
| 135 (77%) silenced by the `isSystem` guard before the posture gate | the lost issue body — **no surviving corroboration** | **not reproduced**: 137 decidably elevated, 0 decidably not, 95 undecidable |
202+
| 127 of 175 statically decidable, 48 runtime-parameter-name sites | restated on the `isSystem`-scoping card | **166 of 243** decidable, **77** undecidable |
203+
| 135 (77%) silenced by the `isSystem` guard before the posture gate | the lost issue body — **no surviving corroboration** | **not reproduced**: 140 decidably elevated, 0 decidably not, 95 undecidable |
204204
| 141 and 132, two independent re-derivations | the card that filed this work | — |
205205

206206
**The differences are not reconciled, and deliberately so.** The old census's
@@ -217,11 +217,11 @@ would report a smaller number and would not say so.
217217

218218
The fourth row is the one worth flagging to anyone citing it. **The 135 / 77%
219219
figure has no surviving corroboration anywhere in the tree.** This census reads
220-
137 of 240 (57%) as decidably elevated, with 95 more whose elevation is a
220+
140 of 243 (58%) as decidably elevated, with 95 more whose elevation is a
221221
run-time fact — so the claim is neither confirmed nor refuted, and the honest
222222
answer is that a static reading cannot settle it.
223223

224-
⇒ **Cite `2 / 240`, and say what it is**: the sites whose options argument was
224+
⇒ **Cite `2 / 243`, and say what it is**: the sites whose options argument was
225225
READ and holds no tenant context, against a decidably tenancy-enabled object.
226226
That is the control's provable yield surface. ⛔ Do not cite it as "the sites
227227
without tenant context" — **29 further sites** have an options argument this
@@ -233,28 +233,28 @@ cannot read, and they are neither in nor out.
233233

234234
| what | count |
235235
| :--- | ---: |
236-
| write call sites on the application surface | **240** |
237-
| …whose object name is statically decidable | 163 |
236+
| write call sites on the application surface | **243** |
237+
| …whose object name is statically decidable | 166 |
238238
| …whose object name is chosen at run time | 77 |
239-
| …against an object with tenancy ENABLED | 162 |
239+
| …against an object with tenancy ENABLED | 165 |
240240
| …against an object that declares tenancy off | 1 |
241-
| threading a tenant context | 181 |
241+
| threading a tenant context | 184 |
242242
| PROVABLY carrying none (options read, no context key) | **8** |
243243
| …of those, against a decidably tenancy-enabled object | **2** |
244244
| options argument UNREADABLE — may or may not carry one | 51 |
245245
| …of those, against a decidably tenancy-enabled object | 29 |
246-
| threading a decidably ELEVATED (`isSystem`) context | 137 |
246+
| threading a decidably ELEVATED (`isSystem`) context | 140 |
247247
| threading a context that is decidably NOT elevated | 0 |
248248
| threading a context whose elevation is a run-time fact | 95 |
249249

250250
| how the instrument reached the site | count |
251251
| :--- | ---: |
252-
| receiver carried a readable engine type | 185 |
252+
| receiver carried a readable engine type | 188 |
253253
| receiver erased, placed by the object NAME | 45 |
254254
| receiver erased, placed by an `object: string` PARAMETER | 5 |
255255
| receiver erased, placed by an `UNTYPED_RECEIVERS` row | 5 |
256256

257-
| object name spelled inline | 112 |
257+
| object name spelled inline | 115 |
258258
| object name spelled through a `const` | 51 |
259259
| object name is an `object: string` parameter | 7 |
260260
| object name is some other run-time expression | 70 |
@@ -307,12 +307,12 @@ holds still. They are required to be HERE and to say WHEN they were true;
307307
their values are not compared. The reasoning, and the measurement behind it,
308308
are in `scripts/check-tenant-audit-census.mjs`.
309309

310-
Measured on 2026-10-25 at `ca3ca05b0`.
310+
Measured on 2026-10-25 at `85aabb332`.
311311

312312
| corpus scale (not enforced) | count |
313313
| :--- | ---: |
314-
| tracked non-test sources scanned | 768 |
315-
| engine-shaped types recognised | 87 |
314+
| tracked non-test sources scanned | 769 |
315+
| engine-shaped types recognised | 88 |
316316
| declared objects in the registry | 117 |
317317
| same-named calls subtracted as non-engine | 176 |
318318

‎content/docs/references/index.mdx‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Protocol reference — every schema by module
33
navTitle: Protocol Reference
4-
description: Every schema published by @objectstack/spec — 1539 schemas across 14 protocol modules
4+
description: Every schema published by @objectstack/spec — 1540 schemas across 14 protocol modules
55
---
66

77
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
@@ -32,9 +32,9 @@ counts are sums of the rows they head. Regenerate with
3232
| [Security Protocol](/docs/references/security) | 5 | 34 | Permission sets, row-level security, sharing rules, tenancy posture. |
3333
| [Shared Protocol](/docs/references/shared) | 10 | 31 | Primitives used across every protocol — identifiers, HTTP, expressions, error maps, enums. |
3434
| [Studio Protocol](/docs/references/studio) | 3 | 35 | Studio designer metadata — the authoring surfaces for the protocols above. |
35-
| [System Protocol](/docs/references/system) | 36 | 285 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. |
35+
| [System Protocol](/docs/references/system) | 37 | 286 | The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance. |
3636
| [UI Protocol](/docs/references/ui) | 16 | 169 | Apps, pages, views, dashboards, reports, actions and themes — the ObjectUI layer. |
37-
| **Total** | **197** | **1539** | 14 protocol modules |
37+
| **Total** | **198** | **1540** | 14 protocol modules |
3838

3939
---
4040

@@ -317,7 +317,7 @@ Studio designer metadata — the authoring surfaces for the protocols above.
317317

318318
## System Protocol
319319

320-
**Source:** `packages/spec/src/system/` · **Import:** `@objectstack/spec/system` · **36 pages, 285 schemas**
320+
**Source:** `packages/spec/src/system/` · **Import:** `@objectstack/spec/system` · **37 pages, 286 schemas**
321321

322322
The runtime environment — logging, jobs, cache, metrics, notifications, i18n and compliance.
323323

@@ -329,6 +329,7 @@ The runtime environment — logging, jobs, cache, metrics, notifications, i18n a
329329
| [`cache.zod.ts`](/docs/references/system/cache) | `CacheAvalanchePrevention`, `CacheConfig`, `CacheConsistency`, `CacheInvalidation`, `CacheStrategy`, `CacheTier`, `CacheWarmup`, `DistributedCacheConfig` |
330330
| [`collaboration.zod.ts`](/docs/references/system/collaboration) | `AwarenessEvent`, `AwarenessSession`, `AwarenessUpdate`, `AwarenessUserState`, `CRDTMergeResult`, `CRDTState`, `CRDTType`, `CollaborationMode`, `CollaborationSession`, `CollaborationSessionConfig`, `CollaborativeCursor`, `CounterOperation`, `CursorColorPreset`, `CursorSelection`, `CursorStyle`, `CursorUpdate`, `GCounter`, `LWWRegister`, `ORSet`, `ORSetElement`, `OTComponent`, `OTOperation`, `OTOperationType`, `OTTransformResult`, `PNCounter`, `TextCRDTOperation`, `TextCRDTState`, `UserActivityStatus`, `VectorClock` |
331331
| [`core-services.zod.ts`](/docs/references/system/core-services) | `CoreServiceName`, `KernelServiceMap`, `KernelServiceStatus`, `ServiceConfig`, `ServiceCriticality` |
332+
| [`demo-staff.zod.ts`](/docs/references/system/demo-staff) | `DemoStaff` |
332333
| [`deploy-bundle.zod.ts`](/docs/references/system/deploy-bundle) | `DeployBundle`, `DeployDiff`, `DeployManifest`, `DeployStatusEnum`, `DeployValidationIssue`, `DeployValidationResult`, `MigrationPlan`, `MigrationStatement`, `SchemaChange` |
333334
| [`dev-login.zod.ts`](/docs/references/system/dev-login) | `DevLogin` |
334335
| [`disaster-recovery.zod.ts`](/docs/references/system/disaster-recovery) | `BackupConfig`, `BackupRetention`, `BackupStrategy`, `DisasterRecoveryPlan`, `FailoverConfig`, `FailoverMode`, `RPO`, `RTO` |
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: Demo Staff schema — System Protocol reference
3+
navTitle: Demo Staff
4+
description: "Demo Staff schemas of the ObjectStack System Protocol: DemoStaff — each property with its type, default and a TypeScript example."
5+
---
6+
7+
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
8+
9+
<Callout type="info">
10+
**Source:** `packages/spec/src/system/demo-staff.zod.ts`
11+
</Callout>
12+
13+
## TypeScript Usage
14+
15+
```typescript
16+
import { DemoStaffSchema } from '@objectstack/spec/system';
17+
import type { DemoStaff } from '@objectstack/spec/system';
18+
19+
// Validate data
20+
const result = DemoStaffSchema.parse(data);
21+
```
22+
23+
---
24+
25+
## DemoStaff
26+
27+
### Properties
28+
29+
| Property | Type | Required | Description |
30+
| :--- | :--- | :--- | :--- |
31+
| **name** | `string` | ✅ | Display name of the demo account — the value a seed dataset names it by in a sys_user reference such as owner_id |
32+
| **email** | `string` | ✅ | Sign-in address of the demo account |
33+
| **position** | `string` | optional | A position this application declares in `positions`, assigned to the demo account |
34+
| **permissionSets** | `string[]` | optional | Permission sets this application declares in `permissions`, granted to the demo account |
35+
36+
37+
---
38+

‎content/docs/references/system/index.mdx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: System Protocol — complete schema reference
33
navTitle: System Protocol
4-
description: "The ObjectStack System Protocol in 36 reference pages: every schema in @objectstack/spec with its properties, types, defaults and a TypeScript example."
4+
description: "The ObjectStack System Protocol in 37 reference pages: every schema in @objectstack/spec with its properties, types, defaults and a TypeScript example."
55
---
66

77
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */}
@@ -15,6 +15,7 @@ This section contains all protocol schemas for the system layer of ObjectStack.
1515
<Card href="/docs/references/system/cache" title="Cache" description="Source: packages/spec/src/system/cache.zod.ts" />
1616
<Card href="/docs/references/system/collaboration" title="Collaboration" description="Source: packages/spec/src/system/collaboration.zod.ts" />
1717
<Card href="/docs/references/system/core-services" title="Core Services" description="Source: packages/spec/src/system/core-services.zod.ts" />
18+
<Card href="/docs/references/system/demo-staff" title="Demo Staff" description="Source: packages/spec/src/system/demo-staff.zod.ts" />
1819
<Card href="/docs/references/system/deploy-bundle" title="Deploy Bundle" description="Source: packages/spec/src/system/deploy-bundle.zod.ts" />
1920
<Card href="/docs/references/system/dev-login" title="Dev Login" description="Source: packages/spec/src/system/dev-login.zod.ts" />
2021
<Card href="/docs/references/system/disaster-recovery" title="Disaster Recovery" description="Source: packages/spec/src/system/disaster-recovery.zod.ts" />

‎content/docs/references/system/meta.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"collaboration",
4040
"doc",
4141
"---More---",
42+
"demo-staff",
4243
"dev-login",
4344
"fate-supplement",
4445
"sms-config",

‎docs/audits/2026-07-unknown-key-strictness-ledger.counts/system.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ hand-patch a number here** — fix the code or the verdict and regenerate.
1919

2020
| Dir | Sites |
2121
|---|---|
22-
| `system/` | 380 |
22+
| `system/` | 381 |

‎docs/audits/2026-08-tenant-audit-write-call-sites.counts.md‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ silent, and `node scripts/tenant-audit-census.mjs --write` is the resolution.
3333

3434
| Measure | Value |
3535
|---|---:|
36-
| Write call sites | 240 |
37-
| Object name statically decidable | 163 |
36+
| Write call sites | 243 |
37+
| Object name statically decidable | 166 |
3838
| Object name chosen at run time | 77 |
39-
| Against a tenancy-enabled object | 162 |
39+
| Against a tenancy-enabled object | 165 |
4040
| Against an object declaring tenancy off | 1 |
41-
| Threading a tenant context | 181 |
41+
| Threading a tenant context | 184 |
4242
| Provably carrying none | 8 |
4343
| …and decidably tenancy-enabled | 2 |
4444
| Options argument unreadable | 51 |
4545
| …and decidably tenancy-enabled | 29 |
46-
| Threading a decidably elevated context | 137 |
46+
| Threading a decidably elevated context | 140 |
4747
| Threading a decidably non-elevated context | 0 |
4848
| Threading a context of undecidable elevation | 95 |
4949

@@ -90,12 +90,12 @@ holds still. They are required to be HERE and to say WHEN they were true;
9090
their values are not compared. The reasoning, and the measurement behind it,
9191
are in `scripts/check-tenant-audit-census.mjs`.
9292

93-
Measured on 2026-10-25 at `ca3ca05b0`.
93+
Measured on 2026-10-25 at `85aabb332`.
9494

9595
| corpus scale (not enforced) | count |
9696
| :--- | ---: |
97-
| tracked non-test sources scanned | 768 |
98-
| engine-shaped types recognised | 87 |
97+
| tracked non-test sources scanned | 769 |
98+
| engine-shaped types recognised | 88 |
9999
| declared objects in the registry | 117 |
100100
| same-named calls subtracted as non-engine | 176 |
101101

@@ -144,6 +144,9 @@ Measured on 2026-10-25 at `ca3ca05b0`.
144144
| `packages/plugins/plugin-auth/src/auth-plugin.ts` | `update` | `sys_user` | enabled | elevated | 1 |
145145
| `packages/plugins/plugin-auth/src/auth-plugin.ts` | `update` | `SystemObjectName.USER` | undecidable | elevated | 1 |
146146
| `packages/plugins/plugin-auth/src/default-organization-invariant.ts` | `insert` | `sys_organization` | enabled | elevated | 1 |
147+
| `packages/plugins/plugin-auth/src/demo-staff.ts` | `update` | `sys_user` | enabled | elevated | 1 |
148+
| `packages/plugins/plugin-auth/src/demo-staff.ts` | `insert` | `sys_user_permission_set` | enabled | elevated | 1 |
149+
| `packages/plugins/plugin-auth/src/demo-staff.ts` | `insert` | `sys_user_position` | enabled | elevated | 1 |
147150
| `packages/plugins/plugin-auth/src/ensure-default-organization.ts` | `insert` | `object` | undecidable | elevated | 1 |
148151
| `packages/plugins/plugin-auth/src/ensure-default-organization.ts` | `update` | `sys_member` | enabled | elevated | 1 |
149152
| `packages/plugins/plugin-auth/src/forced-reset-revocation.ts` | `update` | `SystemObjectName.API_KEY` | undecidable | elevated | 1 |

0 commit comments

Comments
 (0)