Skip to content

Commit 41b4792

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-24896-prelude-grant-projection
2 parents 9b8a2b5 + 7169612 commit 41b4792

3 files changed

Lines changed: 104 additions & 7 deletions

File tree

‎content/docs/releases/v18/index.mdx‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,47 @@ in one major (its D14) instead of spreading them across 17.x minors. While the
2121
line was open, every other breaking change that landed on `main` shipped on it
2222
too, under the same rules.
2323

24+
## Upgrading a database to 18.0.0
25+
26+
An existing database moves to 18.0.0 through the **organization-ownership
27+
ceremony**, `os migrate organization-ownership` (ADR-0131 D10).
28+
29+
- **A fresh install writes a birth marker.** The first boot that creates a
30+
datastore from empty writes a `sys_migration` row
31+
(`adr-0131-organization-ownership`) naming the ownership shape generation it
32+
was born in. A fresh 18.0.0 install never needs the ceremony, under any
33+
tenancy posture.
34+
- **A database without one is refused at boot.** A database 17.x or an 18.0
35+
pre-release (`18.0.0-next.*`) created carries no birth marker, so an 18.0.0
36+
server refuses it and names the ceremony command. Start 18.0.0 against it
37+
once (the refused boot still creates the tables 18.0.0 adds), take a backup,
38+
run `os migrate organization-ownership --out plan.json`, review the plan, run
39+
`os migrate organization-ownership --apply --plan-file plan.json --backup-taken`,
40+
and start the server again. The ceremony writes the same marker, verified,
41+
when its post-check passes.
42+
- **A development boot passes `--dev`.** On a deployment served with `--dev`
43+
(`os dev`, `os serve --dev`), for example a local one with no
44+
`OS_AUTH_SECRET`, both ceremony commands take `--dev`, as the refusal
45+
`os serve --dev` prints names them. `os dev` runs the ceremony itself for a
46+
local SQLite development database.
47+
- **Walled postures boot.** `OS_TENANCY_POSTURE=group` and `isolated` (and
48+
`OS_MULTI_ORG_ENABLED=true`) boot on a fresh install and on a database the
49+
ceremony upgraded, under the same prerequisites as 17.x: the enterprise
50+
`@objectstack/organizations` runtime and `OS_PLATFORM_OWNER_EMAIL`. The
51+
18.0 pre-releases refused them; 18.0.0 does not.
52+
- **A production `os serve` needs an auth secret.** A production `os serve`
53+
whose stack enables auth and which resolves no `OS_AUTH_SECRET` is refused
54+
before any plugin starts: with no AuthPlugin, no caller can
55+
authenticate and every row the boot wrote would have no owner. Set the
56+
secret, or serve without the data API (`--no-server`). `os dev` and
57+
`os serve --dev` use a development fallback and need none, and `os start`
58+
generates an auth secret on its first run and persists it to
59+
`<home>/auth-secret`.
60+
61+
The step-by-step is [Upgrading to 18.0](/docs/upgrading#upgrading-to-180), and
62+
every flag is in
63+
[`os migrate organization-ownership`](/docs/deployment/cli#os-migrate-organization-ownership).
64+
2465
## How a breaking stage lands on this line
2566

2667
- **Through `next` before `latest`.** Every major is published to the `next`

‎content/docs/upgrading.mdx‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,61 @@ writes no artifact, which makes it the fast inner loop while you work through
333333
the to-dos. Full command reference in the [CLI
334334
documentation](/docs/deployment/cli).
335335

336+
## Upgrading to 18.0
337+
338+
18.0 refuses to serve an existing database until an operator step has run on
339+
it. [ADR-0131](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0131-total-organization-ownership-no-null-organization-id.md)
340+
makes organization ownership total, and the rows a 17.x database holds have to
341+
be given their owners before an 18.0 server serves them. That is the
342+
**organization-ownership ceremony**, `os migrate organization-ownership`.
343+
344+
**Which databases need it.** A database 17.x created, or one an 18.0
345+
pre-release (`18.0.0-next.*`) created. The first boot that creates a datastore
346+
from empty writes a **birth marker**, so a fresh 18.0 install never needs the
347+
ceremony, under any tenancy posture. A v18 server serves a database it created
348+
itself or one the ceremony certified, and refuses any other at boot, naming the
349+
command.
350+
351+
**The sequence:**
352+
353+
1. Start 18.0 against the database once (`os serve` / `os start`). The boot is
354+
refused, but its schema sync has already created the tables 18.0 adds, which
355+
the ceremony moves rows into.
356+
2. Take a backup. The platform takes none.
357+
3. Write the plan: `os migrate organization-ownership --out plan.json`. It reads
358+
only.
359+
4. Review the plan.
360+
5. Apply exactly that plan:
361+
`os migrate organization-ownership --apply --plan-file plan.json --backup-taken`.
362+
6. Start the server again.
363+
364+
```bash
365+
os migrate organization-ownership --out plan.json
366+
os migrate organization-ownership --apply --plan-file plan.json --backup-taken
367+
```
368+
369+
**A development boot passes `--dev` to both commands.** A deployment served
370+
with `--dev` (`os dev`, `os serve --dev`), for example a local one with no
371+
`OS_AUTH_SECRET`, composes as a development boot, and the ceremony has to boot
372+
the same way to see the same database. The refusal `os serve --dev` prints names
373+
the command with `--dev`. `os dev` runs the whole sequence itself for a local
374+
SQLite development database.
375+
376+
**Walled postures upgrade too.** `OS_TENANCY_POSTURE=group` and `isolated` boot
377+
in 18.0 on a fresh install and on a database the ceremony upgraded. On a walled
378+
database, a customized copy of a declared webhook or sharing rule blocks its
379+
step and names the row.
380+
381+
**A production `os serve` deployment needs an auth secret.** A production
382+
`os serve` whose stack enables auth and which resolves no `OS_AUTH_SECRET` is
383+
refused before any plugin starts, so set the secret before you start such a
384+
deployment on 18.0. `os start` is not affected: it generates an auth secret on
385+
its first run and persists it to `<home>/auth-secret`.
386+
387+
What the plan lists, how a blocked row is resolved, and every flag are in the
388+
command's reference:
389+
[`os migrate organization-ownership`](/docs/deployment/cli#os-migrate-organization-ownership).
390+
336391
## Per-release specifics
337392

338393
Everything above is the mechanism. The *contents* of a given release — which keys
@@ -349,6 +404,7 @@ have no other channel to reach you than the page below.
349404

350405
| Release | Where its upgrade notes live |
351406
| :--- | :--- |
407+
| v18.0.0 | [Upgrading to 18.0](#upgrading-to-180) (the ownership ceremony) · [v18](/docs/releases/v18) |
352408
| v17.4.0 | [17.4.0](/docs/releases/v17/17-4) — ⛔ checklist not written; machine-draft notes only |
353409
| v17.3.0 | [Upgrade checklist — 17.3.0](/docs/releases/v17/17-3#upgrade-checklist) |
354410
| v17.2.0 | [Upgrade checklist — 17.2.0](/docs/releases/v17/17-2#upgrade-checklist) |

‎packages/cli/CHANGELOG.md‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### Minor Changes
66

7-
- fc34d00: feat(cli): `os serve` (and so `os dev` and `os start`) boots a walled tenancy posture again; `group` and `isolated` are supported on fresh installs
7+
- fc34d00: feat(cli): `os serve` (and so `os dev` and `os start`) boots a walled tenancy posture again; `group` and `isolated` are supported on fresh installs and on databases the ownership ceremony upgraded
88

99
Clause-②: yes (widening)
1010

@@ -159,18 +159,18 @@
159159
os migrate organization-ownership --out plan.json # plan, then review plan.json
160160
os migrate organization-ownership --apply --plan-file plan.json --backup-taken # perform exactly that plan
161161
```
162-
- ae6bd1a: feat(cli)!: 18.0 supports fresh `single` installs only — `os migrate organization-ownership` refuses, and `os serve` refuses a walled posture at boot
162+
- ae6bd1a: feat(cli)!: the 18.0 pre-release refusals of `os migrate organization-ownership` and of a walled posture at boot, both lifted in 18.0.0
163163

164164
Clause-②: yes (narrowing)
165165

166-
<!-- adr-0087: not-required (no-migration-prescription) Nothing an author writes, and no stored shape an author owns, is added, removed, renamed or converted: a CLI command and two deployment postures that used to run now refuse, with no spec key, export, config field or error code removed or renamed. The remedy is an operator's one, stated below: stay on 17.x, or run 18.0 under `single` on a fresh database. -->
166+
<!-- adr-0087: not-required (no-migration-prescription) Nothing an author writes, and no stored shape an author owns, is added, removed, renamed or converted: a CLI command and two deployment postures refused in an 18.0 pre-release, with no spec key, export, config field or error code removed or renamed. 18.0.0 lifts both refusals (12d1476 and fc34d00 in this section), so the operator's remedy is the ownership ceremony, stated below. -->
167167

168-
**BREAKING** (a command and a boot posture that used to run now refuse), shipped as `minor` under the launch-window convention for breaking changes. 18.0 supports fresh installs under the `single` tenancy posture only; upgrading a v17 database and the walled postures arrive in an 18.x release.
168+
**This entry described `18.0.0-next.5`, not 18.0.0.** That pre-release refused the ownership ceremony and the walled postures. 18.0.0 ships neither refusal:
169169

170-
- **FROM** `os migrate organization-ownership` (plan) and `os migrate organization-ownership --apply …` running the v18 ownership ceremony **TO** both refusing with exit `1` and the standard code `NOT_IMPLEMENTED` (under `--json`: `{ error: 'plan_refused' | 'apply_refused', reason: 'upgrade-unavailable', code: 'NOT_IMPLEMENTED', detail }`), reading and writing nothing. The 18.0 ceremony is knowingly incomplete, and an incomplete ceremony must never certify an old database. **Fix:** keep a v17 database on a 17.x release until the 18.x release that carries the upgrade path. `os dev`'s in-place upgrade of a v17 development database runs this command, so it now stops with the same refusal and changes nothing.
171-
- **FROM** `os serve` (and so `os dev` and `os start`) booting with `OS_TENANCY_POSTURE=group` or `isolated`, or with `OS_MULTI_ORG_ENABLED=true`, **TO** a FATAL refusal at the tenancy-posture gate, exit `1`, naming `NOT_IMPLEMENTED` and the 18.x release, before a config is read. `OS_ALLOW_DEGRADED_TENANCY` does not lift it, and no flag or variable does. **Fix:** set `OS_TENANCY_POSTURE=single` (or unset it and `OS_MULTI_ORG_ENABLED`), or keep a walled deployment on a 17.x release.
170+
- **`os migrate organization-ownership` runs** and upgrades a database 17.x or an 18.0 pre-release (`18.0.0-next.*`) created (12d1476 above). A v18 server refuses such a database at boot and names the command. Start 18.0.0 against it once (the boot is refused), take a backup, run `os migrate organization-ownership --out plan.json`, review the plan, run `os migrate organization-ownership --apply --plan-file plan.json --backup-taken`, then start the server again. A deployment served as a development boot (`os dev`, `os serve --dev`, for example a local one with no `OS_AUTH_SECRET`) passes `--dev` to both commands, as the refusal `os serve --dev` prints names it. `os dev` runs the ceremony itself for a local SQLite development database.
171+
- **`os serve` (and so `os dev` and `os start`) boots `OS_TENANCY_POSTURE=group` or `isolated`, and `OS_MULTI_ORG_ENABLED=true`** (fc34d00 above), on a fresh install and on a database the ceremony upgraded.
172172

173-
**What stays as it was.** A fresh install under `single` boots exactly as before. The boot guard that refuses a v17-shaped database is unchanged. Kernel-level boots (`@objectstack/verify`'s `bootStack`, embedded hosts) still accept every posture.
173+
**What else holds.** A fresh install boots under every tenancy posture and writes its birth marker, so it never needs the ceremony. Kernel-level boots (`@objectstack/verify`'s `bootStack`, embedded hosts) still accept every posture.
174174
- 78652c0: feat(cli,plugin-sharing)!: in the 17 → 18 ownership ceremony, a row whose owner cannot be derived blocks certification, and a declared-rule mirror's grants are renamed only onto a rule plugin-sharing serves
175175

176176
Clause-②: yes (narrowing)

0 commit comments

Comments
 (0)