diff --git a/.changeset/24637-spec-upgrade-entries-fresh-install-only.md b/.changeset/24637-spec-upgrade-entries-fresh-install-only.md new file mode 100644 index 00000000000..6107e9ce91e --- /dev/null +++ b/.changeset/24637-spec-upgrade-entries-fresh-install-only.md @@ -0,0 +1,15 @@ +--- +'@objectstack/spec': patch +--- + +fix(spec): the 18.0 upgrade-guide entries that name `os migrate organization-ownership` say first that 18.0 supports fresh installs only + +Clause-②: no + +In 18.0, `os migrate organization-ownership` refuses plan and apply alike on every database (exit 1, `NOT_IMPLEMENTED`, nothing read or written). Seven ADR-0087 semantic entries still told an operator to run `--out PLAN`, then `--apply --plan-file PLAN`, as if 18.0 upgraded a v17 database. Each now says, in the same words as the CLI and the boot refusal: 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. The plan and apply steps stay, marked as the 18.x release's ceremony. + +- `sys-metadata-organization-column-retired`, `sys-metadata-audit-organization-column-retired`, `sys-metadata-commit-organization-column-retired`, `sys-metadata-history-organization-column-retired`, `ups-permission-set-id-column-retired`: the replacement and the acceptance criteria. +- `sharing-rule-declared-mirror-retired`: the replacement and the acceptance criteria. +- `cli-organization-ownership-apply-plan-file-required`: the replacement now says that 18.0 refuses this invocation, as it refuses every invocation of the command, and keeps the plan-file rule as the 18.x release's. + +Only the text changes. Every entry keeps its `id`, its surface and its step. diff --git a/packages/spec/src/migrations/entries/semantic/18.cli-organization-ownership-apply-plan-file-required.ts b/packages/spec/src/migrations/entries/semantic/18.cli-organization-ownership-apply-plan-file-required.ts index e8731570810..82efb17de2c 100644 --- a/packages/spec/src/migrations/entries/semantic/18.cli-organization-ownership-apply-plan-file-required.ts +++ b/packages/spec/src/migrations/entries/semantic/18.cli-organization-ownership-apply-plan-file-required.ts @@ -10,21 +10,29 @@ export const entry: SemanticMigration = { 'os migrate organization-ownership --apply, invoked without --plan-file (the bare --apply --backup-taken that ' + '@objectstack/cli 18.0.0-next.1 shipped, with or without --fate-supplement)', replacement: - 'Run the plan first, `os migrate organization-ownership --out plan.json` (with the same `--fate-supplement`, ' - + 'under the same tenancy posture, against the same database), review the file it writes, then ' - + '`os migrate organization-ownership --apply --backup-taken --plan-file plan.json`. A script or runbook that ' - + 'applies directly gains the plan step and the flag; nothing in a package source or a stored row changes.', + 'nothing in 18.0: 18.0 refuses this invocation, as it refuses every plan and apply of ' + + '`os migrate organization-ownership` on every database (exit 1, `NOT_IMPLEMENTED`, nothing read or written). ' + + '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. A script or runbook that applies directly does not run ' + + 'against 18.0 at all. In that 18.x release, run the plan first, `os migrate organization-ownership --out plan.json` ' + + '(with the same `--fate-supplement`, under the same tenancy posture, against the same database), review the file ' + + 'it writes, then `os migrate organization-ownership --apply --backup-taken --plan-file plan.json`: the script or ' + + 'runbook gains the plan step and the flag; nothing in a package source or a stored row changes.', reason: 'ADR-0131 D10 makes the ceremony an operator\'s act on a plan the operator reviewed. The apply computes its ' + 'own plan at apply time, and that plan\'s inputs can move between the review and the run: a different host ' + 'fate supplement, another release\'s inventory, another tenancy posture or another database. Planning with ' + 'one supplement and applying with another ran the second one\'s fates unreviewed, including a mirror deletion ' - + 'the reviewed plan never listed. So the apply now reads the plan file the operator reviewed and refuses, before ' + + 'the reviewed plan never listed. So the 18.x apply reads the plan file the operator reviewed and refuses, before ' + 'anything is written, when its inventory digest, posture or database differs from the run\'s. Without the ' - + 'file there is nothing to compare, so the bare invocation is refused.', + + 'file there is nothing to compare, so the bare invocation is refused. 18.0 itself withholds the whole ' + + 'ceremony: it is knowingly incomplete in 18.0, and an incomplete ceremony must never certify a v17 database ' + + 'that the boot would then serve, so 18.0 refuses plan and apply alike before it reads anything.', acceptanceCriteria: - 'Every invocation of `os migrate organization-ownership --apply` passes `--plan-file` with the file a plan run ' - + 'wrote, and the run reports `reviewedPlan`. A run that answers `plan-file-required`, `plan-digest-mismatch`, ' + 'On 18.0, no script or runbook runs `os migrate organization-ownership`, and every v17 database stays on a 17.x ' + + 'release. In the 18.x release that carries the upgrade path, every invocation of ' + + '`os migrate organization-ownership --apply` passes `--plan-file` with the file a plan run wrote, and the run ' + + 'reports `reviewedPlan`. A run that answers `plan-file-required`, `plan-digest-mismatch`, ' + '`plan-posture-mismatch` or `plan-database-mismatch` has written nothing: plan again, review, and pass the new ' + 'file.', }; diff --git a/packages/spec/src/migrations/entries/semantic/18.sharing-rule-declared-mirror-retired.ts b/packages/spec/src/migrations/entries/semantic/18.sharing-rule-declared-mirror-retired.ts index 866a0484c75..d505bcbd80e 100644 --- a/packages/spec/src/migrations/entries/semantic/18.sharing-rule-declared-mirror-retired.ts +++ b/packages/spec/src/migrations/entries/semantic/18.sharing-rule-declared-mirror-retired.ts @@ -9,7 +9,7 @@ export const entry: SemanticMigration = { + 'the declared-rule seeder (`bootstrapDeclaredSharingRules`, @objectstack/plugin-sharing) is ' + 'retired. FROM one `managed_by: package` row per declared rule TO none: the sharing-rule ' + 'service reads each declared rule from the registry, its id is its name, and its grants carry ' - + 'that name as `sys_record_share.source_id`; the organization-ownership ceremony renames the ' + + 'that name as `sys_record_share.source_id`; the 18.x organization-ownership ceremony renames the ' + 'grants of the rows the seeder wrote, then deletes those rows, and Setup\'s Sharing Rules object ' + 'list (which lists rows) no longer shows declared rules. `DELETE /api/v1/sharing/rules/:idOrName` ' + 'on a declared rule: FROM 204 with the seeded row deleted (and written again by the next boot) ' @@ -17,8 +17,8 @@ export const entry: SemanticMigration = { replacement: 'change or remove the rule in its declaration in the package (the stack\'s `sharingRules`); ' + 'read declared rules through `GET /api/v1/sharing/rules`, which lists them beside the rules an ' - + 'organization authors. An organization\'s own rule is deleted as before. On an upgraded ' - + 'database run `os migrate organization-ownership --apply` with a fresh plan: its mirror-deletion ' + + 'organization authors. An organization\'s own rule is deleted as before. Existing databases: 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 18.x release, run `os migrate organization-ownership --apply` on the upgraded database with a fresh plan: its mirror-deletion ' + 'step removes the seeded copies', reason: 'ADR-0131 D2 retires the seeders: declared metadata is code, served from the registry, and a ' @@ -34,6 +34,6 @@ export const entry: SemanticMigration = { acceptanceCriteria: 'A fresh boot in every posture writes no `sys_sharing_rule` row for a declared rule and the rule ' + 'still grants; removing the declaration stops its grant; no consumer deletes a declared rule ' - + 'through the sharing-rule API or expects it as a `sys_sharing_rule` row; an upgraded database ' - + 'certifies only after the ceremony has deleted the seeded copies.', + + 'through the sharing-rule API or expects it as a `sys_sharing_rule` row. 18.0 upgrades no v17 database; in the ' + + '18.x release that carries the upgrade path, an upgraded database certifies only after its ceremony has deleted the seeded copies.', }; diff --git a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-audit-organization-column-retired.ts b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-audit-organization-column-retired.ts index cf4df3480d2..b39ad0129cd 100644 --- a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-audit-organization-column-retired.ts +++ b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-audit-organization-column-retired.ts @@ -18,15 +18,15 @@ export const entry: SemanticMigration = { replacement: 'nothing on this table — metadata is the environment\'s (ADR-0131 D6), and no organization owns ' + 'a row. Delete any authored filter, list-view column, report grouping, formula or seed key that ' - + 'names `organization_id` on `sys_metadata_audit`. Existing databases: run the v18 ceremony, ' - + '`os migrate organization-ownership --out PLAN` to write its plan for review, then ' + + 'names `organization_id` on `sys_metadata_audit`. Existing databases: 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 18.x release, run its ceremony: `os migrate organization-ownership --out PLAN` to write its plan for review, then ' + '`os migrate organization-ownership --apply --plan-file PLAN`, which promotes or reports the legacy ' + 'organization rows and then drops the physical column', reason: 'ADR-0131 D6 retired the per-organization overlay axis: every metadata write now lands ' + 'environment-wide with a NULL organization, every read is environment then code, and a legacy ' - + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column until the ceremony has run. The column therefore only holds ' - + 'the legacy rows the 17.x organization layer wrote, and the v18 ceremony owns those: under ' + + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column (18.0 on every such database; the 18.x release that carries the upgrade path until its ceremony has run). The column therefore only holds ' + + 'the legacy rows the 17.x organization layer wrote, and the 18.x ceremony owns those: under ' + 'single it promotes the presentational customizations to environment rows and carries every ' + 'public-form withdrawal onto the environment, fail-closed (the maintainer rulings on organization customizations and form withdrawals), and ' + 'it reports the rest. Only then does its column-drops step drop the column, through the ' @@ -40,6 +40,7 @@ export const entry: SemanticMigration = { acceptanceCriteria: 'No authored metadata names `organization_id` on `sys_metadata_audit`: the field resolver (lint and the data ' + 'door) answers it as an unknown field. A fresh database creates `sys_metadata_audit` with no organization ' - + 'column. On a legacy database, after `os migrate organization-ownership --apply --plan-file PLAN` the column is ' + + '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 18.x release, after `os migrate organization-ownership --apply --plan-file PLAN` on a legacy database the column is ' + 'gone and the boot no longer reports it orphaned.', }; diff --git a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-commit-organization-column-retired.ts b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-commit-organization-column-retired.ts index ae4d032c7b1..afc82e728a8 100644 --- a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-commit-organization-column-retired.ts +++ b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-commit-organization-column-retired.ts @@ -18,15 +18,15 @@ export const entry: SemanticMigration = { replacement: 'nothing on this table — metadata is the environment\'s (ADR-0131 D6), and no organization owns ' + 'a row. Delete any authored filter, list-view column, report grouping, formula or seed key that ' - + 'names `organization_id` on `sys_metadata_commit`. Existing databases: run the v18 ceremony, ' - + '`os migrate organization-ownership --out PLAN` to write its plan for review, then ' + + 'names `organization_id` on `sys_metadata_commit`. Existing databases: 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 18.x release, run its ceremony: `os migrate organization-ownership --out PLAN` to write its plan for review, then ' + '`os migrate organization-ownership --apply --plan-file PLAN`, which promotes or reports the legacy ' + 'organization rows and then drops the physical column', reason: 'ADR-0131 D6 retired the per-organization overlay axis: every metadata write now lands ' + 'environment-wide with a NULL organization, every read is environment then code, and a legacy ' - + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column until the ceremony has run. The column therefore only holds ' - + 'the legacy rows the 17.x organization layer wrote, and the v18 ceremony owns those: under ' + + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column (18.0 on every such database; the 18.x release that carries the upgrade path until its ceremony has run). The column therefore only holds ' + + 'the legacy rows the 17.x organization layer wrote, and the 18.x ceremony owns those: under ' + 'single it promotes the presentational customizations to environment rows and carries every ' + 'public-form withdrawal onto the environment, fail-closed (the maintainer rulings on organization customizations and form withdrawals), and ' + 'it reports the rest. Only then does its column-drops step drop the column, through the ' @@ -40,6 +40,7 @@ export const entry: SemanticMigration = { acceptanceCriteria: 'No authored metadata names `organization_id` on `sys_metadata_commit`: the field resolver (lint and the data ' + 'door) answers it as an unknown field. A fresh database creates `sys_metadata_commit` with no organization ' - + 'column. On a legacy database, after `os migrate organization-ownership --apply --plan-file PLAN` the column is ' + + '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 18.x release, after `os migrate organization-ownership --apply --plan-file PLAN` on a legacy database the column is ' + 'gone and the boot no longer reports it orphaned.', }; diff --git a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-history-organization-column-retired.ts b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-history-organization-column-retired.ts index c0102fcad61..cc8cc8b3f6e 100644 --- a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-history-organization-column-retired.ts +++ b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-history-organization-column-retired.ts @@ -18,15 +18,15 @@ export const entry: SemanticMigration = { replacement: 'nothing on this table — metadata is the environment\'s (ADR-0131 D6), and no organization owns ' + 'a row. Delete any authored filter, list-view column, report grouping, formula or seed key that ' - + 'names `organization_id` on `sys_metadata_history`. Existing databases: run the v18 ceremony, ' - + '`os migrate organization-ownership --out PLAN` to write its plan for review, then ' + + 'names `organization_id` on `sys_metadata_history`. Existing databases: 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 18.x release, run its ceremony: `os migrate organization-ownership --out PLAN` to write its plan for review, then ' + '`os migrate organization-ownership --apply --plan-file PLAN`, which promotes or reports the legacy ' + 'organization rows and then drops the physical column', reason: 'ADR-0131 D6 retired the per-organization overlay axis: every metadata write now lands ' + 'environment-wide with a NULL organization, every read is environment then code, and a legacy ' - + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column until the ceremony has run. The column therefore only holds ' - + 'the legacy rows the 17.x organization layer wrote, and the v18 ceremony owns those: under ' + + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column (18.0 on every such database; the 18.x release that carries the upgrade path until its ceremony has run). The column therefore only holds ' + + 'the legacy rows the 17.x organization layer wrote, and the 18.x ceremony owns those: under ' + 'single it promotes the presentational customizations to environment rows and carries every ' + 'public-form withdrawal onto the environment, fail-closed (the maintainer rulings on organization customizations and form withdrawals), and ' + 'it reports the rest. Only then does its column-drops step drop the column, through the ' @@ -40,6 +40,7 @@ export const entry: SemanticMigration = { acceptanceCriteria: 'No authored metadata names `organization_id` on `sys_metadata_history`: the field resolver (lint and the data ' + 'door) answers it as an unknown field. A fresh database creates `sys_metadata_history` with no organization ' - + 'column. On a legacy database, after `os migrate organization-ownership --apply --plan-file PLAN` the column is ' + + '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 18.x release, after `os migrate organization-ownership --apply --plan-file PLAN` on a legacy database the column is ' + 'gone and the boot no longer reports it orphaned.', }; diff --git a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-organization-column-retired.ts b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-organization-column-retired.ts index fa3ffbaa83f..bf086267686 100644 --- a/packages/spec/src/migrations/entries/semantic/18.sys-metadata-organization-column-retired.ts +++ b/packages/spec/src/migrations/entries/semantic/18.sys-metadata-organization-column-retired.ts @@ -18,15 +18,15 @@ export const entry: SemanticMigration = { replacement: 'nothing on this table — metadata is the environment\'s (ADR-0131 D6), and no organization owns ' + 'a row. Delete any authored filter, list-view column, report grouping, formula or seed key that ' - + 'names `organization_id` on `sys_metadata`. Existing databases: run the v18 ceremony, ' - + '`os migrate organization-ownership --out PLAN` to write its plan for review, then ' + + 'names `organization_id` on `sys_metadata`. Existing databases: 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 18.x release, run its ceremony: `os migrate organization-ownership --out PLAN` to write its plan for review, then ' + '`os migrate organization-ownership --apply --plan-file PLAN`, which promotes or reports the legacy ' + 'organization rows and then drops the physical column', reason: 'ADR-0131 D6 retired the per-organization overlay axis: every metadata write now lands ' + 'environment-wide with a NULL organization, every read is environment then code, and a legacy ' - + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column until the ceremony has run. The column therefore only holds ' - + 'the legacy rows the 17.x organization layer wrote, and the v18 ceremony owns those: under ' + + 'organization row is served by no read, and the v18 runtime refuses to start on a database still holding the column (18.0 on every such database; the 18.x release that carries the upgrade path until its ceremony has run). The column therefore only holds ' + + 'the legacy rows the 17.x organization layer wrote, and the 18.x ceremony owns those: under ' + 'single it promotes the presentational customizations to environment rows and carries every ' + 'public-form withdrawal onto the environment, fail-closed (the maintainer rulings on organization customizations and form withdrawals), and ' + 'it reports the rest. Only then does its column-drops step drop the column, through the ' @@ -40,6 +40,7 @@ export const entry: SemanticMigration = { acceptanceCriteria: 'No authored metadata names `organization_id` on `sys_metadata`: the field resolver (lint and the data ' + 'door) answers it as an unknown field. A fresh database creates `sys_metadata` with no organization ' - + 'column. On a legacy database, after `os migrate organization-ownership --apply --plan-file PLAN` the column is ' + + '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 18.x release, after `os migrate organization-ownership --apply --plan-file PLAN` on a legacy database the column is ' + 'gone and the boot no longer reports it orphaned.', }; diff --git a/packages/spec/src/migrations/entries/semantic/18.ups-permission-set-id-column-retired.ts b/packages/spec/src/migrations/entries/semantic/18.ups-permission-set-id-column-retired.ts index 96e5da404d4..4aa707db32f 100644 --- a/packages/spec/src/migrations/entries/semantic/18.ups-permission-set-id-column-retired.ts +++ b/packages/spec/src/migrations/entries/semantic/18.ups-permission-set-id-column-retired.ts @@ -21,7 +21,8 @@ export const entry: SemanticMigration = { replacement: '`permission_set`, the machine name of the permission set the grant holds (ADR-0131 D4). Delete ' + 'the key from any authored `sys_user_permission_set` seed row or data-door write that still ' - + 'carries it, and name the set instead. Existing databases: run the v18 ceremony. Plan it first, ' + + 'carries it, and name the set instead. Existing databases: 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 18.x release, run its ceremony. Plan it first, ' + '`os migrate organization-ownership --out plan.json`, and review the file it writes; then ' + '`os migrate organization-ownership --apply --backup-taken --plan-file plan.json` executes that plan: its verified ' + 'rewrite names every grant from the column and its column-drops step then drops the two retired ' @@ -30,7 +31,7 @@ export const entry: SemanticMigration = { 'ADR-0131 D4 makes every reference to a catalog item a name, and D3 retired the permission-set ' + 'catalog rows the id pointed at. Since then no writer fills the column and no reader confers ' + 'anything through it: a grant holds its set by permission_set. D10 orders the column\'s removal ' - + 'after every grant names its set, which is the v18 ceremony\'s verified id-to-name rewrite: it ' + + 'after every grant names its set, which is the 18.x ceremony\'s verified id-to-name rewrite: it ' + 'reads the physical column by raw SQL, names each grant, verifies every name against the ' + 'security catalog, and only then drops the column through the schema-drift machinery (schema ' + 'sync is additive, so an undeclared column stays until it is dropped). The boot-time name ' @@ -46,6 +47,7 @@ export const entry: SemanticMigration = { 'No authored stack seed or client write names `permission_set_id` on `sys_user_permission_set`: ' + 'the engine refuses the undeclared field with 400 INVALID_FIELD. A second grant of one set to ' + 'one user in one organization is refused by the unique index with 409 UNIQUE_VIOLATION, ' - + 'platform-wide grants (organization NULL) included, on every write path. On a legacy database, after `os migrate organization-ownership --apply` the column ' + + 'platform-wide grants (organization NULL) included, on every write path. 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 18.x release, after `os migrate organization-ownership --apply --backup-taken --plan-file plan.json` on a legacy database the column ' + 'is gone and the boot no longer reports it orphaned.', };