Per-order terminal reorg linkage
This commit is contained in:
@@ -11,7 +11,8 @@ const pageSchema = z.object({ streamId: z.string().uuid(), previousAnchor: hex,
|
||||
events: z.array(eventSchema).max(64), cursor: z.number().int().nonnegative().safe(),
|
||||
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 };
|
||||
export type CanonicalInboxResult = { streamId: string; cursor: number; head: number; height: number; tip: string;
|
||||
replayed: boolean; appendedEvents: z.infer<typeof eventSchema>[] };
|
||||
|
||||
export class CanonicalInboxError extends Error {
|
||||
readonly code: string;
|
||||
@@ -96,7 +97,7 @@ export async function ingestCanonicalPage(client: PoolClient, raw: unknown): Pro
|
||||
const savedAnchor = await anchorAt(client, page.cursor);
|
||||
if (page.cursor > cursor || savedAnchor !== page.anchor || page.previousAnchor !== page.anchor) throw new CanonicalInboxError('empty-cursor-mismatch');
|
||||
return { streamId: page.streamId, cursor, head: Math.max(page.head, cursor), height: stack.length,
|
||||
tip: stack.at(-1) ?? GENESIS_HASH, replayed: true };
|
||||
tip: stack.at(-1) ?? GENESIS_HASH, replayed: true, appendedEvents: [] };
|
||||
}
|
||||
const firstSequence = page.events[0].sequence;
|
||||
if (firstSequence > cursor + 1) throw new CanonicalInboxError('cursor-gap');
|
||||
@@ -104,6 +105,7 @@ export async function ingestCanonicalPage(client: PoolClient, raw: unknown): Pro
|
||||
if (!predecessor || page.previousAnchor !== predecessor) throw new CanonicalInboxError('cursor-anchor-mismatch');
|
||||
let priorAnchor = predecessor;
|
||||
let appended = false;
|
||||
const appendedEvents: z.infer<typeof eventSchema>[] = [];
|
||||
for (const e of page.events) {
|
||||
if (e.eventHash !== eventDigest(page.streamId, e, priorAnchor)) throw new CanonicalInboxError('event-hash-invalid');
|
||||
if (e.sequence <= cursor) {
|
||||
@@ -113,13 +115,13 @@ export async function ingestCanonicalPage(client: PoolClient, raw: unknown): Pro
|
||||
if (e.sequence !== cursor + 1 || priorAnchor !== anchor) throw new CanonicalInboxError('cursor-anchor-mismatch');
|
||||
applyTip(stack, e);
|
||||
await client.query('INSERT INTO wk_custody.custody_meta(key,value) VALUES($1,$2)', [eventKey(e.sequence), JSON.stringify(e)]);
|
||||
cursor = e.sequence; anchor = e.eventHash; appended = true;
|
||||
cursor = e.sequence; anchor = e.eventHash; appended = true; appendedEvents.push(e);
|
||||
}
|
||||
priorAnchor = e.eventHash;
|
||||
}
|
||||
if (page.cursor !== page.events.at(-1)!.sequence || page.anchor !== priorAnchor) throw new CanonicalInboxError('cursor-anchor-mismatch');
|
||||
return { streamId: page.streamId, cursor, head: Math.max(page.head, cursor), height: stack.length,
|
||||
tip: stack.at(-1) ?? GENESIS_HASH, replayed: !appended };
|
||||
tip: stack.at(-1) ?? GENESIS_HASH, replayed: !appended, appendedEvents };
|
||||
}
|
||||
|
||||
/** Full append-only inbox verification. Expected to run under the caller's coherent audit snapshot. */
|
||||
|
||||
Reference in New Issue
Block a user