import type { DatabaseSyncLike } from '../../db.js'; import { type Context } from '../../api.js'; export type DlqBucket = 'parse_error' | 'unroutable' | 'signature_fail'; export interface DlqItem { id: number; tenantId: string; teamId: string | null; rawPayload: string; error: string; receivedAt: string; retriedAt: string | null; bucket: DlqBucket | string; retryCount: number; signature: string | null; slackTimestamp: string | null; } /** * v0.39 commit 3: writeToDlq is now bucket-aware. `bucket` defaults to * 'parse_error' to preserve the legacy single-arg call sites while letting * new callers tag rows for `hippo slack dlq replay` triage. * * `tenantId: null` means "no tenant resolved" (unroutable team). Stored as * the sentinel '__unroutable__' so the column stays NOT NULL — a mismatch * the listing CLI surfaces explicitly. */ export interface WriteDlqOpts { tenantId: string | null; rawPayload: string; error: string; bucket?: DlqBucket; teamId?: string | null; signature?: string | null; slackTimestamp?: string | null; } export declare function writeToDlq(db: DatabaseSyncLike, opts: WriteDlqOpts): number; export declare function listDlq(db: DatabaseSyncLike, opts: { tenantId: string; limit?: number; }): DlqItem[]; export declare function getDlqEntry(db: DatabaseSyncLike, id: number): DlqItem | null; export declare function markDlqRetried(db: DatabaseSyncLike, id: number): void; export interface ReplayDlqOpts { /** Skip signature verification when the row's signature/timestamp are missing or stale. */ force?: boolean; /** Current signing secret. If omitted, signature check is skipped (force-only path). */ signingSecret?: string; /** Now (unix seconds) override for tests. */ now?: number; /** Skew window override for tests. */ skewSeconds?: number; } export interface ReplayDlqResult { ok: boolean; status: string; memoryId: string | null; retryCount: number; reason?: string; } /** * Replay a DLQ row through the normal ingest path. Used by `hippo slack dlq * replay [--force]`. * * Behavior: * 1. SELECT the row. * 2. If signature + slack_timestamp are present and `signingSecret` is set, * re-verify with the CURRENT secret (not previous). Failure → bail unless * --force. Legacy rows from before v19 may have NULL signature; those * require --force to replay safely. * 3. Re-parse the raw_payload and dispatch to ingestMessage / handleMessageDeleted. * 4. On success: mark retried_at, increment retry_count. * 5. On failure: increment retry_count only, leave the row. * * The replay always uses the routing the deployment has NOW (current * slack_workspaces table + env), not whatever was in effect when the original * envelope was DLQed. That is intentional: the DLQ exists to be drained after * the operator fixed the routing. */ export declare function replayDlqEntry(ctx: Pick, id: number, opts?: ReplayDlqOpts): ReplayDlqResult; //# sourceMappingURL=dlq.d.ts.map