Skip to content

Commit b5010d9

Browse files
committed
test(dogfood): ceremoniedFixture boots the 18.0 bytes once, refused, before the ceremony
The ceremony's sibling-moves step asks for the sibling logs this release added (sys_identity_email, sys_platform_setting_audit) rather than creating them, so the operator's sequence is a refused boot of this release first, then the plan and its apply. The shared helper now takes that boot and throws unless the ownership guard refused it; #24688's principal x door matrix uses it (25 cases, green). Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014UATXWqAXqkaZkbG92ox6V
1 parent 1699ec5 commit b5010d9

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

‎packages/qa/dogfood/test/identity-mail-read-gate.dogfood.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe('[#24625] identity-mail bodies over a ceremonied 18.0 database: princip
115115
};
116116

117117
beforeAll(async () => {
118-
const { file } = ceremoniedFixture(dir, fixtureSql, 'identity-mail-gate');
118+
const { file } = await ceremoniedFixture(dir, fixtureSql, 'identity-mail-gate');
119119
stack = await bootFixture(file);
120120
ql = await stack.kernel.getServiceAsync<any>('objectql');
121121

‎packages/qa/dogfood/test/upgrade-harness/ceremony.ts‎

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { copyFileSync, readFileSync } from 'node:fs';
1212
import { createRequire } from 'node:module';
1313
import { dirname, join } from 'node:path';
1414
import { fileURLToPath } from 'node:url';
15+
import { isOrganizationOwnershipBootRefusal } from '@objectstack/runtime';
16+
import { bootFixture } from './populate-fixture.js';
1517
import { loadSqlIntoSqlite } from './sqlite-text-dump.js';
1618

1719
const SHOWCASE_DIR = fileURLToPath(new URL('../../../../../examples/app-showcase/', import.meta.url));
@@ -41,13 +43,30 @@ export function runOwnershipCeremony(dir: string, file: string, tag: string): Re
4143

4244
/**
4345
* A copy of the 18.0 fixture the ceremony has certified, at `dir/<tag>.db`,
44-
* ready to boot under the guard. The ceremony runs on a working copy and the
45-
* certified bytes are copied out, so no boot ever opens the path the
46-
* ceremony's process held (the stale-image hazard the harness measured).
46+
* ready to boot under the guard — reached the way an operator reaches it.
47+
* First a boot of this release over the 18.0 bytes: the guard refuses it, and
48+
* its schema sync has already created the tables this release added (the
49+
* sibling logs the ceremony's `sibling-moves` step moves rows into), which the
50+
* ceremony asks for rather than creates. Then the plan and its apply. The
51+
* ceremony runs on a working copy and the certified bytes are copied out, so
52+
* no boot ever opens the path the ceremony's process held (the stale-image
53+
* hazard the harness measured). Throws when the first boot is not refused by
54+
* the ownership guard.
4755
*/
48-
export function ceremoniedFixture(dir: string, fixtureSql: string, tag: string): { file: string; report: Record<string, unknown> } {
56+
export async function ceremoniedFixture(dir: string, fixtureSql: string, tag: string): Promise<{ file: string; report: Record<string, unknown> }> {
4957
const work = join(dir, `${tag}.ceremony.db`);
5058
loadSqlIntoSqlite(fixtureSql, work);
59+
let refusal: unknown;
60+
try {
61+
const stack = await bootFixture(work);
62+
await stack.stop();
63+
} catch (error) {
64+
for (let e = error, depth = 0; !!e && typeof e === 'object' && depth < 8; e = (e as { cause?: unknown }).cause, depth++) {
65+
if (isOrganizationOwnershipBootRefusal(e)) refusal = e;
66+
}
67+
if (!refusal) throw error;
68+
}
69+
if (!refusal) throw new Error('the 18.0 fixture booted without the ceremony: the ownership guard did not refuse it');
5170
const report = runOwnershipCeremony(dir, work, tag);
5271
const file = join(dir, `${tag}.db`);
5372
copyFileSync(work, file);

0 commit comments

Comments
 (0)