Strengthened the disposable reorg rehearsal

This commit is contained in:
2026-10-20 19:31:08 -04:00
parent 22da9764eb
commit 8cfcf6c025
6 changed files with 62 additions and 15 deletions
+22 -1
View File
@@ -12,7 +12,7 @@ const pageSchema = z.object({ streamId: z.string().uuid(), previousAnchor: hex,
head: z.number().int().nonnegative().safe(), caughtUp: z.boolean() }).strict();
export type CanonicalInboxPage = z.infer<typeof pageSchema>;
export type CanonicalInboxResult = { streamId: string; cursor: number; head: number; height: number; tip: string;
replayed: boolean; appendedEvents: z.infer<typeof eventSchema>[] };
replayed: boolean; appendedEvents: z.infer<typeof eventSchema>[]; reviewRequired?: boolean };
export class CanonicalInboxError extends Error {
readonly code: string;
@@ -127,4 +127,25 @@ export async function ingestCanonicalPage(client: PoolClient, raw: unknown): Pro
/** Full append-only inbox verification. Expected to run under the caller's coherent audit snapshot. */
export async function auditCanonicalInbox(client: PoolClient): Promise<void> {
await readCanonicalHistory(client);
const reviews = await client.query(`SELECT key,value FROM wk_custody.custody_meta
WHERE key LIKE 'sale-reorg-review:%' ORDER BY key`);
for (const row of reviews.rows) {
let record: unknown;
try { record = JSON.parse(row.value); } catch { throw new CanonicalInboxError('sale-review-record-invalid'); }
const schema = z.object({ version: z.literal(1), streamId: z.string().uuid(), orderId: z.string().uuid(),
terminalTransactionId: hex, stateRoot: hex, eventSequence: z.number().int().positive().safe(), eventHash: hex }).strict();
const parsed = schema.safeParse(record), keyMatch = /^sale-reorg-review:([a-f0-9-]{36}):(\d+)$/.exec(row.key);
if (!parsed.success || !keyMatch || keyMatch[1] !== parsed.data.orderId || Number(keyMatch[2]) !== parsed.data.eventSequence) {
throw new CanonicalInboxError('sale-review-record-invalid');
}
const event = await client.query('SELECT value FROM wk_custody.custody_meta WHERE key=$1',
[eventKey(parsed.data.eventSequence)]);
if (!event.rowCount) throw new CanonicalInboxError('sale-review-event-missing');
const disconnected = storedEvent(event.rows[0].value);
if (disconnected.type !== 'disconnect' || disconnected.eventHash !== parsed.data.eventHash ||
!disconnected.transactionIds.includes(parsed.data.terminalTransactionId)) {
throw new CanonicalInboxError('sale-review-event-mismatch');
}
}
if (reviews.rowCount) throw new CanonicalInboxError('posted-sale-terminal-disconnected');
}