/**
 * GitHub event ingest with afterWrite race-safe idempotency.
 *
 * Mirrors src/connectors/slack/ingest.ts. The dedupe key is sha256(eventName +
 * ':' + rawBody) (codex P0 #3) — derived from the signed body, not from the
 * unsigned X-GitHub-Delivery header, so a replay attacker cannot bypass
 * idempotency by rotating the delivery UUID.
 *
 * Race semantics (codex P1 #6):
 *   - Fast path: hasSeenKey pre-check returns 'duplicate' for the common case.
 *   - Slow path: hasSeenKey passes (no row yet). Two workers may race into
 *     remember() concurrently. Inside the writeEntry SAVEPOINT, INSERT OR
 *     IGNORE on github_event_log either inserts (changes=1, commit) or
 *     collides (changes=0, throw DuplicateIdempotencyError -> SAVEPOINT
 *     rolls back this worker's memory row). Exactly one memory exists per
 *     idempotency_key.
 *
 * The Slack precedent's race test was insufficient — it tested the fast path,
 * not the SAVEPOINT collision. The `__testInjectBeforeLog` hook below lets
 * tests pre-populate github_event_log inside the SAVEPOINT to actually
 * exercise the changes=0 -> rollback path.
 */
import { type Context } from '../../api.js';
import { type DatabaseSyncLike } from '../../db.js';
import type { GitHubIssueEvent, GitHubIssueCommentEvent, GitHubPullRequestEvent, GitHubPullRequestReviewCommentEvent } from './types.js';
export type IngestStatus = 'ingested' | 'duplicate' | 'skipped' | 'skipped_duplicate';
export interface IngestResult {
    status: IngestStatus;
    memoryId: string | null;
}
/**
 * Discriminated union of the four event shapes V1 ingests. The eventName
 * field MUST equal the X-GitHub-Event header value; computeIdempotencyKey
 * folds it into the dedupe key so the same body posted under two different
 * X-GitHub-Event headers produces two distinct keys (test 7).
 */
export type IngestEvent = {
    eventName: 'issues';
    payload: GitHubIssueEvent;
} | {
    eventName: 'issue_comment';
    payload: GitHubIssueCommentEvent;
} | {
    eventName: 'pull_request';
    payload: GitHubPullRequestEvent;
} | {
    eventName: 'pull_request_review_comment';
    payload: GitHubPullRequestReviewCommentEvent;
};
export interface IngestInput {
    /** The X-GitHub-Event header value + parsed body, discriminated. */
    event: IngestEvent;
    /** The raw HTTP body — used for the idempotency key (replay-safe per codex P0 #3). */
    rawBody: string;
    /** X-GitHub-Delivery header value, audit metadata only. */
    deliveryId: string;
    /**
     * Test-only hook fired inside the SAVEPOINT, AFTER the memory row is
     * inserted but BEFORE the github_event_log INSERT OR IGNORE. Tests pass
     * a function that pre-inserts the github_event_log row using the
     * provided db handle to simulate a concurrent worker winning the race.
     * Production callers leave this undefined.
     */
    __testInjectBeforeLog?: (db: DatabaseSyncLike, idempotencyKey: string) => void;
}
export declare function ingestEvent(ctx: Context, input: IngestInput): IngestResult;
//# sourceMappingURL=ingest.d.ts.map