Skip to content

Commit a3064ef

Browse files
committed
test(cli): fixtures standing in for an earlier release's database carry no birth marker; the #2178 NOT NULL drift re-keyed off the tenant column
Claude-Session: https://claude.ai/code/session_014UATXWqAXqkaZkbG92ox6V Co-authored-by: Claude <noreply@anthropic.com>
1 parent f1264d7 commit a3064ef

3 files changed

Lines changed: 30 additions & 8 deletions

File tree

‎packages/cli/src/commands/migrate/organization-ownership.report-file.integration.test.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,15 @@ async function bootServed(projectDir: string, dbFile: string): Promise<void> {
114114
await kernel.use(new PlatformObjectsPlugin() as any);
115115
await runtime.start();
116116
await kernel.shutdown();
117+
// This boot of THIS tree created the store from empty, so it wrote this
118+
// release's birth marker; the database it stands in for (an earlier
119+
// release's) carries none, and the cases below read the marker's absence.
120+
const db = new Database(dbFile);
121+
try {
122+
db.prepare('DELETE FROM sys_migration WHERE id = ?').run(ORGANIZATION_OWNERSHIP_MIGRATION_ID);
123+
} finally {
124+
db.close();
125+
}
117126
}
118127

119128
interface Prepared {

‎packages/cli/src/utils/organization-ownership-platform-global-column-drop.integration.test.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ async function bootV17(dbFile: string): Promise<void> {
193193
await kernel.use(osgcObjectsPlugin() as any);
194194
await runtime.start();
195195
await kernel.shutdown();
196+
// This boot of THIS tree created the store from empty, so it wrote this
197+
// release's birth marker; the v17 database it stands in for carries none,
198+
// and the drop gate below reads that absence.
199+
const db = new Database(dbFile);
200+
try {
201+
db.prepare(`DELETE FROM sys_migration WHERE id = 'adr-0131-organization-ownership'`).run();
202+
} finally {
203+
db.close();
204+
}
196205
}
197206

198207
/** A supplement row: `column-drop` for `drop`, `report` for every other host object. */

‎packages/cli/src/utils/schema-migrate.integration.test.ts‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,28 +42,32 @@ describe('bootSchemaStack + migrate engine (integration)', () => {
4242
name: 'mig_biz_unit',
4343
fields: {
4444
name: { type: 'text', required: true },
45-
organization_id: { type: 'text', required: false }, // optional now
45+
organization_id: { type: 'text', required: false },
46+
region: { type: 'text', required: false }, // optional now
4647
code: { type: 'text', unique: true }, // tenant-scoped since #3696
4748
},
4849
},
4950
],
5051
}),
5152
);
5253

53-
// Seed a "legacy" DB: organization_id NOT NULL (the #2178 shape) plus the
54-
// platform-wide unique index on `code` the pre-#3696 driver emitted.
54+
// Seed a "legacy" DB: an optional field's column NOT NULL (the #2178 shape,
55+
// re-keyed off `organization_id`, whose NOT NULL is the ownership
56+
// ceremony's and never drift) plus the platform-wide unique index on
57+
// `code` the pre-#3696 driver emitted.
5558
const seed = new SqlDriver({ client: 'better-sqlite3', connection: { filename: dbFile }, useNullAsDefault: true });
5659
const k = (seed as any).knex;
5760
await k.schema.createTable('mig_biz_unit', (t: any) => {
5861
t.string('id').primary();
5962
t.timestamp('created_at');
6063
t.timestamp('updated_at');
6164
t.string('name').notNullable();
62-
t.string('organization_id').notNullable();
65+
t.string('organization_id');
66+
t.string('region').notNullable();
6367
t.string('code');
6468
});
6569
await k.raw('CREATE UNIQUE INDEX mig_biz_unit_code_unique ON mig_biz_unit (code)');
66-
await k('mig_biz_unit').insert({ id: '1', name: 'Acme', organization_id: 'org1', code: 'BU-00001' });
70+
await k('mig_biz_unit').insert({ id: '1', name: 'Acme', organization_id: 'org1', region: 'emea', code: 'BU-00001' });
6771
await k.destroy();
6872

6973
savedEnv.OS_ARTIFACT_PATH = process.env.OS_ARTIFACT_PATH;
@@ -87,8 +91,8 @@ describe('bootSchemaStack + migrate engine (integration)', () => {
8791
// Boot changed nothing — this is exactly what `os migrate plan` renders.
8892
const drift = await stack.driver!.detectManagedDrift();
8993

90-
const org = drift.find((d) => d.table === 'mig_biz_unit' && d.column === 'organization_id');
91-
expect(org, 'expected drift on mig_biz_unit.organization_id').toBeDefined();
94+
const org = drift.find((d) => d.table === 'mig_biz_unit' && d.column === 'region');
95+
expect(org, 'expected drift on mig_biz_unit.region').toBeDefined();
9296
// ADR-0113: a column stricter than its declaration is needs_confirm —
9397
// reported by plan, applied by an explicit `os migrate apply` (the human
9498
// IS the confirmation), but never by dev auto-reconcile.
@@ -111,7 +115,7 @@ describe('bootSchemaStack + migrate engine (integration)', () => {
111115
expect(skipped).toHaveLength(0);
112116

113117
const after = await stack.driver!.detectManagedDrift();
114-
expect(after.find((d) => d.table === 'mig_biz_unit' && d.column === 'organization_id')).toBeUndefined();
118+
expect(after.find((d) => d.table === 'mig_biz_unit' && d.column === 'region')).toBeUndefined();
115119
expect(after.find((d) => d.op.type === 'replace_unique_index')).toBeUndefined();
116120

117121
// The seeded row survived the reconcile.

0 commit comments

Comments
 (0)