diff --git a/content/docs/concepts/metadata-lifecycle.mdx b/content/docs/concepts/metadata-lifecycle.mdx index a2d1780fa27..a3f1b64ef78 100644 --- a/content/docs/concepts/metadata-lifecycle.mdx +++ b/content/docs/concepts/metadata-lifecycle.mdx @@ -106,7 +106,7 @@ later ships. See [ADR-0070](https://github.com/objectstack-ai/objectstack/blob/m **Most metadata types must not be overlaid by an environment** — overlaying a packaged item would break the physical schema or the behaviour its package ships. The whitelist lives in **one** place: `MetadataTypeRegistryEntry.allowEnvironmentOverlay` in `packages/spec/src/kernel/metadata-plugin.zod.ts` (spelled `allowOrgOverride` before protocol 18; `GET /api/v1/meta/types` serves it per entry as `allowEnvironmentOverlay`). -> **ADR-0131 D6 — the per-organization overlay axis is retired.** The `/meta` doors (REST and the runtime dispatcher) carry no organization into a metadata write or read: a Studio or `PUT /api/v1/meta/...` write of the five ✅ types below lands **environment-wide** (since ADR-0131 D7 the `sys_metadata` family declares no organization column) and is served to every organization, and an organization admin holding only the retired `manage_org_presentation` capability is refused (`403`). The protocol itself refuses every organization-scoped write, and every read — item, list, layers, cached, history, diff, audit, drafts and the commit timeline — is environment → code, whatever organization a caller names. An overlay row an earlier release stored under an organization — under the `single` posture, every Studio save of these types, filed under the Default Organization — is served by no read, and an 18.x `os serve` refuses to start on a database still holding one until the v18 migration ceremony (ADR-0131 C7: `os migrate organization-ownership --out PLAN`, then `--apply --plan-file PLAN`) has carried it to the environment layer and dropped the column; nothing deletes or rewrites it before then. The anonymous form doors read the environment alone too: the ceremony carries every organization-layer public-form withdrawal onto the environment, fail-closed. The table still records which types take an overlay of a shipped item. +> **ADR-0131 D6 — the per-organization overlay axis is retired.** The `/meta` doors (REST and the runtime dispatcher) carry no organization into a metadata write or read: a Studio or `PUT /api/v1/meta/...` write of the five ✅ types below lands **environment-wide** (since ADR-0131 D7 the `sys_metadata` family declares no organization column) and is served to every organization, and an organization admin holding only the retired `manage_org_presentation` capability is refused (`403`). The protocol itself refuses every organization-scoped write, and every read — item, list, layers, cached, history, diff, audit, drafts and the commit timeline — is environment → code, whatever organization a caller names. An overlay row an earlier release stored under an organization — under the `single` posture, every Studio save of these types, filed under the Default Organization — is served by no read, and on a SQL database (SQLite, PostgreSQL, MySQL) still holding one a v18 `os serve` refuses to start. 18.0 supports fresh installs only and does not upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path. In that release, the v18 migration ceremony (ADR-0131 C7: `os migrate organization-ownership --out PLAN`, then `--apply --plan-file PLAN`) carries such a row to the environment layer and drops the column; nothing deletes or rewrites it before then. The anonymous form doors read the environment alone too: in that release the ceremony carries every organization-layer public-form withdrawal onto the environment, fail-closed. The table still records which types take an overlay of a shipped item. | Type | `allowEnvironmentOverlay` | Rationale | | :--- | :---: | :--- | diff --git a/content/docs/deployment/cli.mdx b/content/docs/deployment/cli.mdx index 4a9160f8908..dd6f1128007 100644 --- a/content/docs/deployment/cli.mdx +++ b/content/docs/deployment/cli.mdx @@ -196,18 +196,25 @@ os dev --database file:./data/test.db --auth-secret $(openssl rand -hex 32) | `--seed-admin` / `--no-seed-admin` | — | Seed a dev admin (`admin@objectos.ai` / `admin123`) on an empty DB — default on; override with `--admin-email` / `--admin-password` | | `-v, --verbose` | — | Verbose output | -##### A 17.x development database is upgraded in place +##### A 17.x development database A v18 server refuses to start on a database still in the v17 organization-ownership shape until the [ownership ceremony](#os-migrate-organization-ownership) -has run on it. `os dev` runs that ceremony for you when the database is a local -SQLite file: +has run on it. 18.0 supports fresh `single` installs; upgrades and walled postures arrive in 18.x. In 18.0 the ceremony refuses, so `os dev` stops at step 2 with its refusal and changes nothing. +18.0 does not upgrade a v17 database: keep a v17 database on a 17.x release +until the 18.x release that carries the upgrade path. For a local SQLite file, +`os dev` in 18.0 still takes step 1's copy first and prints where it is, +beside the ceremony's `NOT_IMPLEMENTED` refusal; any other database gets no +copy and the same answer. +In the 18.x release that carries the upgrade path, `os dev` runs that ceremony +for you when the database is a local SQLite file: + 1. It copies the database file and its `telemetry` sibling (each with its `-wal` / `-shm`) into `/backups/organization-ownership-/`. 2. It runs `os migrate organization-ownership --dev` (the plan), then applies @@ -215,12 +222,14 @@ refusal and changes nothing. beside the copy. 3. It prints the ceremony's warnings and starts the server again. -If a step blocks, or the post-check still holds rows (a row whose owner cannot +In that release, if a step blocks, or the post-check still holds rows (a row whose owner cannot be derived, named per table with its remedy), `os dev` stops and prints what holds it, where the copy is, and the command that resumes the run. It tries once per session. A database that is not a local SQLite file (PostgreSQL, a remote libSQL, `:memory:`) is not -upgraded in place: run the ceremony yourself. `os serve` and `os start` never run -it; they refuse and name the command. +upgraded in place: run the ceremony yourself. + +`os serve` and `os start` never run the ceremony: they refuse to start, and on +a v17 database their 18.0 refusal says that 18.0 does not upgrade it. ##### Serving dev over https @@ -1025,13 +1034,18 @@ safe. No flag skips these refusals: - `sys_account.issuer` is dropped only when its retirement pre-flight reads the table clean (`os migrate account-issuer` reports the colliding rows). - `sys_comment.reactions` waits for a verified `os migrate comment-reactions --apply` run. -- `organization_id` on any table the organization-ownership ceremony covers - waits for a verified `os migrate organization-ownership --apply --plan-file FILE` - run. These tables are the ADR-0131 D7 tables and the `sys_metadata` family. - The ceremony drops those columns itself, in its column-drops step, before it - records the run verified. Dropping one first would turn every legacy +- `organization_id` waits for a verified run of the organization-ownership + ceremony, on every table the drift offers to drop it from: the ceremony plans + every table that still carries the column, the ADR-0131 D7 tables and the + `sys_metadata` family among them. Dropping one first would turn every legacy organization row into an environment row. Under `--json` the refusal answers `message: 'refused_organization_ownership_unmigrated'` and lists the `tables`. + 18.0 itself never records a verified run, so on a v17 database this refusal + holds on every run. 18.0 supports fresh installs only and does not upgrade a + v17 database: keep a v17 database on a 17.x release until the 18.x release + that carries the upgrade path. In that release, the ceremony's + `os migrate organization-ownership --apply --plan-file FILE` run drops these + columns itself, in its column-drops step, before it records the run verified. Each refusal holds the whole `--allow-destructive` run: nothing in it is created, applied or dropped, the run's other changes included. A run without @@ -1478,14 +1492,15 @@ reports the failed read and exits `1`. A failed read or write exits `1`. The v18 ownership ceremony (ADR-0131 D10). A v18 `os serve` / `os start` refuses to start on a database still in the v17 organization-ownership shape until this -has run. Under `os dev` it runs on its own for a local SQLite database (see -[`os dev`](#os-dev)). +has run. In the 18.x release that carries the upgrade path, `os dev` runs it on +its own for a local SQLite database (see [`os dev`](#os-dev)). 18.0 supports fresh `single` installs; upgrades and walled postures arrive in 18.x. In 18.0 this command refuses, plan and apply alike: it exits `1` with `NOT_IMPLEMENTED` (under `--json`, `code` beside `error`) and reads and writes nothing. Keep a v17 database on a 17.x release until the 18.x release -that carries the upgrade path. +that carries the upgrade path. The invocations below, and what the list after +them says the ceremony does, are that 18.x release's. ```bash diff --git a/content/docs/kernel/contracts/metadata-service.mdx b/content/docs/kernel/contracts/metadata-service.mdx index 3489e9ab65b..c082d2d5b3d 100644 --- a/content/docs/kernel/contracts/metadata-service.mdx +++ b/content/docs/kernel/contracts/metadata-service.mdx @@ -412,11 +412,16 @@ overlay axis is retired: the doors carry no organization, so the overlay is column, ADR-0131 D7) and served to every organization of the deployment, whatever the author's active organization. Every protocol read is environment → code, whatever organization a caller names. An overlay -row an earlier release stored under an organization is served by no read, and -an 18.x `os serve` refuses to start on a database still holding one until the -v18 migration ceremony (ADR-0131 C7) has carried it to the environment layer. The anonymous form doors read the environment alone too: the ceremony carries -every organization-layer public-form withdrawal onto the environment, -fail-closed. The per-user, +row an earlier release stored under an organization is served by no read. On a +SQL database (SQLite, PostgreSQL, MySQL) still holding one, a v18 `os serve` +refuses to start, because the `sys_metadata` family there still carries its +`organization_id` column. 18.0 supports fresh installs only and does not +upgrade a v17 database: keep a v17 database on a 17.x release until the 18.x +release that carries the upgrade path. In that release, the v18 migration +ceremony (ADR-0131 C7) carries such a row to the environment layer. The +anonymous form doors read the environment alone too; in that release the +ceremony carries every organization-layer public-form withdrawal onto the +environment, fail-closed. The per-user, per-field patch overlay a previous revision of this page taught here was removed in #13135 — it was never served by any route. diff --git a/content/docs/permissions/capabilities.mdx b/content/docs/permissions/capabilities.mdx index 9a3af4ea755..847f32c0bb1 100644 --- a/content/docs/permissions/capabilities.mdx +++ b/content/docs/permissions/capabilities.mdx @@ -217,8 +217,11 @@ and resource `requiredPermissions` match capability names **as strings**. The boot writes no row for a capability, declared or curated: both are served by the registry. The `sys_capability` object itself is retired and no longer registered (ADR-0131 D3): a row an older database still holds is served by no -route and read by nothing, and `os migrate organization-ownership --apply` -reports the authored rows and deletes the seeded copies (ADR-0131 D10). +route and read by nothing. In the 18.x release that carries the upgrade path +(18.0 does not upgrade a v17 database: see +[`os migrate organization-ownership`](/docs/deployment/cli#os-migrate-organization-ownership)), +`os migrate organization-ownership --apply` reports the authored rows and +deletes the seeded copies (ADR-0131 D10). Withdraw a capability by withdrawing the **grant**. diff --git a/content/docs/permissions/permission-sets.mdx b/content/docs/permissions/permission-sets.mdx index 84ec96ec1ec..f3710de1cc1 100644 --- a/content/docs/permissions/permission-sets.mdx +++ b/content/docs/permissions/permission-sets.mdx @@ -396,7 +396,10 @@ posture, the platform operator. This has three author-visible consequences: package. Uninstall the owning package to remove a packaged set entirely. An older database keeps the `sys_permission_set` table and its rows, and -nothing serves or reads them. `os migrate organization-ownership --apply` +nothing serves or reads them. In the 18.x release that carries the upgrade +path (18.0 does not upgrade a v17 database: see +[`os migrate organization-ownership`](/docs/deployment/cli#os-migrate-organization-ownership)), +`os migrate organization-ownership --apply` (ADR-0131 D10) converts the sets an organization authored in Setup into environment metadata under `single` and deletes the seeded copies. The shipped sets that an install created before 2026-08-15 stored as `managed_by: 'admin'`