|
| 1 | +// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. |
| 2 | + |
| 3 | +import type { SemanticMigration } from '../../types.js'; |
| 4 | + |
| 5 | +export const entry: SemanticMigration = { |
| 6 | + id: 'cli-organization-ownership-apply-plan-file-required', |
| 7 | + // No backticks in `surface`: build-upgrade-guide.ts renders it inside a code |
| 8 | + // span AND a table cell. |
| 9 | + surface: |
| 10 | + 'os migrate organization-ownership --apply, invoked without --plan-file (the bare --apply --backup-taken that ' |
| 11 | + + '@objectstack/cli 18.0.0-next.1 shipped, with or without --fate-supplement)', |
| 12 | + replacement: |
| 13 | + 'Run the plan first, `os migrate organization-ownership --out plan.json` (with the same `--fate-supplement`, ' |
| 14 | + + 'under the same tenancy posture, against the same database), review the file it writes, then ' |
| 15 | + + '`os migrate organization-ownership --apply --backup-taken --plan-file plan.json`. A script or runbook that ' |
| 16 | + + 'applies directly gains the plan step and the flag; nothing in a package source or a stored row changes.', |
| 17 | + reason: |
| 18 | + 'ADR-0131 D10 makes the ceremony an operator\'s act on a plan the operator reviewed. The apply computes its ' |
| 19 | + + 'own plan at apply time, and that plan\'s inputs can move between the review and the run: a different host ' |
| 20 | + + 'fate supplement, another release\'s inventory, another tenancy posture or another database. Planning with ' |
| 21 | + + 'one supplement and applying with another ran the second one\'s fates unreviewed, including a mirror deletion ' |
| 22 | + + 'the reviewed plan never listed. So the apply now reads the plan file the operator reviewed and refuses, before ' |
| 23 | + + 'anything is written, when its inventory digest, posture or database differs from the run\'s. Without the ' |
| 24 | + + 'file there is nothing to compare, so the bare invocation is refused.', |
| 25 | + acceptanceCriteria: |
| 26 | + 'Every invocation of `os migrate organization-ownership --apply` passes `--plan-file` with the file a plan run ' |
| 27 | + + 'wrote, and the run reports `reviewedPlan`. A run that answers `plan-file-required`, `plan-digest-mismatch`, ' |
| 28 | + + '`plan-posture-mismatch` or `plan-database-mismatch` has written nothing: plan again, review, and pass the new ' |
| 29 | + + 'file.', |
| 30 | +}; |
0 commit comments