diff --git a/.changeset/26424-demo-staff-dev-login-seed-prose.md b/.changeset/26424-demo-staff-dev-login-seed-prose.md new file mode 100644 index 00000000000..c8224440766 --- /dev/null +++ b/.changeset/26424-demo-staff-dev-login-seed-prose.md @@ -0,0 +1,12 @@ +--- +'@objectstack/spec': patch +--- + +docs(spec): `demoStaff` and `devLogins` prose state what a seeded `sys_user` row really does, and `devLogins` points at `demoStaff` + +Clause-②: no +Metadata-protocol: none + +- **Before.** `DemoStaffSchema`'s TSDoc said a `sys_user` row written through `data` is refused (ADR-0092). It is not: every seed write runs under the system execution context, which the identity-write guard stands aside for, so the row lands. `DevLoginSchema` told the author to "seed the account itself in `data`" in its prescriptions for the `permissions`, `capabilities` and `seed` keys, and its header and `email` description assumed the application seeds the account. Following that lands a directory row with no credential, which cannot sign in. +- **Now.** The `demoStaff` TSDoc says the row lands as a directory row with no account and cannot sign in. The `devLogins` prescriptions, header and `email` description tell the author to declare the person in `demoStaff`, so that `os dev` creates an account that can sign in. The regenerated `references/system/dev-login.mdx` carries the new `email` description. +- No schema, key or behaviour changes. Only prose and a refusal prescription's wording change. diff --git a/content/docs/references/system/dev-login.mdx b/content/docs/references/system/dev-login.mdx index 56a063419c1..be5e35c54e7 100644 --- a/content/docs/references/system/dev-login.mdx +++ b/content/docs/references/system/dev-login.mdx @@ -28,7 +28,7 @@ const result = DevLoginSchema.parse(data); | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | -| **email** | `string` | ✅ | Email of an account this application seeds — printed by the development boot banner | +| **email** | `string` | ✅ | Email of an account that can sign in, such as one declared in `demoStaff` — printed by the development boot banner | | **password** | `string` | optional | Development-fixture password printed beside the address; omit when the account signs in another way | | **label** | `string` | optional | The audience this account belongs to (e.g. `Hiring admin`) — printed before the address | diff --git a/packages/spec/src/system/demo-staff.zod.ts b/packages/spec/src/system/demo-staff.zod.ts index 3439ed1393d..93f4bb51470 100644 --- a/packages/spec/src/system/demo-staff.zod.ts +++ b/packages/spec/src/system/demo-staff.zod.ts @@ -12,9 +12,12 @@ import { strictObject } from '../shared/strict-object'; * ## Why the platform creates it and the application only declares it * * A metadata app's demo seed hands records to named people (`owner_id: - * 'Legal Counsel 1'`), and a seed cannot create a person: a `sys_user` row - * written through `data` is refused (ADR-0092), and it could not sign in - * anyway — signing in needs a hashed credential the auth pipeline mints. So + * 'Legal Counsel 1'`), and a seed cannot create a person who can sign in. A + * `sys_user` row written through `data` is not refused — every seed write runs + * under the system execution context, which ADR-0092's identity-write guard + * stands aside for — but it lands as a directory row with no account, and it + * cannot sign in: signing in needs a hashed credential the auth pipeline mints, + * and a seed row carries none. So * every application used to carry its own script that created the accounts * through the auth door, assigned their positions and permission sets, and * re-ran the seed so the deferred owners resolved. The maintainer ruled the diff --git a/packages/spec/src/system/dev-login.zod.ts b/packages/spec/src/system/dev-login.zod.ts index 4adf4b18ca1..7450a77fb56 100644 --- a/packages/spec/src/system/dev-login.zod.ts +++ b/packages/spec/src/system/dev-login.zod.ts @@ -28,11 +28,14 @@ import { strictObject } from '../shared/strict-object'; * ## What it is NOT * * ⛔ Not an identity, not a seed, and not an authorization: declaring an entry - * here CREATES NOTHING. It is presentation — the application naming accounts it - * seeds by some other means (`data` fixtures, an `onEnable` hook, its own - * script) so the banner can point the operator at one that shows something. - * An entry naming an account nothing seeds prints a credential that does not - * work, exactly as a README line would. + * here CREATES NOTHING. It is presentation — the application naming accounts + * that exist by some other means so the banner can point the operator at one + * that shows something. The way to have a demo account is to declare the person + * in `demoStaff`: `os dev` creates the account through the auth door, so it can + * sign in. A `sys_user` row seeded through `data` is not that — it lands as a + * directory row with no credential and cannot sign in. An entry naming an + * account nothing created prints a credential that does not work, exactly as a + * README line would. * * ## Read only in development * @@ -64,14 +67,15 @@ export const DevLoginSchema = lazySchema(() => strictObject( permissions: 'a `devLogins` entry grants nothing — it only names an account for the boot banner to ' + 'print. Grant capabilities with a permission set (`permissions`) or a position ' - + '(`positions`), and seed the account itself in `data`.', + + '(`positions`), and declare the person in `demoStaff` so `os dev` creates the account.', capabilities: 'a `devLogins` entry grants nothing — it only names an account for the boot banner to ' + 'print. Declare capabilities in `capabilities` and distribute them with `positions` / ' - + '`permissions`; seed the account itself in `data`.', + + '`permissions`; declare the person in `demoStaff` so `os dev` creates the account.', seed: - 'a `devLogins` entry creates no account. Seed the user record in the stack\'s `data` ' - + 'fixtures (or in `onEnable`) and name it here so the banner can print it.', + 'a `devLogins` entry creates no account. Declare the person in `demoStaff` — `os dev` ' + + 'creates the account so it can sign in — and name it here so the banner can print it. ' + + 'A `sys_user` row seeded through `data` has no credential and cannot sign in.', }, }, { @@ -84,7 +88,7 @@ export const DevLoginSchema = lazySchema(() => strictObject( * sign-in form and every seeded fixture key on, so a value that is not one * names an account the operator cannot reach. */ - email: z.string().email().describe('Email of an account this application seeds — printed by the development boot banner'), + email: z.string().email().describe('Email of an account that can sign in, such as one declared in `demoStaff` — printed by the development boot banner'), /** * The password to print beside {@link DevLogin.email}.