import type { PaymentNotifier } from './checkout-flow.js'; import type { CommandAuthorityChannel } from './types.js'; /** * One place a payment notice can be sent, already resolved to a routable target. * * `backfillable` is a property of the CHANNEL, not of this send: it says whether * that channel's history can be re-read for a span the daemon was down. * `recoverInterruptedWindow` keys on it, so it travels with the delivery. */ export interface PaymentNoticeTarget { readonly channel: CommandAuthorityChannel; /** Whatever the router needs to address this surface. Opaque here. */ readonly request: unknown; readonly backfillable: boolean; } /** The narrow slice of `ChannelDeliveryRouter` this needs. */ export interface PaymentNoticeRouter { deliver(request: never): Promise; } /** * Where an answer comes back from. * * Separated from delivery because they are genuinely different directions and * different infrastructure: a send is a router call, an answer is an inbound * message arriving on a channel minutes later. A port keeps the window logic * testable without standing up an inbound pipeline. */ export interface PaymentReplySource { /** * Resolve with the first answer that arrives before the deadline, or null. * * Null must mean SILENCE and nothing else. An implementation that resolved * null on its own internal error would convert a failure into "the owner did not * object", which on the veto path buys something. */ waitForAnswer(input: { readonly kind: 'approval' | 'veto'; readonly deadlineMs: number; readonly channels: readonly CommandAuthorityChannel[]; }): Promise<{ readonly answer: 'approve' | 'deny' | 'acknowledge' | 'object'; readonly channel: CommandAuthorityChannel; } | null>; } export interface ChannelPaymentNotifierDeps { readonly router: PaymentNoticeRouter; readonly targets: readonly PaymentNoticeTarget[]; readonly replies: PaymentReplySource; /** Called with the reason a channel failed, for the operator log. Never the notice. */ readonly onDeliveryFailure?: ((input: { readonly channel: CommandAuthorityChannel; readonly reason: string; }) => void) | undefined; } /** * Read an inbound reply as an answer, or as nothing. * * The two maps are separate because the same word means opposite things: "stop" * on an approval is a denial and on a veto is an objection, and both happen to * refuse, but "go" is an approval on one and an acknowledgement on the other, * and those settle differently. */ export declare function parsePaymentReply(text: string, kind: 'approval' | 'veto'): 'approve' | 'deny' | 'acknowledge' | 'object' | null; /** * A notifier that really sends, over the same router that carries every other * channel message. * * One send per configured channel, all of them for the same notice, and the * report says per channel what happened. There is no retry: a purchase notice * that failed to send is information the window needs NOW, and a retry loop * would push the decision past the point where the total is still valid. */ export declare function createChannelPaymentNotifier(deps: ChannelPaymentNotifierDeps): PaymentNotifier; //# sourceMappingURL=notice-delivery.d.ts.map