import { z } from 'zod'; import { type EventId, type Instant, type ModuleId } from './ids.js'; export declare const entityRef: z.ZodObject<{ entityType: z.ZodString; entityId: z.ZodString; }, z.core.$strip>; export type EntityRef = z.infer; export declare const piiClass: z.ZodEnum<{ direct: "direct"; none: "none"; pseudonymous: "pseudonymous"; }>; export type PiiClass = z.infer; export declare const eventType: z.ZodString; export declare const systemActor: z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>; /** * A CONNECTOR acted — an external provider's callback, effected through a * connection (#97). * * A third member rather than a synthetic principal, for the reason * `PlatformActorId` is branded separately from `PrincipalId`: a connector that * reads as a person in the audit trail is worse than one that cannot act at * all. The spine has to be able to say "Scrive did this" without naming a human * who did not. */ export declare const connectorActor: z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>; export declare const actor: z.ZodUnion, z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>, z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>]>; export type Actor = z.infer; /** * What authorized a mutation (K-34). Each entry is a permission the emitting operation * checked-and-passed; `grant` — present only when the allow resolved through a * `granted:` tuple (an entity or node capability grant) rather than a role bundle — * is that granting tuple's `object`, which names WHICH grant (e.g. `workorder:01J…`, * `scope:01J…`). Absent `grant` ⇒ authorized by a role. * * Kernel-stamped: module code can neither supply it (it is not on `DomainEventInput`) nor * suppress it. The full proof chain is deliberately NOT persisted — `explain` re-derives * chains on demand; what re-derivation cannot recover, once tuples have since changed, is * which permission and grant were consulted at write time. That pointer is what is kept. */ export declare const eventAuthorization: z.ZodObject<{ permission: z.core.$ZodBranded; grant: z.ZodOptional; }, z.core.$strip>; export type EventAuthorization = z.infer; export declare const domainEventInput: z.ZodObject<{ type: z.ZodString; schemaVersion: z.ZodNumber; entity: z.ZodObject<{ entityType: z.ZodString; entityId: z.ZodString; }, z.core.$strip>; piiClass: z.ZodEnum<{ direct: "direct"; none: "none"; pseudonymous: "pseudonymous"; }>; subjectId: z.ZodOptional>; payload: z.ZodUnknown; }, z.core.$strip>; export type DomainEventInput = z.infer; export declare const domainEvent: z.ZodObject<{ id: z.core.$ZodBranded; type: z.ZodString; schemaVersion: z.ZodNumber; occurredAt: z.core.$ZodBranded; tenantId: z.core.$ZodBranded; scopeId: z.core.$ZodBranded; actor: z.ZodUnion, z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>, z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>]>; entity: z.ZodObject<{ entityType: z.ZodString; entityId: z.ZodString; }, z.core.$strip>; piiClass: z.ZodEnum<{ direct: "direct"; none: "none"; pseudonymous: "pseudonymous"; }>; subjectId: z.ZodOptional>; authorization: z.ZodOptional; grant: z.ZodOptional; }, z.core.$strip>>>; impersonation: z.ZodOptional; by: z.core.$ZodBranded; }, z.core.$strip>>; operation: z.ZodOptional; payload: z.ZodUnknown; }, z.core.$strip>; export type DomainEvent = z.infer; /** * One entry of an entity's TIMELINE — the envelope of an event about it, and * nothing that was said (#800). * * Five demos hand-wrote the `SELECT` behind this and all five published a * different shape for it, which is the small half of the problem. The large half * is that two of the four fields are not what a reader of `_substrat_outbox` * assumes: * * - **`actor` is the union, not an id.** The writer persists * `JSON.stringify(actor)`, so a principal is stored WITH its quotes and a * system or connector actor is stored as an object. `SELECT actor` returns a * string that looks usable and is not — an agent building a timeline hit this * as a real bug and had to read the adapter to find it. Here the column is * decoded once, so a caller resolving a name gets the union the spine actually * recorded rather than a string to trim quotes off. * - **`id` is the entity's VERSION at this point** (#901), not just a row key. * The same token `versionOf` returns and `If-Match` compares, so "list the * history", "restore to this version" and "refuse my stale write" speak one * vocabulary. It is therefore the cursor: `ORDER BY id` is creation order * because `ulid()` is monotonic, and `OUTBOX_ENTITY_INDEX` makes the walk a * seek. */ export declare const timelineEntry: z.ZodObject<{ id: z.core.$ZodBranded; type: z.ZodString; occurredAt: z.core.$ZodBranded; actor: z.ZodUnion, z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>, z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>]>; }, z.core.$strip>; export type TimelineEntry = z.infer; /** * A timeline entry plus what a history VIEW needs — the second layer of #800. * * `timelineEntry` answers *Anna touched this at 14:02*. A history strip has to * answer *Anna changed Status from Lead to Customer*, and the outbox already * holds the rest of that. Two of these fields have a nullable that is a fact * rather than a gap: * * - **`payload` is null after an erasure.** A shred nulls the payload and keeps * the row (§5.3: "pseudonymous keys and transaction facts remain"), so a * history correctly degrades to "someone changed this, then". A renderer must * expect the null; it is a supported result, not an error. * - **`authorization` is null when UNRECORDED** — a row written before K-34 * added the column — which is a different fact from an empty list (checked * nothing). Keeping them distinct is the whole reason the column is nullable * in the DDL. * * Field-level "X → Y" is reconstructed by diffing consecutive payloads: nothing * stores a before-state. For the few fields a history strip actually shows * (status, owner, value), emitting the previous value explicitly in the fat * payload is more honest than making every reader diff — a per-vertical call. */ export declare const historyEntry: z.ZodObject<{ id: z.core.$ZodBranded; type: z.ZodString; occurredAt: z.core.$ZodBranded; actor: z.ZodUnion, z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>, z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>]>; payload: z.ZodUnknown; authorization: z.ZodNullable; grant: z.ZodOptional; }, z.core.$strip>>>; impersonation: z.ZodNullable; by: z.core.$ZodBranded; }, z.core.$strip>>; piiClass: z.ZodEnum<{ direct: "direct"; none: "none"; pseudonymous: "pseudonymous"; }>; subjectId: z.ZodNullable>; operation: z.ZodNullable; version: z.ZodNullable; causedBy: z.ZodNullable>; invocationId: z.ZodNullable; }, z.core.$strip>; export type HistoryEntry = z.infer; /** * Why a causal walk stopped (#1237). The whole value of the view is in telling these * apart, so it is a named reason rather than the absence of a next step. */ export declare const causeTerminal: z.ZodEnum<{ cycle: "cycle"; depth: "depth"; missing: "missing"; operation: "operation"; unrecorded: "unrecorded"; }>; export type CauseTerminal = z.infer; /** * One event's causal chain, newest first (#1237) — the walk backwards this whole * feature exists for: "this invoice exists; what started that?" * * `chain[0]` is the event asked about and each entry caused the one before it, so the * last entry is as far back as the spine can say. `terminal` says WHY it is the last, * and a reader must not treat the five reasons alike. */ export declare const causeChain: z.ZodObject<{ chain: z.ZodArray; type: z.ZodString; occurredAt: z.core.$ZodBranded; actor: z.ZodUnion, z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>, z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>]>; payload: z.ZodUnknown; authorization: z.ZodNullable; grant: z.ZodOptional; }, z.core.$strip>>>; impersonation: z.ZodNullable; by: z.core.$ZodBranded; }, z.core.$strip>>; piiClass: z.ZodEnum<{ direct: "direct"; none: "none"; pseudonymous: "pseudonymous"; }>; subjectId: z.ZodNullable>; operation: z.ZodNullable; version: z.ZodNullable; causedBy: z.ZodNullable>; invocationId: z.ZodNullable; }, z.core.$strip>>; terminal: z.ZodEnum<{ cycle: "cycle"; depth: "depth"; missing: "missing"; operation: "operation"; unrecorded: "unrecorded"; }>; }, z.core.$strip>; export type CauseChain = z.infer; /** * How one consumer's delivery of one event stands (#1237). * * `_substrat_deliveries.delivered_at` carries TWO readings — when a terminal row was * delivered, and when a still-retrying row was last attempted — because the column * predates retry state and is NOT NULL. A view that printed it as "delivered at" * would date a delivery that has not happened, so the state is resolved here and the * timestamp is labelled by it. */ export declare const deliveryState: z.ZodEnum<{ dead: "dead"; delivered: "delivered"; retrying: "retrying"; }>; export type DeliveryState = z.infer; export declare const eventDelivery: z.ZodObject<{ consumer: z.core.$ZodBranded; state: z.ZodEnum<{ dead: "dead"; delivered: "delivered"; retrying: "retrying"; }>; at: z.core.$ZodBranded; error: z.ZodNullable; attempts: z.ZodNumber; invocationId: z.ZodNullable; }, z.core.$strip>; export type EventDelivery = z.infer; /** * One event and what it set off (#1237) — the forward half of the causal spine, and * the honest answer to "expand this invocation". * * Assembled from what is already recorded rather than from spans: which consumers the * event reached (`_substrat_deliveries`), and which events they emitted in turn * (`caused_by`, #1437). What it is NOT is a timing waterfall — nothing in the platform * emits a span for an operation, a permission check or an engine call, so those steps * have no duration to draw and this does not pretend otherwise. */ export interface EventEffects { event: HistoryEntry; /** * The consumers this event reached. * * EMPTY IS AMBIGUOUS and the reader must be told so: no consumer declares this type, * or dispatch has not run yet. The delivery table records arrivals, not the absence * of them, and nothing here can tell the two apart. */ deliveries: EventDelivery[]; /** The events emitted in reaction to this one, each with its own effects. */ effects: EventEffects[]; } /** How far the forward walk got, with the same care as `causeTerminal`. */ export declare const effectsTerminal: z.ZodEnum<{ complete: "complete"; cycle: "cycle"; depth: "depth"; missing: "missing"; }>; export type EffectsTerminal = z.infer; export interface EffectsTree { root: EventEffects | null; terminal: EffectsTerminal; /** Events in the tree, the root included — what the cap was spent on. */ count: number; } /** * Everything one call emitted (#1237), oldest first — `readInvocation`'s answer. * * The read neither walk can make: the two follow cause, so both miss a SIBLING, and * two events one operation emitted independently are most of "what did this request * do". Consumers' emits in the same post-commit tail share the id and are included. */ export interface InvocationEvents { events: HistoryEntry[]; /** * The call did MORE than is shown. A different claim from "the call did this much", * and a reader must be told which one they are looking at. */ truncated: boolean; } /** * One delivery that gave up (#1525), with enough of its event to find it again — * `readDeadLetters`' entry. * * The scope-wide read `walkEventEffects` could not be: that walk reaches a delivery * only THROUGH its event, so a dead letter was visible only to someone who already knew * which record to open. An in-scope consumer does not retry, so one failure is terminal * and these rows wait for a human. * * No payload, deliberately. The envelope is enough to open the event's own reads, and a * list that decoded every payload would be a disclosure decision per row. */ export interface DeadLetter { eventId: EventId; eventType: string; occurredAt: Instant; /** The entity the event was about — what a reader opens next. */ entity: EntityRef; /** * The call the EVENT came from (#1237). Null for a seed or internal call, or an * event older than the column. * * It is not, in general, the call that attempted the delivery — see * `attemptInvocationId`, which is. This one said it was until #1525 put the * delivery's own id beside it, and the rows in this very list are where the two * come apart most often. */ invocationId: string | null; /** * The call the LAST attempt ran in (#1525) — the one that gave up, since these rows * are terminal. Pairs with `at`, which is when that attempt happened. * * Usually NOT `invocationId`: an executor's first attempt runs in the emitting * call's post-commit tail, and every retry after it in a drain that is a different * call or none. A row that exhausted its attempts therefore most often names a * later call, or null. An in-scope consumer does not retry, so for those two the * ids do agree — and that agreement is a fact about consumers, not a rule. * * Null is two facts: the attempt carried no call (a drain, an alarm, a seed), or * the row predates the column. */ attemptInvocationId: string | null; /** The consumer that gave up — a module id, or `executor:` for an executor. */ consumer: ModuleId; /** When it was last attempted, which for a dead row is when it gave up. */ at: Instant; error: string; attempts: number; } /** * One event as it leaves the scope for Tier 2 (#1334) — the exact-history lake * the master plan commits to (§5.3: "domain events → Pipelines → Iceberg on R2"). * * Everything the envelope holds, because the lake is where reporting, * reconciliation and audit are answered and a field dropped here cannot be * recovered later. In particular it carries: * * - **`subjectId`**, the pseudonymous erasure key. A shred erases Tier 1's * payload; the lake copy has to be reachable too, and this is the column that * makes "delete every row for this subject" expressible there. Shipping * payloads without it would put personal data somewhere an erasure cannot * follow — so the key travels with them, always. * - **`authorization`, `impersonation`, `operation`, `version`** — the K-34 chain, * the K-42 stamp and the signals dimensions, whose nulls stay facts on the way * out exactly as `historyEntry` documents them. * - **`causedBy`** (#1237) — the event this one was emitted in reaction to. Tier 2 * is where a causal walk over MANY scopes or a long history is answerable at * all, so the one column that makes the walk possible cannot be the one the * drain drops. It was: the outbox has carried `caused_by` since #1237 and the * generated stream schema declares it, while this shape did not — so the lake's * column would have been null on every row, reading as "nothing ever had a * cause" rather than "we never shipped it". The schema gate pins the declared * columns to the adapters' DDL; nothing pins them to what this type can supply. */ export declare const drainedEvent: z.ZodObject<{ id: z.core.$ZodBranded; type: z.ZodString; schemaVersion: z.ZodNumber; occurredAt: z.core.$ZodBranded; tenantId: z.core.$ZodBranded; scopeId: z.core.$ZodBranded; actor: z.ZodUnion, z.ZodObject<{ system: z.core.$ZodBranded; }, z.core.$strip>, z.ZodObject<{ connection: z.ZodString; }, z.core.$strip>]>; entity: z.ZodObject<{ entityType: z.ZodString; entityId: z.ZodString; }, z.core.$strip>; piiClass: z.ZodEnum<{ direct: "direct"; none: "none"; pseudonymous: "pseudonymous"; }>; subjectId: z.ZodOptional>; authorization: z.ZodOptional; grant: z.ZodOptional; }, z.core.$strip>>>; impersonation: z.ZodOptional; by: z.core.$ZodBranded; }, z.core.$strip>>; payload: z.ZodUnknown; operation: z.ZodNullable; version: z.ZodNullable; causedBy: z.ZodNullable>; invocationId: z.ZodNullable; }, z.core.$strip>; export type DrainedEvent = z.infer; /** * `redrainEvents` input (#1334): reopen rows stamped strictly before this instant. * * `instant`, so it is the same ISO 8601 shape `drained_at` holds and the adapters' string * comparison stays a time comparison. Required with no default on purpose — see the * contract in the kernel: the instant IS the guard against reopening rows that already * reached the rebuilt table. */ /** * How many rows one `redrainEvents` call reopens at most (#1334). * * The outbox is never pruned, so "every stamped row before an instant" is unbounded by * construction: on an old, busy scope a single UPDATE would scan and rewrite the whole * history, and on the Durable-Object host that is one request against a fixed budget — * it would fail, and fail again on every retry, so the scope could never make progress. * A bounded call always finishes, which is what makes the operation retryable at all. * * The protocol is therefore a LOOP, not a single shot: call until it returns 0. A call * that returns the cap has almost certainly left rows behind; one that returns fewer has * not, and the final 0 is the only proof the window is exhausted. */ export declare const REDRAIN_BATCH = 5000; /** * `countOnly` (#1545): answer how many rows the window holds and reopen NOTHING. * * Optional, and absent means the reopen this verb has always performed — so every caller * written before it keeps its behaviour. It exists because a dry run had no way to ask the * one question it is run to answer: `redrainEvents` only ever reopened, so a caller could * either learn the number by changing the rows or learn nothing. `pnpm lake:redrain * --dry-run` was the honest version of the second. * * A count is UNBOUNDED where the reopen is batched at `REDRAIN_BATCH`: an aggregate * materialises no rows, so the Durable-Object request budget that forces the batch does not * apply. It therefore answers for the WHOLE window in one call — which is also why it is not * comparable to a single reopen call's return value, only to the sum of the loop. */ export declare const redrainEventsInput: z.ZodObject<{ drainedBefore: z.core.$ZodBranded; countOnly: z.ZodOptional; }, z.core.$strip>; export type RedrainEventsInput = z.infer; //# sourceMappingURL=events.d.ts.map