export { rejectedForCaller, type RejectedForCaller } from './hook-rejected.js'; import { type HookOutcome } from './hook-contract.js'; type WebhookLane = 'FACTS' | 'ATTENTIONS'; /** * 훅 하나를 처리한다 — 찾고 · 확인하고 · 커넥터에게 옮기게 하고 · 유입으로 넘긴다. * * 유입 자체(`ingest`)는 부르는 쪽이 넘겨 준다: 이 파일이 엔진을 직접 부르면 시험할 때 엔진이 필요해지고, * 그러면 규약을 확인하는 시험을 쓸 수 없다. */ export declare function handleHook(args: { domainId: string; source: string; instanceId: string; headers: Record; body: unknown; /** * 받은 바이트 그대로 — 서명을 확인하려면 이것이 있어야 한다. * * 파싱한 객체를 다시 문자열로 만들면 키 순서와 공백이 달라져 서명이 맞지 않는다. 없으면 서명을 쓰는 * 요청은 거절된다(§`authorizeHook`). */ rawBody?: string; /** 서명 창을 재는 기준 시각. 부르는 쪽이 준다 — 여기서 읽으면 시험이 시계에 매인다. */ nowMs?: number; /** 레코드를 트윈에 넣는다 — 받은 수와 **떨어진 것들**을 돌려준다. */ ingest: (instanceId: string, records: unknown[], lane: WebhookLane) => IngestResult | Promise; /** * 구멍을 봤다 — **부르는 쪽이 무엇을 할지 정한다.** * * 여기서 backfill 을 직접 부르지 않는다. 이 파일은 `ingest`·`store` 를 인자로 받아 가볍게 유지한다 * (그래야 테스트가 엔진 없이 이 판정을 확인할 수 있다). backfill 을 import 하면 그 규율이 깨진다. * * 기다리지 않는 것도 부르는 쪽의 몫이다 — 훅의 응답이 늦으면 보내는 쪽이 되풀이한다. */ onGap?: (scope: string) => void; /** * 저장소를 대신 쓰는 자리 — **시험이 재기동을 넣을 수 있게.** * * `ingest` 를 부르는 쪽이 넘겨 주는 것과 같은 이유다(위 §). 커서는 재기동을 넘어 살아야 하는데, 한 * 프로세스 안에서만 확인하면 「적히나」는 보이지만 「다시 세우면 읽히나」는 안 보인다. 그 둘이 갈린 * 결함을 이 저장소가 이미 겪었다. */ store: HookStore; }): Promise; /** * 유입이 돌려주는 것. * * 떨어진 것을 **수가 아니라 목록으로** 받는다. 수만 받으면 보내는 쪽에 「몇 건이 떨어졌다」밖에 말할 수 * 없고, 그러면 무엇을 따로 두어야 할지 알 수 없어 배치 전체를 다시 보내거나 전부 버린다. */ export interface IngestResult { applied: number; duplicates: number; rejected: { record: unknown; errors: string[]; }[]; /** * How many records were vocabulary rather than events — **needed so the reply's sum closes.** * * `liveIngest` has counted this all along and this boundary dropped it, because the callback was * typed as `IngestResult` and vocabulary was not on it. So `offered` counted those records and * none of the other three did, and a sender checking the sum would have seen a loss on ordinary * traffic (§`WebhookResponse.offered`). * * Optional because an ingest that handles no vocabulary need not say zero, and a caller that * simply does not know must not be made to claim none. */ vocabulary?: number; } /** * 훅이 저장소에 닿는 두 자리 — 연결을 찾는 것과 커서를 적는 것. * * 이 둘만 밖으로 낸다. 나머지는 인자만 보고 답하므로 시험이 데이터베이스를 세우지 않아도 된다. */ export interface HookStore { load(domainId: string, source: string): Promise; saveCursor(refId: string, cursor: unknown): Promise; }