import { type Firestore } from 'firebase-admin/firestore'; import { type ClaimDueDeliveriesInput, type DeliveryStore, type EnqueueDeliveryInput, type EnqueueDeliveryResult, type Iso8601, type ListDeliveriesFilter, type RecordAttemptInput, type RecordInboundEventResult, type WebhookDelivery } from 'stipend-mcp'; export interface FirestoreDeliveryStoreOptions { readonly firestore: Firestore; /** * Prefix prepended to every collection name. Useful in tests so that * concurrent runs against the same emulator don't see each other's * data. Defaults to no prefix. */ readonly collectionPrefix?: string; /** Override clock for deterministic tests. Defaults to `nowIso()`. */ readonly now?: () => Iso8601; /** * Optional async hook invoked at the top of every atomic section * (`enqueueDelivery`, `claimDueDeliveries`, `recordInboundEvent`). * Conformance tests inject this to exercise interleavings; production * callers must not supply it. Firestore retries transactions on * write contention, so the hook can fire more than once for the same * logical call. */ readonly beforeAtomicSection?: () => Promise | void; } /** * Firestore-backed {@link DeliveryStore}. * * Layout (mirrors the Phase 7 SESSION_NOTES sketch): * * - `delivery_outbound/{id}` — the main delivery doc. * - `delivery_outbound_idempotency/{idempotencyKey}` — pointer doc * `{deliveryId}`. `tx.create` collision detection on this doc is * what defends against double-enqueue on replay (mirrors the * consumption ledger's idempotency pattern). * - `delivery_inbound/{source}__{eventId}` — inbound event-id * dedup. `tx.create` collision = "we've already processed this * event"; the receiver short-circuits. * * The event payload is stored as a raw JSON string (`eventJson`) plus * separate scalar fields for the bits we need to query on (`eventType`). * Storing the payload as a string preserves canonical byte-for-byte * shape through Firestore — avoiding the round-trip noise that * Firestore's structured types (Timestamps, nested maps, undefined-as- * null promotion) inject into otherwise opaque host event payloads. * * Composite indexes required (declared in `firestore.indexes.json`): * - `(status, scheduledAt)` for `claimDueDeliveries`. * - `(status, createdAt)` for `listDeliveries` with status filter. * - `(eventType, createdAt)` for `listDeliveries` with eventType filter. */ export declare class FirestoreDeliveryStore implements DeliveryStore { private readonly db; private readonly prefix; private readonly now; private readonly beforeAtomicSection; constructor(options: FirestoreDeliveryStoreOptions); private col; private deliveryRef; private idempotencyRef; private inboundRef; enqueueDelivery(input: EnqueueDeliveryInput): Promise; getDelivery(id: string): Promise; claimDueDeliveries(input: ClaimDueDeliveriesInput): Promise; recordAttempt(input: RecordAttemptInput): Promise; listDeliveries(filter?: ListDeliveriesFilter): Promise; recordInboundEvent(source: string, eventId: string, eventType?: string): Promise; } //# sourceMappingURL=firestore-delivery-store.d.ts.map