@intenque/network-sdk 0.0.0-stage → 2.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +145 -0
- package/README.md +254 -2
- package/dist/capture/index.cjs +1 -0
- package/dist/capture/index.d.cts +57 -0
- package/dist/capture/index.d.ts +57 -0
- package/dist/capture/index.js +1 -0
- package/dist/cli/index.js +1745 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/constants-C_6Zxu_k.d.cts +20 -0
- package/dist/constants-C_6Zxu_k.d.ts +20 -0
- package/dist/react/index.cjs +3 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +421 -0
- package/dist/react/index.d.ts +421 -0
- package/dist/react/index.js +3 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/index.cjs +2 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +350 -0
- package/dist/server/index.d.ts +350 -0
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -0
- package/dist/styles.css +141 -0
- package/package.json +111 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/server/sign.ts","../../src/constants.ts","../../src/server/referral.ts","../../src/server/outbox.ts","../../src/server/wire.ts","../../src/server/delivery.ts","../../src/server/drain.ts","../../src/server/relay.ts","../../src/server/reporter.ts"],"names":["sha256Hex","data","createHash","hmacBase","timestamp","nonce","siteKey","keyId","method","path","body","signRequest","input","randomUUID","signature","createHmac","verifySignature","secret","expected","timingSafeEqual","SDK_VERSION","CLICK_ID_RE","clickId","v","scope","header","req","name","h","referralFromRequest","ref","r","c","s","first","referralMiddleware","_res","next","OUTBOX_DEFAULT_COLLECTION","OUTBOX_TTL_SECONDS","outboxSchemaDefinition","OUTBOX_INDEXES","outboxModel","mongoose","collection","existing","schema","indexed","indexWarned","indexing","ensureOutboxIndexes","model","warn","running","failed","keys","options","run","keyOf","k","rowOf","doc","e","createOutbox","entry","eventType","eventId","unauthorizedSince","rest","state","key","p","update","until","now","names","same","a","b","applyPatch","createMemoryOutbox","entries","find","x","i","due","createSpill","max","map","oldest","evicted","moveSpill","spill","outbox","moved","inserted","CONVERSION_TYPES","REVERSAL_TARGETS","LINK_TARGETS","REVERSAL_TYPES","CONVERSION_BODY_RULES","AMOUNT_MAX_CENTS","EVENT_ID_RE","CURRENCY_RE","SITE_SECRET_RE","KEY_ID_RE","SITE_KEY_RE","SIGNED_PATHS","isLinkedType","t","amountOk","rule","SEC","RETRY_DELAYS_MS","IN_PROCESS_MAX_DELAY_MS","RETRY_AFTER_CAP_MS","AFTER_RETRIES_MS","UNAUTHORIZED_RETRY_MS","UNAUTHORIZED_MAX_MS","LEASE_MS","TIMEOUT_DEFAULT_MS","TIMEOUT_MIN_MS","TIMEOUT_MAX_MS","RESPONSE_MAX_BYTES","WRITE_TIMEOUT_MS","SKEW_MAX_OFFSET_MS","hubOrigin","raw","u","timeoutMsOf","opt","envValue","n","classifyResponse","status","code","parseRetryAfter","value","nowMs","at","clockOffsetMs","estimateOffsetMs","dateHeader","tSend","tRecv","hub","offset","readCapped","res","reader","dec","text","done","errorCodeOf","json","sendSigned","cfg","timeoutMs","headers","ctl","timer","drainBackoffMs","attempts","base","sleep","ms","resolve","bounded","work","createDelivery","deps","logger","once","warnOnce","outcomeOf","kind","request","out","attempt","remove","drop","error","reason","settle","retryInMs","retry","inMs","rejectedAt","patch","spilled","since","chain","retryAfter","delay","kept","DRAIN_FIRST_MS","DRAIN_EVERY_MS","DRAIN_JITTER_MS","DRAIN_BATCH","DRAIN_EXPIRE_MS","CLOSE_WAIT_MS","createDrainer","delivery","closed","tick","row","drainNow","schedule","pending","MIN","RELAY_MAX_BYTES","RELAY_PER_IP_PER_MIN","RELAY_PER_PROCESS_PER_MIN","D_MAX_MS","UA_MAX","ORIGIN_RE","readText","buf","chunks","size","inputOf","relayBody","visitorIp","ph","d","origin","window","total","perIp","allow","ip","w","createRelay","warned","opts","trusted","isIP","ISO_DATETIME_RE","ENQUEUE_TIMEOUT_MS","OUTBOX_WARN_EVERY_MS","buildConversionBody","event","type","occurred","occurredAt","valueCents","feeCents","rules","currency","reverses","targets","REQUIRED_ENV","ENV_FORMAT","verifyEnv","env","problems","production","message","createConversionReporter","site","m","meta","enabled","indexes","hubUrlWarned","rawHub","hubUrl","inflight","track","err","start","idle","outboxWarnedAt","unavailable","drainer","forget","fail","ra","enqueue","written"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Conversion request signing — spec §5.4 as amended by the 2.2 changelog (addendum \"HMAC base string\"):\n * `X-INR-Signature: v1=<hex HMAC-SHA256(secret, timestamp + \".\" + nonce + \".\" + siteKey + \".\" + keyId + \".\" + METHOD\n * + \".\" + path + \".\" + sha256hex(rawBody))>` with `X-INR-Site`, `X-INR-Key-Id`, `X-INR-Timestamp` (unix seconds),\n * `X-INR-Nonce` (uuid v4). Mirrors packages/shared `hmacBaseV1` without importing it; the committed vectors\n * (packages/shared/fixtures/hmac-v1.vectors.json) pin both. Exported for sites with non-Node backends to port (§6.5).\n * Node-only.\n */\nimport { createHash, createHmac, randomUUID, timingSafeEqual } from 'node:crypto'\n\nexport type SignInput = {\n secret: string\n siteKey: string\n keyId: string\n method: string\n /** Path only (`/v1/conversions`, `/v1/conversions/ping`, `/v1/referrals/<clickId>`, `/v1/landings`). */\n path: string\n /** The exact bytes sent (`''` for an empty body). */\n body: string | Uint8Array\n /** Unix seconds; defaults to now. */\n timestamp?: number\n /** uuid v4; defaults to a fresh one. Every attempt re-signs with a fresh nonce (§6.5). */\n nonce?: string\n}\n\nexport type SignedHeaders = {\n 'Content-Type': 'application/json'\n 'X-INR-Site': string\n 'X-INR-Key-Id': string\n 'X-INR-Timestamp': string\n 'X-INR-Nonce': string\n 'X-INR-Signature': string\n}\n\nexport function sha256Hex(data: string | Uint8Array): string {\n return createHash('sha256').update(data).digest('hex')\n}\n\n/** The v1 HMAC base string: the identifiers are bound, so a signature never verifies under another site or key. */\nexport function hmacBase(\n timestamp: number,\n nonce: string,\n siteKey: string,\n keyId: string,\n method: string,\n path: string,\n body: string | Uint8Array,\n): string {\n return `${timestamp}.${nonce}.${siteKey}.${keyId}.${method.toUpperCase()}.${path}.${sha256Hex(body)}`\n}\n\nexport function signRequest(input: SignInput): {\n headers: SignedHeaders\n timestamp: number\n nonce: string\n signature: string\n} {\n if (!input.secret) throw new Error('signRequest: secret is required')\n const timestamp = input.timestamp ?? Math.floor(Date.now() / 1000)\n const nonce = input.nonce ?? randomUUID()\n const mac = createHmac('sha256', input.secret)\n .update(\n hmacBase(timestamp, nonce, input.siteKey, input.keyId, input.method, input.path, input.body),\n 'utf8',\n )\n .digest('hex')\n const signature = `v1=${mac}`\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'X-INR-Site': input.siteKey,\n 'X-INR-Key-Id': input.keyId,\n 'X-INR-Timestamp': String(timestamp),\n 'X-INR-Nonce': nonce,\n 'X-INR-Signature': signature,\n },\n timestamp,\n nonce,\n signature,\n }\n}\n\n/** Constant-time check of a `v1=<hex>` signature (what the hub does; here for tests and ports). */\nexport function verifySignature(\n secret: string,\n input: {\n timestamp: number\n nonce: string\n siteKey: string\n keyId: string\n method: string\n path: string\n body: string | Uint8Array\n },\n signature: string,\n): boolean {\n if (!/^v1=[0-9a-f]{64}$/.test(signature)) return false\n const { timestamp, nonce, siteKey, keyId, method, path, body } = input\n const expected = createHmac('sha256', secret)\n .update(hmacBase(timestamp, nonce, siteKey, keyId, method, path, body), 'utf8')\n .digest('hex')\n return timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(signature.slice(3), 'hex'))\n}\n","/**\n * Network-wide constants the SDK must agree on with the hub (packages/shared/src/constants.ts) — spec §4.2, §4.3,\n * §4.5, §5.3, §6.1. Kept in a dependency-free file so every entry (react, capture, server, cli) can import it without\n * pulling the others in.\n */\n\n/** Semver of this package; SDK major = manifest schema major (§6.1). Bumped by the version script. */\nexport const SDK_VERSION = '2.2.0-beta.2'\n/** `schema` this SDK reads (§4.3). A greater major → failure → fallback. */\nexport const MANIFEST_SCHEMA_MAJOR = 2\n/**\n * §6.1 compiled `DEFAULT_CDN_BASE`: the production manifest base. Decision 15: default DigitalOcean domains until the\n * agency domain exists, so this is the Spaces CDN default endpoint plus the production prefix (`network/v1`). It is\n * only the last resort for a site with no committed fallback (§4.2 URL precedence: `config.manifestUrl ??\n * (config.cdnBase ?? fallback.cdnBase ?? DEFAULT_CDN_BASE)`); a domain cutover is a publish + `sync-fallback`, not an\n * SDK release.\n */\nexport const DEFAULT_CDN_BASE =\n 'https://inr-network-public.nyc3.cdn.digitaloceanspaces.com/network/v1'\n/** §4.3 \"hard fail at publish if > 24 KB\": the verifier refuses larger input before parsing. */\nexport const MANIFEST_MAX_BYTES = 24 * 1024\n/** §4.5 SDK step 2: 7 d grace after `notAfter`. */\nexport const SIGNER_GRACE_MS = 7 * 86_400_000\n/** §4.6 SDK fetch: 4 s timeout through an AbortController. */\nexport const FETCH_TIMEOUT_MS = 4000\n/** §5.3 referral query parameter and storage key. */\nexport const REFERRAL_PARAM = 'inr'\nexport const REFERRAL_STORAGE_KEY = 'inr_ref'\n/** §5.3: a referral older than 30 d is ignored. */\nexport const REFERRAL_TTL_MS = 30 * 86_400_000\nexport const CLICK_ID_RE = /^[A-Za-z0-9_-]{32}$/\n/** §6.3 UTM defaults, used only when no manifest is loaded (the manifest's `links` win). */\nexport const UTM = { medium: 'network', campaign: 'cross-promo' } as const\n\n// §5.1 signals — the SDK-side copies of the hub's `ANALYTICS_LIMITS` / `HEADLESS_BITS` / `CLIENT_FLAGS`\n// (packages/shared); `test/signals-contract.test.ts` asserts they agree, so neither side can drift.\n/** The impression goes 10 s after the section first became visible, unless a click, `hidden` or `pagehide` came first. */\nexport const IMPRESSION_TIMER_MS = 10_000\n/**\n * Decision row 6 (\"precise claim\", §6.3): a link rewritten with `inr=<clickId>` returns to its at-rest href (UTMs only)\n * this long after the gesture ends (pointerup / pointercancel, or the click / context menu / drag that used it), or at\n * once on blur (release 2b review round 2).\n */\nexport const HREF_RESTORE_MS = 2_000\n/** `seen` = ≥ 50 % visible for ≥ 1000 ms continuous (section and card alike). */\nexport const SEEN_MS = 1000\n/** The hub's `no_section_seen` threshold (`sm < 300`, §5.2 step 5): a click re-sends the impression when it crossed it. */\nexport const NO_SECTION_SEEN_MS = 300\nexport const VISIBLE_RATIO = 0.5\n/** Every `ms` / `sm` / `fv` offset is bounded to one day, `vp.w/h` to 20 000, `items` to 24, `fl` to 8 (§2.4). */\nexport const SIGNAL_MS_MAX = 86_400_000\nexport const SIGNAL_VP_MAX = 20_000\nexport const SIGNAL_ITEMS_MAX = 24\nexport const SIGNAL_FLAGS_MAX = 8\n/** The hub refuses bodies over 4 KB (413); the SDK trims never-visible cards before it gets there. */\nexport const SIGNAL_BODY_MAX = 4096\n/**\n * Impression sends per page view (first send + re-sends at the end of later visibility episodes). Below the hub's 20\n * (`sendsMax`, beyond which a page view is `dup_pv` / suspect), so a visitor who switches tabs all afternoon never\n * turns a real page view suspect.\n */\nexport const IMPRESSION_SENDS_MAX = 10\n/** Click ids remembered per page view to send each one once (a `contextmenu` then `auxclick`, a doubled handler). */\nexport const CLICK_IDS_REMEMBERED = 64\n/** §2.4 `hd` bitmask bits (client signals); the hub treats `webdriver | headlessUa` as `bot`. */\nexport const HEADLESS_BITS = {\n webdriver: 1,\n noLanguages: 2,\n zeroPlugins: 4,\n headlessUa: 8,\n noOuterWindow: 16,\n} as const\n/**\n * §5.1 flags the SDK reports on the next impression (`fl`): the §2.4 vocabulary the directory loader can set. The\n * loader's `sig_revoked` travels as `sig_fail` (a revoked kid is a signature failure; §2.4 has no `sig_revoked`) and\n * the SDK-local `fetch_fail` / `insecure_context` are never transmitted.\n */\nexport const CLIENT_FLAGS = [\n 'sig_fail',\n 'rev_rollback',\n 'stale_cache',\n 'fallback_invalid',\n 'fallback_key_expired',\n 'sitekey_from_fallback',\n 'sdk_outdated',\n] as const\nexport type ClientFlag = (typeof CLIENT_FLAGS)[number]\n/** §4.6 fallback file path inside a site repo. */\nexport const FALLBACK_PATH = 'src/data/network.fallback.json'\nexport const CONFIG_PATH = 'src/network.config.js'\n\nexport type SiteChannel = 'production' | 'preview'\n\n/** §4.2: the alias URL for a site. */\nexport function manifestUrlFor(cdnBase: string, siteKey: string, channel: SiteChannel): string {\n return `${cdnBase.replace(/\\/+$/, '')}/${channel === 'preview' ? 'preview/' : ''}sites/${siteKey}/manifest.json`\n}\n","/**\n * `referralFromRequest(req)` / `referralMiddleware()` — spec §5.3 / §6.5: body `inrRef` first (`attachReferral` body\n * mode), then the `X-INR-Ref*` headers (header mode); validated, ≤ 32 chars. Returns `null` when absent or invalid.\n * `referralFromRequest` is pure; the middleware also strips the body's `inrRef`.\n */\nimport { CLICK_ID_RE } from '../constants.js'\n\nexport type ReferralRef = {\n clickId: string\n firstClickId: string | null\n tokenScope: 'session' | 'persistent'\n}\n\ntype ReqLike = {\n body?: unknown\n headers?: Record<string, unknown> | undefined\n get?: (name: string) => string | undefined\n}\n\nconst clickId = (v: unknown): string | null =>\n typeof v === 'string' && CLICK_ID_RE.test(v) ? v : null\nconst scope = (v: unknown): ReferralRef['tokenScope'] | null =>\n v === 'session' || v === 'persistent' ? v : null\n\nfunction header(req: ReqLike, name: string): unknown {\n if (typeof req.get === 'function') return req.get(name)\n const h = req.headers\n if (!h) return undefined\n const v = h[name] ?? h[name.toLowerCase()]\n return Array.isArray(v) ? v[0] : v\n}\n\nexport function referralFromRequest(req: ReqLike): ReferralRef | null {\n try {\n const body = req.body\n const ref =\n body && typeof body === 'object' ? (body as Record<string, unknown>)['inrRef'] : undefined\n if (ref && typeof ref === 'object') {\n const r = ref as Record<string, unknown>\n const c = clickId(r['clickId'])\n const s = scope(r['tokenScope'])\n if (c && s) {\n const first = r['firstClickId']\n return {\n clickId: c,\n firstClickId: first == null ? null : clickId(first),\n tokenScope: s,\n }\n }\n }\n const c = clickId(header(req, 'X-INR-Ref'))\n const s = scope(header(req, 'X-INR-Ref-Scope'))\n if (c && s) {\n const first = header(req, 'X-INR-Ref-First')\n return { clickId: c, firstClickId: first == null ? null : clickId(first), tokenScope: s }\n }\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Express middleware alternative: sets `req.inrRef` (`ReferralRef | null`), then removes an own `inrRef` from any\n * object body (valid or not; plain objects, arrays and class instances alike), so `new Model(req.body)` and strict\n * validators never see it (2.2 changelog). A body that cannot be changed (frozen, a throwing proxy) keeps it and never\n * throws.\n */\nexport function referralMiddleware() {\n return (req: ReqLike & { inrRef?: ReferralRef | null }, _res: unknown, next: () => void) => {\n req.inrRef = referralFromRequest(req)\n try {\n // own properties only (an inherited inrRef is not the body's); a primitive or null body throws, a frozen one\n // returns false: either way it is left as it is\n Reflect.deleteProperty(req.body as object, 'inrRef')\n } catch {\n // not an object\n }\n next()\n }\n}\n","/**\n * Mongo outbox for conversion reports — spec §6.5: collection `inrConversionOutbox` (TTL 14 d, matching the hub's\n * `occurredAt` lower bound), one row per `(eventType, eventId)`, storing the UNSIGNED body (every attempt re-signs\n * with a fresh timestamp and nonce). `nextAttemptAt` is the lease (addendum \"Claim and lease\"); `unauthorizedSince`\n * carries the 24 h rule of 401, missing config and misrouted answers (403, 404, a 3xx). The site passes its own `mongoose` (7 or 8; the model API used is identical on both); the\n * SDK has no runtime dependency on it. The schema declares no index and has `autoIndex: false`: `ensureOutboxIndexes`\n * creates the three helper indexes itself (addendum \"Outbox row v2 and indexes\"). The bounded in-memory spill holds\n * reports whose enqueue failed or timed out (addendum \"`report()`\").\n */\nexport const OUTBOX_DEFAULT_COLLECTION = 'inrConversionOutbox'\nexport const OUTBOX_TTL_SECONDS = 14 * 86_400\n/** The in-memory spill bound; beyond it the oldest entry is dropped as `memory_full`. */\nexport const SPILL_MAX = 1000\n\n/** The last failed attempt: HTTP status (0 for transport failures and missing config) and the hub's error code. */\nexport type OutboxError = { status: number; code: string | null }\n\nexport type OutboxEntry = {\n eventType: string\n eventId: string\n body: Record<string, unknown>\n attempts: number\n nextAttemptAt: Date\n lastStatus: number | null\n lastError: OutboxError | null\n /** Set by the first 401, missing config or misrouted answer (403, 404, a 3xx); cleared by any other. */\n unauthorizedSince: Date | null\n createdAt: Date\n}\n\nexport type OutboxKey = Pick<OutboxEntry, 'eventType' | 'eventId'>\n\n/** What a retried attempt writes back; `attempts` is the number of attempts this sender made. */\nexport type ReschedulePatch = {\n nextAttemptAt: Date\n lastStatus: number\n lastError: OutboxError\n attempts: number\n /** The 401 / missing-config clock: kept at its earliest value; `null` clears it. */\n unauthorizedAt: Date | null\n}\n\n/** The subset of mongoose the outbox touches (so tests can pass a stub and the SDK stays dependency-free). */\nexport type MongooseLike = {\n Schema: new (definition: Record<string, unknown>, options?: Record<string, unknown>) => unknown\n models: Record<string, unknown>\n model: (name: string, schema?: unknown, collection?: string) => unknown\n}\n\ntype Thenable<T> = Promise<T> | { exec: () => Promise<T> }\ntype Filter = Record<string, unknown>\n\n/** The model methods used (addendum \"Mongoose 7 and 8\"). */\nexport type OutboxModelLike = {\n updateOne: (filter: Filter, update: Filter, options?: Filter) => Thenable<unknown>\n findOneAndUpdate?: (filter: Filter, update: Filter, options?: Filter) => Thenable<unknown>\n deleteOne?: (filter: Filter) => Thenable<unknown>\n deleteMany?: (filter: Filter) => Thenable<unknown>\n countDocuments: (filter?: Filter) => Thenable<number>\n collection?: { createIndex: (keys: Filter, options?: Filter) => Promise<unknown> }\n}\n\nexport function outboxSchemaDefinition(): Record<string, unknown> {\n return {\n eventType: { type: String, required: true },\n eventId: { type: String, required: true },\n body: { type: Object, required: true },\n attempts: { type: Number, default: 0 },\n nextAttemptAt: { type: Date, default: Date.now },\n lastStatus: { type: Number, default: null },\n lastError: { type: Object, default: null },\n // no default and never stored as null: `$min` keeps a null (BSON orders it before every date)\n unauthorizedSince: { type: Date },\n createdAt: { type: Date, default: Date.now },\n }\n}\n\n/** The three helper indexes (default names), created by `ensureOutboxIndexes`, never by `autoIndex`. */\nexport const OUTBOX_INDEXES: readonly [Filter, Filter][] = [\n [{ createdAt: 1 }, { expireAfterSeconds: OUTBOX_TTL_SECONDS }],\n [{ nextAttemptAt: 1 }, {}],\n [{ eventType: 1, eventId: 1 }, { unique: true }],\n]\n\n/** Builds (or reuses) the outbox model on the given mongoose instance. */\nexport function outboxModel(\n mongoose: MongooseLike,\n collection: string = OUTBOX_DEFAULT_COLLECTION,\n): OutboxModelLike {\n const name = `InrOutbox_${collection}`\n const existing = mongoose.models[name]\n if (existing) return existing as OutboxModelLike\n const schema = new mongoose.Schema(outboxSchemaDefinition(), {\n versionKey: false,\n autoIndex: false,\n })\n return mongoose.model(name, schema, collection) as OutboxModelLike\n}\n\nconst indexed = new WeakSet<object>()\nconst indexWarned = new WeakSet<object>()\nconst indexing = new WeakMap<object, Promise<void>>()\n/**\n * Creates the helper indexes (`collection.createIndex`, so `autoIndex: false` sites get them too): each one on its\n * own, so a conflict on one leaves the others created. Called at construction and at every drain tick until all three\n * succeed (a reporter built before `mongoose.connect()` times out its first try). Failures are one warn\n * `INR_OUTBOX_INDEX_FAILED` per process and model; reporting goes on without them.\n */\nexport function ensureOutboxIndexes(\n model: OutboxModelLike,\n warn: (message: string) => void,\n): Promise<void> {\n if (indexed.has(model)) return Promise.resolve()\n let running = indexing.get(model)\n if (!running) {\n running = (async () => {\n // one after the other (concurrent builds on a new collection contend), each failure on its own\n let failed = false\n for (const [keys, options] of OUTBOX_INDEXES)\n await Promise.resolve()\n .then(() => model.collection!.createIndex(keys, options))\n .catch(() => (failed = true))\n if (!failed) indexed.add(model)\n else if (!indexWarned.has(model)) {\n indexWarned.add(model)\n warn('INR_OUTBOX_INDEX_FAILED')\n }\n })().finally(() => indexing.delete(model))\n indexing.set(model, running)\n }\n return running\n}\n\nconst run = <T>(r: Thenable<T>): Promise<T> =>\n 'exec' in r && typeof r.exec === 'function' ? r.exec() : (r as Promise<T>)\n\nexport type Outbox = {\n /**\n * Idempotent on `(eventType, eventId)`: inserts the entry's whole state once; a repeat leaves the existing row\n * alone. Resolves `true` when this call inserted the row.\n */\n enqueue: (entry: OutboxEntry) => Promise<boolean>\n /** Success or a drop. */\n remove: (key: OutboxKey) => Promise<void>\n /** A retried attempt. Never creates a row. */\n reschedule: (key: OutboxKey, patch: ReschedulePatch) => Promise<void>\n /** An in-process chain renews its row's lease before each retry; false when no such row exists (purged). */\n renew: (key: OutboxKey, until: Date) => Promise<boolean>\n /** The drain claim: the most overdue due row, its lease moved to `until` and `attempts + 1`; null when none. */\n claim: (now: Date, until: Date) => Promise<OutboxEntry | null>\n /** `forget()`: deletes every row whose body names the click id (as `clickId` or `firstClickId`). */\n purge: (clickId: string) => Promise<void>\n pending: () => Promise<number>\n}\n\nconst keyOf = (k: OutboxKey): OutboxKey => ({ eventType: k.eventType, eventId: k.eventId })\n\n/** A stored row as the drainer uses it: a Phase 1c string `lastError` reads as `{ status: 0, code }`. */\nexport function rowOf(doc: Record<string, unknown>): OutboxEntry {\n const e = doc['lastError']\n return {\n ...(doc as OutboxEntry),\n lastError: typeof e === 'string' ? { status: 0, code: e } : ((e as OutboxError) ?? null),\n unauthorizedSince: (doc['unauthorizedSince'] as Date | undefined) ?? null,\n }\n}\n\nexport function createOutbox(model: OutboxModelLike): Outbox {\n return {\n async enqueue(entry) {\n const { eventType, eventId, unauthorizedSince, ...rest } = entry\n const state = unauthorizedSince ? { ...rest, unauthorizedSince } : rest\n const r = (await run(\n model.updateOne({ eventType, eventId }, { $setOnInsert: state }, { upsert: true }),\n )) as { matchedCount?: number } | null\n return !(Number(r?.matchedCount) > 0)\n },\n async remove(key) {\n await run(model.deleteOne!(keyOf(key)))\n },\n async reschedule(key, p) {\n const update: Record<string, unknown> = {\n $set: { nextAttemptAt: p.nextAttemptAt, lastStatus: p.lastStatus, lastError: p.lastError },\n ...(p.attempts > 0 ? { $inc: { attempts: p.attempts } } : {}),\n // $min sets a missing field and never moves an earlier 401 clock forward\n ...(p.unauthorizedAt\n ? { $min: { unauthorizedSince: p.unauthorizedAt } }\n : { $unset: { unauthorizedSince: 1 } }),\n }\n await run(model.updateOne(keyOf(key), update))\n },\n async renew(key, until) {\n const r = (await run(model.updateOne(keyOf(key), { $set: { nextAttemptAt: until } }))) as {\n matchedCount?: number\n } | null\n return r?.matchedCount !== 0\n },\n async claim(now, until) {\n const doc = (await run(\n model.findOneAndUpdate!(\n { nextAttemptAt: { $lte: now } },\n { $set: { nextAttemptAt: until }, $inc: { attempts: 1 } },\n { sort: { nextAttemptAt: 1 }, new: true, lean: true },\n ),\n )) as Record<string, unknown> | null\n return doc ? rowOf(doc) : null\n },\n async purge(clickId) {\n await run(\n model.deleteMany!({ $or: [{ 'body.clickId': clickId }, { 'body.firstClickId': clickId }] }),\n )\n },\n pending: () => run(model.countDocuments({})),\n }\n}\n\n/** Whether a queued body names the click id (forget's purge). */\nexport const names = (e: OutboxEntry, clickId: string): boolean =>\n e.body['clickId'] === clickId || e.body['firstClickId'] === clickId\n\nconst same = (a: OutboxKey, b: OutboxKey): boolean =>\n a.eventType === b.eventType && a.eventId === b.eventId\n\n/** Applies a reschedule patch to an in-memory row (memory outbox and spill). */\nexport function applyPatch(e: OutboxEntry, p: ReschedulePatch): void {\n e.nextAttemptAt = p.nextAttemptAt\n e.lastStatus = p.lastStatus\n e.lastError = p.lastError\n e.attempts += p.attempts\n e.unauthorizedSince = p.unauthorizedAt\n ? new Date(Math.min(e.unauthorizedSince?.getTime() ?? Infinity, p.unauthorizedAt.getTime()))\n : null\n}\n\n/** In-memory outbox for sites without Mongo (tests, `enabled: false`): lost on restart, by design. */\nexport function createMemoryOutbox(): Outbox & { entries: OutboxEntry[] } {\n const entries: OutboxEntry[] = []\n const find = (key: OutboxKey) => entries.find((x) => same(x, key))\n return {\n entries,\n async enqueue(entry) {\n if (find(entry)) return false\n entries.push({ ...entry })\n return true\n },\n async remove(key) {\n const i = entries.findIndex((e) => same(e, key))\n if (i >= 0) entries.splice(i, 1)\n },\n async reschedule(key, p) {\n const e = find(key)\n if (e) applyPatch(e, p)\n },\n async renew(key, until) {\n const e = find(key)\n if (e) e.nextAttemptAt = until\n return !!e\n },\n async claim(now, until) {\n let due: OutboxEntry | undefined\n for (const e of entries)\n if (e.nextAttemptAt <= now && (!due || e.nextAttemptAt < due.nextAttemptAt)) due = e\n if (!due) return null\n due.nextAttemptAt = until\n due.attempts += 1\n return { ...due }\n },\n async purge(clickId) {\n for (let i = entries.length - 1; i >= 0; i--)\n if (names(entries[i]!, clickId)) entries.splice(i, 1)\n },\n pending: async () => entries.length,\n }\n}\n\n/** Reports whose enqueue failed or timed out, oldest first, at most `max`. */\nexport type Spill = {\n /** Adds the entry unless its key is already spilled; returns the oldest entry it evicted, if any. */\n add: (entry: OutboxEntry) => OutboxEntry | null\n has: (key: OutboxKey) => boolean\n get: (key: OutboxKey) => OutboxEntry | undefined\n delete: (key: OutboxKey) => void\n entries: () => OutboxEntry[]\n readonly size: number\n}\n\nexport function createSpill(max: number = SPILL_MAX): Spill {\n const map = new Map<string, OutboxEntry>()\n const k = (e: OutboxKey): string => `${e.eventType}\\u0000${e.eventId}`\n return {\n add(entry) {\n if (map.has(k(entry))) return null\n map.set(k(entry), entry)\n if (map.size <= max) return null\n const [oldest, evicted] = map.entries().next().value as [string, OutboxEntry]\n map.delete(oldest)\n return evicted\n },\n has: (key) => map.has(k(key)),\n get: (key) => map.get(k(key)),\n delete: (key) => void map.delete(k(key)),\n entries: () => [...map.values()],\n get size() {\n return map.size\n },\n }\n}\n\n/**\n * Moves every spilled entry, with its current state, into the outbox (the drainer runs this first on each tick). An\n * entry `forget()` (or a finished send) took out of the spill while an earlier one was moving is skipped, and one\n * taken out while its own write was in flight has the row it wrote removed again, so an erased click id is never\n * re-inserted after the purge. A failed write leaves the entry spilled for the next tick.\n */\nexport async function moveSpill(spill: Spill, outbox: Outbox): Promise<number> {\n let moved = 0\n for (const e of spill.entries())\n if (spill.get(e) === e) {\n const inserted = await outbox.enqueue(e)\n if (spill.get(e) === e) spill.delete(e)\n else if (inserted) await outbox.remove(e)\n moved++\n }\n return moved\n}\n","/**\n * The conversion wire contract as the SDK mirrors it — Phase 3 addendum \"ConversionBodySchema home and SDK mirror\",\n * \"EventId\", \"Link tables\", \"Per-type body rules\", \"`fee_charged`\", \"Site secret format\", \"`keyId`\". packages/shared\n * is the source; the server entry never imports it (zero runtime deps), and test/conversions-contract.test.ts fails\n * when either side changes alone.\n */\n\n/** §5.5 canonical conversion types plus `fee_charged` (R2(c)): 12 entries, in the hub's order. */\nexport const CONVERSION_TYPES = [\n 'booking_created',\n 'booking_paid',\n 'contact_submitted',\n 'quote_requested',\n 'call_clicked',\n 'signup',\n 'purchase',\n 'booking_cancelled',\n 'booking_refunded',\n 'booking_no_show',\n 'chargeback',\n 'fee_charged',\n] as const\nexport type ConversionType = (typeof CONVERSION_TYPES)[number]\n\n/** §5.5 reversal targets. */\nexport const REVERSAL_TARGETS = {\n booking_cancelled: ['booking_created'],\n booking_no_show: ['booking_created'],\n booking_refunded: ['booking_paid'],\n chargeback: ['booking_paid', 'purchase'],\n} as const satisfies Partial<Record<ConversionType, readonly ConversionType[]>>\n/** Every type that carries `reverses`; a fee names the no-show or cancel it belongs to (it is not a reversal). */\nexport const LINK_TARGETS = {\n ...REVERSAL_TARGETS,\n fee_charged: ['booking_no_show', 'booking_cancelled'],\n} as const satisfies Partial<Record<ConversionType, readonly ConversionType[]>>\nexport type LinkedType = keyof typeof LINK_TARGETS\nexport const REVERSAL_TYPES = Object.freeze(\n Object.keys(REVERSAL_TARGETS) as (keyof typeof REVERSAL_TARGETS)[],\n)\n\ntype AmountRule = 'null' | 'optional' | 'required' | 'positive'\n/** Per-type amount rules: `null` forbids, `optional` allows null or 0…1e9, `required` 0…1e9, `positive` 1…1e9. */\nexport const CONVERSION_BODY_RULES = {\n booking_created: { value: 'optional', fee: 'null' },\n booking_paid: { value: 'required', fee: 'null' },\n contact_submitted: { value: 'null', fee: 'null' },\n quote_requested: { value: 'optional', fee: 'null' },\n call_clicked: { value: 'null', fee: 'null' },\n signup: { value: 'optional', fee: 'null' },\n purchase: { value: 'optional', fee: 'null' },\n booking_cancelled: { value: 'null', fee: 'optional' },\n booking_refunded: { value: 'positive', fee: 'null' },\n booking_no_show: { value: 'null', fee: 'optional' },\n chargeback: { value: 'positive', fee: 'null' },\n fee_charged: { value: 'null', fee: 'positive' },\n} as const satisfies Record<ConversionType, { value: AmountRule; fee: AmountRule }>\n\n/** `valueCents` / `feeCents` upper bound. */\nexport const AMOUNT_MAX_CENTS = 1_000_000_000\n/** A lower-case site prefix, `:`, an id without `.`, `@`, `+`, `:` or whitespace; ≤ 64 in all; never `erased:`. */\nexport const EVENT_ID_RE = /^(?=.{1,64}$)(?!erased:)[a-z][a-z0-9_]{0,31}:[A-Za-z0-9_-]{1,62}$/\nexport const CURRENCY_RE = /^[A-Z]{3}$/\n/** `INR_SITE_SECRET`: `'inrs1_' + base64url(32 bytes)`; the HMAC key is the string's UTF-8 bytes. */\nexport const SITE_SECRET_RE = /^inrs1_[A-Za-z0-9_-]{43}$/\nexport const KEY_ID_RE = /^[0-9a-f]{8}$/\n/** `X-INR-Site`: a slug of ≤ 48 characters. */\nexport const SITE_KEY_RE = /^(?=.{1,48}$)[a-z0-9]+(-[a-z0-9]+)*$/\n/** `sdk` on the wire and on the model. */\nexport const SDK_FIELD_MAX = 40\n\n/** The literal path each signed endpoint signs (forget appends the click id). */\nexport const SIGNED_PATHS = {\n conversion: '/v1/conversions',\n ping: '/v1/conversions/ping',\n landing: '/v1/landings',\n forget: '/v1/referrals/',\n} as const\n\nexport const isLinkedType = (t: string): t is LinkedType => Object.hasOwn(LINK_TARGETS, t)\n\n/** Whether an amount satisfies its per-type rule (integer 0…1e9 or null, then the rule). */\nexport function amountOk(rule: AmountRule, v: number | null): boolean {\n if (v === null) return rule === 'null' || rule === 'optional'\n if (!(Number.isInteger(v) && v >= (rule === 'positive' ? 1 : 0) && v <= AMOUNT_MAX_CENTS))\n return false\n return rule !== 'null'\n}\n","/**\n * Signed delivery to the hub — Phase 3 addendum \"SDK server\": Transport, Response classification, In-process attempts,\n * TIMESTAMP_SKEW, 401 and missing config. One attempt = resolve config, sign `JSON.stringify(body)` with a fresh\n * timestamp and nonce, POST it, classify the answer; an attempt's outcome is written back to the outbox (and the\n * spill) by `settle`. The outbox drainer (drain.ts) reuses `attempt` and `settle`; `forget()` and `landingRelay()`\n * reuse `sendSigned`.\n */\nimport { SDK_VERSION } from '../constants.js'\nimport {\n applyPatch,\n type Outbox,\n type OutboxEntry,\n type OutboxError,\n type ReschedulePatch,\n type Spill,\n} from './outbox.js'\nimport { signRequest } from './sign.js'\nimport { SIGNED_PATHS } from './wire.js'\n\nconst SEC = 1000\n// Module constants rather than a property bag: the minifier renames them (server entry size budget).\n/** Retries after attempt 1 (§6.5 \"2 s, 8 s, 30 s\"); a longer Retry-After replaces the next delay. */\nexport const RETRY_DELAYS_MS = [2 * SEC, 8 * SEC, 30 * SEC] as const\n/** A Retry-After above this ends the in-process chain. */\nexport const IN_PROCESS_MAX_DELAY_MS = 30 * SEC\n/** Cap on a Retry-After written to `nextAttemptAt`. */\nexport const RETRY_AFTER_CAP_MS = 3600 * SEC\n/** `nextAttemptAt` after the in-process retries. */\nexport const AFTER_RETRIES_MS = 60 * SEC\n/**\n * 401 / missing config, and a misrouted answer (403, 404, a 3xx): next try in 10 min; dropped once\n * 24 h have passed since the first of them (one shared clock, stored as `unauthorizedSince`).\n */\nexport const UNAUTHORIZED_RETRY_MS = 10 * 60 * SEC\nexport const UNAUTHORIZED_MAX_MS = 24 * 3600 * SEC\n/** The lease `report()` writes with the row (the drainer claims rows whose lease ran out). */\nexport const LEASE_MS = 150 * SEC\nexport const TIMEOUT_DEFAULT_MS = 3000\nconst TIMEOUT_MIN_MS = 500\nconst TIMEOUT_MAX_MS = 30_000\nexport const RESPONSE_MAX_BYTES = 8192\n/**\n * Outbox calls give up waiting after this (the row's lease covers a write that never lands; `report()` resolves\n * within it whatever the outbox does).\n */\nexport const WRITE_TIMEOUT_MS = 2000\n/** A skew estimate is used only within ±24 h. */\nexport const SKEW_MAX_OFFSET_MS = 24 * 3600 * SEC\n\nexport type Logger = {\n warn: (message: string, meta?: Record<string, unknown>) => void\n info?: (message: string, meta?: Record<string, unknown>) => void\n}\n\n/** `INR_HUB_URL` as an origin (one trailing `/` stripped): `https:`, or `http:` for loopback only; else null. */\nexport function hubOrigin(raw: string | undefined): string | null {\n if (!raw) return null\n const s = raw.endsWith('/') ? raw.slice(0, -1) : raw\n if (!/^[a-z][a-z0-9+.-]*:\\/\\/[^/?#]+$/i.test(s)) return null\n let u: URL\n try {\n u = new URL(s)\n } catch {\n return null\n }\n if (u.pathname !== '/' || u.username || u.password) return null\n if (u.protocol === 'https:') return u.origin\n if (u.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(u.hostname))\n return u.origin\n return null\n}\n\n/** `timeoutMs ?? INR_TIMEOUT_MS ?? 3000`, clamped to [500, 30 000] ms (a blank env value is unset, not 0). */\nexport function timeoutMsOf(opt: number | undefined, envValue: string | undefined): number {\n const s = envValue?.trim()\n const n = opt ?? (s ? Number(s) : undefined)\n const v = n === undefined || !Number.isFinite(n) ? TIMEOUT_DEFAULT_MS : n\n return Math.min(TIMEOUT_MAX_MS, Math.max(TIMEOUT_MIN_MS, v))\n}\n\nexport type Classification =\n 'success' | 'terminal' | 'retryable' | 'skew' | 'unauthorized' | 'misrouted'\n\n/**\n * The §6.5 matrix (status first, then code; a missing body is classified by status). Status 0 is a transport failure\n * (network error, timeout). 403, 404 and any 3xx that reaches it are `misrouted` (a proxy, WAF or maintenance page in\n * the way, a missing route prefix): retried in process, then every 10 min, dropped 24 h after the first like a 401.\n * A real redirect never gets here: fetch with `redirect: 'error'` fails 301/302/303/307/308 (with or without\n * `Location`) as a transport error (status 0, retryable), so only 300, 304 and the like are classified.\n */\nexport function classifyResponse(status: number, code: string | null): Classification {\n if (status >= 200 && status < 300) return 'success'\n if (status === 409) return code === 'NONCE_REUSED' ? 'success' : 'terminal'\n if (status === 400) return code === 'TIMESTAMP_SKEW' ? 'skew' : 'terminal'\n if (status === 401) return 'unauthorized'\n if (status === 0 || status === 408 || status === 425 || status === 429) return 'retryable'\n if (status >= 500 && status < 600) return 'retryable'\n // what is left below 405: 3xx, 402, 403, 404 (fetch never surfaces a 1xx)\n return status < 405 && status !== 402 ? 'misrouted' : 'terminal'\n}\n\n/** `Retry-After` as delta seconds or an HTTP-date, in ms from `nowMs`; null when absent or unparseable. */\nexport function parseRetryAfter(value: string | null | undefined, nowMs: number): number | null {\n if (!value) return null\n const v = value.trim()\n if (/^\\d+$/.test(v)) return Number(v) * SEC\n const at = Date.parse(v)\n return Number.isNaN(at) ? null : Math.max(0, at - nowMs)\n}\n\n/** Process-wide estimate of `hubClock − Date.now()`, shared by every reporter; never persisted. */\nlet clockOffsetMs = 0\nexport const clockOffset = {\n get: (): number => clockOffsetMs,\n /** Tests only. */\n reset: (): void => {\n clockOffsetMs = 0\n },\n}\n/** NTP-style: the hub's `Date` (second resolution, so + 500 ms) against the request's midpoint. */\nexport function estimateOffsetMs(\n dateHeader: string | null,\n tSend: number,\n tRecv: number,\n): number | null {\n const hub = dateHeader ? Date.parse(dateHeader) : NaN\n if (Number.isNaN(hub)) return null\n const offset = Math.round(hub + 500 - (tSend + tRecv) / 2)\n return Math.abs(offset) <= SKEW_MAX_OFFSET_MS ? offset : null\n}\n\nexport type DeliveryConfig = { hubUrl: string; siteKey: string; keyId: string; secret: string }\n\nexport type SendResult = {\n status: number\n code: string | null\n retryAfterMs: number | null\n date: string | null\n tSend: number\n tRecv: number\n}\n\n/** At most `max` bytes of the answer (enough for the error envelope); the rest is never read. */\nasync function readCapped(res: Response, max: number): Promise<string> {\n const reader = res.body?.getReader()\n if (!reader) return ''\n const dec = new TextDecoder()\n let text = ''\n for (let n = 0; n < max;) {\n const { done, value } = await reader.read()\n if (done) break\n text += dec.decode(value.subarray(0, max - n), { stream: true })\n n += value.byteLength\n }\n reader.cancel().catch(() => undefined)\n return text\n}\n\n/** The answer's error code, kept only in the hub's shape (an upper-case token ≤ 64 chars): it is logged and stored. */\nexport function errorCodeOf(text: string): string | null {\n try {\n const json = JSON.parse(text) as { error?: { code?: unknown }; code?: unknown } | null\n const code = json?.error?.code ?? json?.code\n return typeof code === 'string' && /^[A-Z][A-Z0-9_]{0,63}$/.test(code) ? code : null\n } catch {\n return null\n }\n}\n\n/** One signed request. Never throws: transport failures come back as status 0 with code NETWORK / TIMEOUT. */\nexport async function sendSigned(\n cfg: DeliveryConfig,\n req: SignedReq,\n timeoutMs: number,\n): Promise<SendResult> {\n const timestamp = Math.floor((Date.now() + clockOffsetMs) / 1000)\n const { headers } = signRequest({ ...cfg, ...req, timestamp })\n const ctl = new AbortController()\n const timer = setTimeout(() => ctl.abort(), timeoutMs)\n ;(timer as { unref?: () => void }).unref?.()\n const tSend = Date.now()\n try {\n const res = await fetch(cfg.hubUrl + req.path, {\n method: req.method,\n headers: { ...headers, 'User-Agent': `intenque-network-sdk/${SDK_VERSION}` },\n body: req.body,\n redirect: 'error',\n signal: ctl.signal,\n })\n const tRecv = Date.now()\n const text = await readCapped(res, RESPONSE_MAX_BYTES).catch(() => '')\n return {\n status: res.status,\n code: errorCodeOf(text),\n retryAfterMs: parseRetryAfter(res.headers.get('retry-after'), tRecv),\n date: res.headers.get('date'),\n tSend,\n tRecv,\n }\n } catch {\n const code = ctl.signal.aborted ? 'TIMEOUT' : 'NETWORK'\n return { status: 0, code, retryAfterMs: null, date: null, tSend, tRecv: Date.now() }\n } finally {\n clearTimeout(timer)\n }\n}\n\nexport type AttemptOutcome =\n | {\n kind: Exclude<Classification, 'skew'>\n status: number\n code: string | null\n retryAfterMs: number | null\n }\n | { kind: 'skew'; status: 400; code: 'TIMESTAMP_SKEW'; offsetMs: number | null }\n /** No global fetch: nothing sent, the row stays queued. */\n | { kind: 'nofetch' }\n\nexport type DropReason =\n 'terminal' | 'unauthorized_24h' | 'misrouted_24h' | 'expired' | 'memory_full'\n/** How a settled attempt counts in `drainNow()`; null when nothing was written (no fetch). */\nexport type Settled = 'sent' | 'retried' | 'dropped' | null\n\nexport type SignedReq = { method: 'POST' | 'DELETE'; path: string; body: string }\n\nexport type Delivery = {\n /** One signed request (forget, relay): config re-read, the skew re-sign, never throws. */\n request: (req: SignedReq) => Promise<AttemptOutcome>\n /** One attempt for a queued body, including the one immediate re-signed retry after TIMESTAMP_SKEW. */\n attempt: (entry: OutboxEntry) => Promise<AttemptOutcome>\n /**\n * Writes an attempt's outcome back (`retryInMs`: a retryable answer's delay). `attempts` = attempts this sender made\n * since it last wrote the row (0 after a drain claim, which counted its own).\n */\n settle: (\n entry: OutboxEntry,\n out: AttemptOutcome,\n attempts: number,\n retryInMs?: number,\n ) => Promise<Settled>\n /** Deletes the row and spill entry, then the `inr_outbox_dropped_total` warn line. */\n drop: (entry: OutboxEntry, error: OutboxError, reason: DropReason) => Promise<'dropped'>\n /**\n * Attempt 1, then up to 3 retries in process (retryable and misrouted answers); the final outcome is settled. A\n * retry is skipped (nothing settled) once the row and its spill entry are gone (`forget()` purged them).\n */\n chain: (entry: OutboxEntry) => Promise<Settled>\n}\n\nexport type DeliveryDeps = {\n /** Resolved at every attempt (env re-read, rotation picked up); null when a value is missing or invalid. */\n config: () => DeliveryConfig | null\n timeoutMs: number\n outbox: Outbox\n spill: Spill\n logger: Logger\n}\n\n/** Drain backoff: `min(60 s × 2^max(0, attempts − 4), 1800 s) × U(0.8, 1.2)`. */\nexport function drainBackoffMs(attempts: number): number {\n const base = Math.min(60 * SEC * 2 ** Math.max(0, attempts - 4), 1800 * SEC)\n return Math.round(base * (0.8 + Math.random() * 0.4))\n}\n\nexport const sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n const t = setTimeout(resolve, ms)\n ;(t as { unref?: () => void }).unref?.()\n })\n\n/**\n * An outbox call, bounded: its value, or `undefined` when it failed or took longer than `WRITE_TIMEOUT_MS` (a hung\n * Mongo cannot pin a finished chain nor a `report()`). Never rejects.\n */\nexport async function bounded<T>(work: () => Promise<T>): Promise<T | undefined> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n Promise.resolve()\n .then(work)\n .catch(() => undefined),\n new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), WRITE_TIMEOUT_MS)\n }),\n ])\n } finally {\n clearTimeout(timer)\n }\n}\n\nexport function createDelivery(deps: DeliveryDeps): Delivery {\n const { outbox, spill, logger } = deps\n const once = new Set<string>()\n const warnOnce = (code: string): void => {\n if (once.has(code)) return\n once.add(code)\n logger.warn(code)\n }\n\n const outcomeOf = (r: SendResult): AttemptOutcome => {\n const kind = classifyResponse(r.status, r.code)\n if (kind === 'skew')\n return {\n kind,\n status: 400,\n code: 'TIMESTAMP_SKEW',\n offsetMs: estimateOffsetMs(r.date, r.tSend, r.tRecv),\n }\n return { kind, status: r.status, code: r.code, retryAfterMs: r.retryAfterMs }\n }\n\n /** One signed request with the current config, plus the one immediate re-signed retry after TIMESTAMP_SKEW. */\n async function request(req: SignedReq): Promise<AttemptOutcome> {\n const cfg = deps.config()\n // missing config sends nothing and follows the 401 path (addendum \"401 and missing config\")\n if (!cfg)\n return { kind: 'unauthorized', status: 0, code: 'INR_ENV_MISSING', retryAfterMs: null }\n if (typeof globalThis.fetch !== 'function') {\n warnOnce('INR_NO_FETCH')\n return { kind: 'nofetch' }\n }\n let out = outcomeOf(await sendSigned(cfg, req, deps.timeoutMs))\n if (out.kind === 'skew' && out.offsetMs !== null) {\n clockOffsetMs = out.offsetMs\n out = outcomeOf(await sendSigned(cfg, req, deps.timeoutMs))\n if (out.kind === 'skew' && out.offsetMs !== null) clockOffsetMs = out.offsetMs\n }\n return out\n }\n const attempt = (entry: OutboxEntry): Promise<AttemptOutcome> =>\n request({ method: 'POST', path: SIGNED_PATHS.conversion, body: JSON.stringify(entry.body) })\n\n const remove = async (entry: OutboxEntry): Promise<void> => {\n spill.delete(entry)\n await bounded(() => outbox.remove(entry))\n }\n const drop = async (\n entry: OutboxEntry,\n error: OutboxError,\n reason: DropReason,\n ): Promise<'dropped'> => {\n await remove(entry)\n logger.warn('inr_outbox_dropped_total', {\n eventType: entry.eventType,\n eventId: entry.eventId,\n status: error.status,\n code: error.code,\n reason,\n })\n return 'dropped'\n }\n\n async function settle(\n entry: OutboxEntry,\n out: AttemptOutcome,\n attempts: number,\n retryInMs: number = AFTER_RETRIES_MS,\n ): Promise<Settled> {\n if (out.kind === 'nofetch') return null\n const now = Date.now()\n const error: OutboxError = { status: out.status, code: out.code }\n /** Reschedules the row (and its spill entry); `rejectedAt` feeds the 24 h clock of 401 / misrouted answers. */\n const retry = async (inMs: number, rejectedAt: Date | null = null): Promise<Settled> => {\n const patch: ReschedulePatch = {\n nextAttemptAt: new Date(now + inMs),\n lastStatus: out.status,\n lastError: error,\n attempts,\n unauthorizedAt: rejectedAt,\n }\n const spilled = spill.get(entry)\n if (spilled) applyPatch(spilled, patch)\n await bounded(() => outbox.reschedule(entry, patch))\n return 'retried'\n }\n switch (out.kind) {\n case 'success':\n await remove(entry)\n return 'sent'\n case 'terminal':\n return drop(entry, error, 'terminal')\n case 'unauthorized':\n case 'misrouted': {\n const since = entry.unauthorizedSince?.getTime()\n if (since !== undefined && now - since >= UNAUTHORIZED_MAX_MS) {\n if (out.kind === 'unauthorized')\n logger.warn('INR_UNAUTHORIZED', {\n eventType: entry.eventType,\n eventId: entry.eventId,\n ...error,\n })\n return drop(entry, error, `${out.kind}_24h`)\n }\n return retry(UNAUTHORIZED_RETRY_MS, new Date(now))\n }\n case 'skew':\n logger.warn('INR_CLOCK_SKEW', { offsetMs: out.offsetMs })\n return retry(drainBackoffMs(entry.attempts + attempts))\n case 'retryable':\n return retry(retryInMs)\n }\n }\n\n async function chain(entry: OutboxEntry): Promise<Settled> {\n for (let i = 0; ; i++) {\n const out = await attempt(entry)\n if (out.kind !== 'retryable' && out.kind !== 'misrouted') return settle(entry, out, i + 1)\n const retryAfter =\n out.retryAfterMs === null ? null : Math.min(out.retryAfterMs, RETRY_AFTER_CAP_MS)\n if (i === RETRY_DELAYS_MS.length)\n return settle(entry, out, i + 1, Math.max(AFTER_RETRIES_MS, retryAfter ?? 0))\n const delay = Math.max(RETRY_DELAYS_MS[i]!, retryAfter ?? 0)\n // a Retry-After above 30 s (BREAKER_OPEN's 60) goes straight to the outbox\n if (delay > IN_PROCESS_MAX_DELAY_MS) return settle(entry, out, i + 1, retryAfter!)\n await sleep(delay)\n // renew the lease so no drain tick claims the row while this chain still owns it\n const until = new Date(Date.now() + LEASE_MS)\n const spilled = spill.get(entry)\n if (spilled) spilled.nextAttemptAt = until\n // stop only when the outbox answered that no such row exists (an outbox error or timeout keeps sending)\n let kept: unknown\n await bounded(async () => (kept = await outbox.renew(entry, until)))\n if (kept === false && !spilled) return null\n }\n }\n\n return { request, attempt, settle, drop, chain }\n}\n","/**\n * The outbox drainer — Phase 3 addendum \"Drainer\", \"Claim and lease\", \"Drop logging\". Each tick moves the spill into\n * the outbox, then claims (lease now + 150 s, `attempts + 1`) and sends up to 50 due rows, one at a time; a 429 or 503\n * ends the tick. Every attempt goes through `Delivery.attempt`, so it re-reads the config (a rotated `INR_KEY_ID` /\n * `INR_SITE_SECRET` in `process.env` applies at the next row) and re-signs with a fresh timestamp and nonce. Ticks\n * never overlap: the first at 10 s + U(0, 10 s), then 60 s ± 10 s after the previous one ends, unref'd.\n */\nimport { drainBackoffMs, LEASE_MS, RETRY_AFTER_CAP_MS, sleep, type Delivery } from './delivery.js'\nimport { moveSpill, type Outbox, type Spill } from './outbox.js'\n\nconst SEC = 1000\nexport const DRAIN_FIRST_MS = 10 * SEC\nexport const DRAIN_EVERY_MS = 60 * SEC\n/** ± jitter on the interval, and the U(0, x) added to the first tick. */\nexport const DRAIN_JITTER_MS = 10 * SEC\nexport const DRAIN_BATCH = 50\n/** A row older than this is deleted (`expired`) instead of sent: the hub refuses `occurredAt` past 14 d. */\nexport const DRAIN_EXPIRE_MS = 14 * 86_400 * SEC - 3600 * SEC\n/** `close()` waits at most this for a running tick and the send chains. */\nexport const CLOSE_WAIT_MS = 5 * SEC\n\nexport type DrainResult = { sent: number; retried: number; dropped: number }\n\nexport type Drainer = {\n start: () => void\n drainNow: () => Promise<DrainResult>\n close: (pending: () => Promise<void>) => Promise<void>\n}\n\nexport function createDrainer(deps: {\n delivery: Delivery\n outbox: Outbox\n spill: Spill\n /** The outbox failed during a tick (throttled by the reporter). */\n unavailable: () => void\n /** Runs at the start of each tick (the helper indexes until they exist); never awaited. */\n onTick?: () => void\n}): Drainer {\n const { delivery, outbox, spill } = deps\n let timer: ReturnType<typeof setTimeout> | undefined\n let running: Promise<DrainResult> | null = null\n let closed = false\n\n async function tick(): Promise<DrainResult> {\n const r: DrainResult = { sent: 0, retried: 0, dropped: 0 }\n try {\n deps.onTick?.()\n await moveSpill(spill, outbox)\n for (let i = 0; i < DRAIN_BATCH; i++) {\n const now = Date.now()\n const row = await outbox.claim(new Date(now), new Date(now + LEASE_MS))\n if (!row) break\n if (now - new Date(row.createdAt).getTime() >= DRAIN_EXPIRE_MS) {\n await delivery.drop(row, row.lastError ?? { status: 0, code: null }, 'expired')\n r.dropped++\n continue\n }\n const out = await delivery.attempt(row)\n const retryAfter = 'retryAfterMs' in out ? (out.retryAfterMs ?? 0) : 0\n const done = await delivery.settle(\n row,\n out,\n 0,\n Math.max(drainBackoffMs(row.attempts), Math.min(retryAfter, RETRY_AFTER_CAP_MS)),\n )\n if (done) r[done]++\n // no fetch: the row keeps its lease; the hub's own back-pressure: wait for the next tick\n if (!done || ('status' in out && (out.status === 429 || out.status === 503))) break\n }\n } catch {\n deps.unavailable()\n }\n return r\n }\n\n function drainNow(): Promise<DrainResult> {\n running ??= tick().finally(() => {\n running = null\n })\n return running\n }\n\n function schedule(ms: number): void {\n if (closed) return\n timer = setTimeout(() => {\n void drainNow().then(() =>\n schedule(DRAIN_EVERY_MS + (Math.random() * 2 - 1) * DRAIN_JITTER_MS),\n )\n }, ms)\n ;(timer as { unref?: () => void }).unref?.()\n }\n\n return {\n start: () => schedule(DRAIN_FIRST_MS + Math.random() * DRAIN_JITTER_MS),\n drainNow,\n async close(pending) {\n closed = true\n clearTimeout(timer)\n await Promise.race([Promise.allSettled([running, pending()]), sleep(CLOSE_WAIT_MS)])\n },\n }\n}\n","/**\n * `landingRelay()` — Phase 3 addendum \"`landingRelay()`\" (spec §5.3 as amended by the 2.2 changelog): an Express\n * handler for the site's own `POST /inr/landing`. It takes `{ c, scope, ph, d }` from the site's frontend (JSON or\n * text/plain, ≤ 1 KB; parsed by the site's body parser or read here), and forwards one signed `POST /v1/landings` with\n * the wire relay body. The hub hashes `visitorIp` / `visitorUa` / `visitorOrigin` and discards them. The browser always\n * gets an empty 204, whatever happens (nothing is learnable, nothing is retried).\n */\nimport { isIP } from 'node:net'\nimport { CLICK_ID_RE, SDK_VERSION } from '../constants.js'\nimport { SIGNED_PATHS } from './wire.js'\n\nconst MIN = 60_000\n/** Input body cap. */\nexport const RELAY_MAX_BYTES = 1024\n/** Forwards per visitor IP and per process, per minute; the excess is dropped. */\nexport const RELAY_PER_IP_PER_MIN = 10\nexport const RELAY_PER_PROCESS_PER_MIN = 300\nconst D_MAX_MS = 30 * 86_400_000\nconst UA_MAX = 512\nconst ORIGIN_RE = /^https?:\\/\\/[^/\\s]{1,253}$/\n\nexport type RelayRequest = {\n body?: unknown\n ip?: string | undefined\n headers?: Record<string, unknown> | undefined\n app?: { get: (name: string) => unknown } | undefined\n readable?: boolean\n on?: (event: string, listener: (chunk?: unknown) => void) => unknown\n}\nexport type RelayResponse = { status: (code: number) => { end: () => void } }\nexport type RelayOptions = {\n /** The visitor's address when `req.ip` is not it (another proxy setup); Express `trust proxy` is still required. */\n visitorIp?: ((req: RelayRequest) => string | null | undefined) | undefined\n}\n\n/** The body as text when no parser ran (or `express.text` / `express.raw` did); null when over 1 KB or unreadable. */\nfunction readText(req: RelayRequest): Promise<string | null> {\n const b = req.body\n if (typeof b === 'string' || b instanceof Uint8Array) {\n const buf = Buffer.from(b)\n return Promise.resolve(buf.length > RELAY_MAX_BYTES ? null : buf.toString('utf8'))\n }\n if (!req.readable || typeof req.on !== 'function') return Promise.resolve(null)\n return new Promise((resolve) => {\n const chunks: Buffer[] = []\n let size = 0\n req.on!('data', (c) => {\n size += (c as Buffer).length\n // over the cap: keep draining (the 204 still goes out), keep nothing\n if (size <= RELAY_MAX_BYTES) chunks.push(c as Buffer)\n })\n req.on!('end', () =>\n resolve(size > RELAY_MAX_BYTES ? null : Buffer.concat(chunks).toString('utf8')),\n )\n req.on!('error', () => resolve(null))\n })\n}\n\nasync function inputOf(req: RelayRequest): Promise<Record<string, unknown> | null> {\n const b = req.body\n if (b && typeof b === 'object' && !(b instanceof Uint8Array) && Object.keys(b).length > 0)\n return JSON.stringify(b).length > RELAY_MAX_BYTES ? null : (b as Record<string, unknown>)\n const text = await readText(req)\n try {\n const json: unknown = text === null ? null : JSON.parse(text)\n return json && typeof json === 'object' ? (json as Record<string, unknown>) : null\n } catch {\n return null\n }\n}\n\nconst header = (req: RelayRequest, name: string): string | null => {\n const v = req.headers?.[name]\n return typeof v === 'string' ? v : null\n}\n\n/** The wire relay body for one landing (`LandingRelayBodySchema`), or null when the input is not one. */\nexport function relayBody(\n input: Record<string, unknown>,\n visitorIp: string,\n req: RelayRequest,\n): Record<string, unknown> | null {\n const { c, scope, ph, d } = input\n if (typeof c !== 'string' || !CLICK_ID_RE.test(c)) return null\n if (scope !== 'session' && scope !== 'persistent') return null\n if (ph !== undefined && !(typeof ph === 'string' && /^[0-9a-f]{16}$/.test(ph))) return null\n if (d !== undefined && !(Number.isInteger(d) && (d as number) >= 0 && (d as number) <= D_MAX_MS))\n return null\n const origin = header(req, 'origin')\n return {\n v: 1,\n clickId: c,\n scope,\n pathHash: ph,\n d,\n visitorIp,\n visitorUa: (header(req, 'user-agent') ?? '').slice(0, UA_MAX),\n visitorOrigin: origin !== null && ORIGIN_RE.test(origin) ? origin : null,\n sdk: `server/${SDK_VERSION}`,\n }\n}\n\n/**\n * Fixed one-minute windows, process-wide (every handler of every reporter): ≤ 10 forwards per visitor IP and ≤ 300 in\n * all (so the map holds ≤ 300 addresses).\n */\nlet window = -1\nlet total = 0\nconst perIp = new Map<string, number>()\nfunction allow(ip: string): boolean {\n const w = Math.floor(Date.now() / MIN)\n if (w !== window) {\n window = w\n total = 0\n perIp.clear()\n }\n const n = perIp.get(ip) ?? 0\n if (total >= RELAY_PER_PROCESS_PER_MIN || n >= RELAY_PER_IP_PER_MIN) return false\n perIp.set(ip, n + 1)\n total++\n return true\n}\nexport const relayLimits = {\n /** Tests only. */\n reset: (): void => {\n window = -1\n },\n}\n\nexport function createRelay(deps: {\n enabled: boolean\n /** Sends the signed request (detached, tracked by the reporter's `idle()`). */\n forward: (req: { method: 'POST'; path: string; body: string }) => void\n warn: (message: string) => void\n}) {\n let warned = false // once per reporter\n return (opts: RelayOptions = {}) =>\n async (req: RelayRequest, res: RelayResponse): Promise<void> => {\n let body: Record<string, unknown> | null = null\n try {\n const input = await inputOf(req)\n // req.ip is the proxy's address unless Express trusts the proxy hop: forwarding it would hash one visitor.\n // Required with opts.visitorIp too (addendum \"`landingRelay()`\")\n const trusted = Boolean(req.app?.get('trust proxy'))\n if (!trusted && !warned) {\n warned = true\n deps.warn('INR_RELAY_TRUST_PROXY')\n }\n const ip = trusted ? (opts.visitorIp?.(req) ?? req.ip) : undefined\n if (deps.enabled && input && typeof ip === 'string' && isIP(ip)) {\n body = relayBody(input, ip, req)\n if (body && !allow(ip)) body = null\n }\n } catch {\n body = null // never throws into the site's route\n }\n try {\n res.status(204).end()\n } catch {\n // a response the site already ended: nothing to answer\n }\n if (body)\n deps.forward({ method: 'POST', path: SIGNED_PATHS.landing, body: JSON.stringify(body) })\n }\n}\n","/**\n * `createConversionReporter` — spec §6.5 as amended by the Phase 3 addendum (\"SDK server\"). `report()` validates the\n * event against the mirrored wire rules, writes the UNSIGNED v1 body to the outbox (≤ 2 s, else the in-memory spill)\n * and starts the in-process attempts (delivery.ts) without awaiting them. It never throws, never rejects and never\n * waits on the network. Caller contract: request handlers may `void inr.report(...)`; Stripe webhook handlers\n * `await` it before answering 200, so a crash cannot lose a committed event (Stripe retries). The drainer (drain.ts)\n * retries the outbox; `forget()` is the signed erasure and `landingRelay()` the first-party relay (relay.ts).\n */\nimport { CLICK_ID_RE, SDK_VERSION } from '../constants.js'\nimport {\n bounded,\n createDelivery,\n IN_PROCESS_MAX_DELAY_MS,\n LEASE_MS,\n hubOrigin,\n RETRY_DELAYS_MS,\n sleep,\n timeoutMsOf,\n WRITE_TIMEOUT_MS,\n type AttemptOutcome,\n type DeliveryConfig,\n type Logger,\n} from './delivery.js'\nimport { createDrainer, type DrainResult } from './drain.js'\nimport {\n createMemoryOutbox,\n createOutbox,\n createSpill,\n ensureOutboxIndexes,\n names,\n outboxModel,\n OUTBOX_DEFAULT_COLLECTION,\n type MongooseLike,\n type Outbox,\n type OutboxEntry,\n type Spill,\n} from './outbox.js'\nimport { createRelay, type RelayOptions, type RelayRequest, type RelayResponse } from './relay.js'\nimport {\n amountOk,\n CONVERSION_BODY_RULES,\n CONVERSION_TYPES,\n CURRENCY_RE,\n EVENT_ID_RE,\n isLinkedType,\n KEY_ID_RE,\n LINK_TARGETS,\n SITE_KEY_RE,\n SIGNED_PATHS,\n SITE_SECRET_RE,\n type ConversionType,\n} from './wire.js'\n\nexport { CONVERSION_TYPES, type ConversionType, type DrainResult, type Logger, type RelayOptions }\n\nconst ISO_DATETIME_RE = /^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d(:\\d\\d(\\.\\d+)?)?(Z|[+-]\\d\\d:\\d\\d)$/\n\n/** `report()` resolves after at most this, whatever the outbox does. */\nexport const ENQUEUE_TIMEOUT_MS = WRITE_TIMEOUT_MS\n/** `INR_OUTBOX_UNAVAILABLE` is logged at most once per this. */\nconst OUTBOX_WARN_EVERY_MS = 60_000\n\nexport type ConversionEvent = {\n eventType: ConversionType\n eventId: string\n clickId: string\n firstClickId?: string | null | undefined\n tokenScope: 'session' | 'persistent'\n occurredAt: Date | string\n valueCents?: number | null | undefined\n feeCents?: number | null | undefined\n currency?: string | null | undefined\n reverses?: { eventType: ConversionType; eventId: string } | null | undefined\n}\n\n/** §5.4 v1 body (unknown keys → 400 on the hub, so nothing else is ever added here). */\nexport type ConversionBody = {\n v: 1\n eventType: ConversionType\n eventId: string\n clickId: string\n firstClickId: string | null\n tokenScope: 'session' | 'persistent'\n occurredAt: string\n valueCents: number | null\n feeCents: number | null\n currency: string | null\n reverses: { eventType: ConversionType; eventId: string } | null\n sdk: string\n}\n\nexport type ReporterOptions = {\n hubUrl?: string | undefined\n siteKey?: string | undefined\n /** `INR_KEY_ID` / `INR_SITE_SECRET` in `process.env` win at every attempt, so a redeploy after rotation applies. */\n keyId?: string | undefined\n secret?: string | undefined\n /** `INR_ENABLED !== 'false'`; when false `report()` validates and drops. */\n enabled?: boolean | undefined\n /** Per attempt; default `INR_TIMEOUT_MS` or 3000, clamped to [500, 30 000]. */\n timeoutMs?: number | undefined\n /** `collection` defaults to `INR_OUTBOX_COLLECTION`, else `inrConversionOutbox` (the name `doctor` checks). */\n outbox?: { mongoose?: MongooseLike; collection?: string } | undefined\n logger?: Logger | undefined\n}\n\nexport type ReportResult =\n /** Durable in the outbox. */\n | { status: 'queued'; body: ConversionBody }\n /** The outbox write failed or timed out: held in memory (≤ 1000) until the next drain; attempts still run. */\n | { status: 'spilled'; body: ConversionBody }\n | { status: 'disabled'; body: ConversionBody }\n | { status: 'invalid'; error: string }\n\nexport type ConversionReporter = {\n /** Validates, builds the body, queues it and starts the in-process attempts. Never throws, never rejects. */\n report: (event: ConversionEvent) => Promise<ReportResult>\n /**\n * §5.9 erasure: purges queued reports naming the id, then the signed `DELETE /v1/referrals/:clickId` (up to 4\n * attempts). True once the hub answered 2xx; keep the local referral until then. Ignores `enabled`.\n */\n forget: (clickId: string) => Promise<boolean>\n /** §5.3 first-party landing relay: an Express handler that always answers 204 (relay.ts). */\n landingRelay: (opts?: RelayOptions) => (req: RelayRequest, res: RelayResponse) => Promise<void>\n /** The unsigned body an event produces (exposed for tests and for ports). */\n bodyFor: (event: ConversionEvent) => ConversionBody | { error: string }\n /** One drain tick now (joins a running one). */\n drainNow: () => Promise<DrainResult>\n /** Stops the drainer and waits ≤ 5 s for a running tick and the send chains (graceful shutdown). */\n close: () => Promise<void>\n outbox: Outbox\n spill: Spill\n /** Resolves once every in-process attempt chain started so far has settled (tests, graceful shutdown). */\n idle: () => Promise<void>\n}\n\n/**\n * The C.4 body, or the first rule it breaks (mirrors `ConversionBodySchema`): eventId per EVENT_ID_RE, clickId and\n * tokenScope non-null, the per-type amount rules, currency required with any amount, `reverses` required on the\n * linked types with `eventType ∈ LINK_TARGETS[type]` and null otherwise. Currency is upper-cased; a valid `Date` or an\n * ISO datetime string with `Z` or an offset is sent as ISO UTC with milliseconds.\n */\nexport function buildConversionBody(event: ConversionEvent): ConversionBody | { error: string } {\n if (!event || typeof event !== 'object') return { error: 'event' }\n const type = event.eventType\n if (typeof type !== 'string' || !Object.hasOwn(CONVERSION_BODY_RULES, type))\n return { error: 'eventType' }\n if (typeof event.eventId !== 'string' || !EVENT_ID_RE.test(event.eventId))\n return { error: 'eventId' }\n if (typeof event.clickId !== 'string' || !CLICK_ID_RE.test(event.clickId))\n return { error: 'clickId' }\n const first = event.firstClickId ?? null\n if (first !== null && !(typeof first === 'string' && CLICK_ID_RE.test(first)))\n return { error: 'firstClickId' }\n if (event.tokenScope !== 'session' && event.tokenScope !== 'persistent')\n return { error: 'tokenScope' }\n const occurred =\n event.occurredAt instanceof Date\n ? event.occurredAt\n : // ISO with Z or an offset only: V8 parses anything else ('1', a space) leniently, in local time\n typeof event.occurredAt === 'string' && ISO_DATETIME_RE.test(event.occurredAt)\n ? new Date(event.occurredAt)\n : new Date(NaN)\n const occurredAt = Number.isNaN(occurred.getTime()) ? '' : occurred.toISOString()\n // years 0000–9999 only (toISOString gives ±YYYYYY outside): the hub's ISO datetime has a 4-digit year\n if (!/^\\d{4}-/.test(occurredAt)) return { error: 'occurredAt' }\n const valueCents = event.valueCents ?? null\n const feeCents = event.feeCents ?? null\n const rules = CONVERSION_BODY_RULES[type]\n if (!amountOk(rules.value, valueCents)) return { error: 'valueCents' }\n if (!amountOk(rules.fee, feeCents)) return { error: 'feeCents' }\n let currency: string | null = null\n if (event.currency != null) {\n currency = typeof event.currency === 'string' ? event.currency.toUpperCase() : ''\n if (!CURRENCY_RE.test(currency)) return { error: 'currency' }\n }\n if (currency === null && (valueCents !== null || feeCents !== null)) return { error: 'currency' }\n const reverses = event.reverses ?? null\n if (isLinkedType(type)) {\n const targets: readonly string[] = LINK_TARGETS[type]\n if (\n reverses === null ||\n typeof reverses !== 'object' ||\n !targets.includes(reverses.eventType) ||\n typeof reverses.eventId !== 'string' ||\n !EVENT_ID_RE.test(reverses.eventId)\n )\n return { error: 'reverses' }\n } else if (reverses !== null) return { error: 'reverses' }\n return {\n v: 1,\n eventType: type,\n eventId: event.eventId,\n clickId: event.clickId,\n firstClickId: first === event.clickId ? null : first,\n tokenScope: event.tokenScope,\n occurredAt,\n valueCents,\n feeCents,\n currency,\n reverses: reverses ? { eventType: reverses.eventType, eventId: reverses.eventId } : null,\n sdk: `server/${SDK_VERSION}`,\n }\n}\n\nconst REQUIRED_ENV = ['INR_HUB_URL', 'INR_SITE_KEY', 'INR_KEY_ID', 'INR_SITE_SECRET'] as const\nconst ENV_FORMAT: Partial<Record<(typeof REQUIRED_ENV)[number], (v: string) => boolean>> = {\n INR_HUB_URL: (v) => hubOrigin(v) !== null,\n INR_SITE_KEY: (v) => SITE_KEY_RE.test(v),\n INR_KEY_ID: (v) => KEY_ID_RE.test(v),\n INR_SITE_SECRET: (v) => SITE_SECRET_RE.test(v),\n}\n\n/**\n * §6.5 `verifyEnv()`: returns the missing or invalid names (`INR_KEY_ID (invalid)`); never prints a value. Throws\n * when `NODE_ENV !== 'production'` or `INR_STRICT_ENV === 'true'` (JCM staging runs NODE_ENV=production), warns\n * otherwise so a misconfigured reporter never takes a production backend down. `opts.production` overrides NODE_ENV.\n */\nexport function verifyEnv(\n env: Record<string, string | undefined> = process.env,\n opts: { production?: boolean; logger?: Logger } = {},\n): string[] {\n const problems = REQUIRED_ENV.flatMap((k) => {\n const v = env[k]\n if (!v) return [k]\n return ENV_FORMAT[k] && !ENV_FORMAT[k](v) ? [`${k} (invalid)`] : []\n })\n if (problems.length === 0) return []\n const production = opts.production ?? env['NODE_ENV'] === 'production'\n const message = `@intenque/network-sdk/server: missing or invalid env ${problems.join(', ')}`\n if (!production || env['INR_STRICT_ENV'] === 'true') throw new Error(message)\n ;(opts.logger ?? console).warn(message)\n return problems\n}\n\nexport function createConversionReporter(opts: ReporterOptions = {}): ConversionReporter {\n const site = opts.logger ?? { warn: (m, meta) => console.warn(m, meta ?? '') }\n // a throwing site logger must not reject report() or a send chain (an unhandled rejection kills Node)\n const logger: Logger = {\n warn: (m, meta) => {\n try {\n site.warn(m, meta)\n } catch {\n // dropped: nothing safer to do with a log line\n }\n },\n }\n const enabled = opts.enabled !== false\n const env = (): Record<string, string | undefined> =>\n typeof process === 'undefined' ? {} : process.env\n const model = opts.outbox?.mongoose\n ? outboxModel(\n opts.outbox.mongoose,\n opts.outbox.collection ?? (env()['INR_OUTBOX_COLLECTION'] || OUTBOX_DEFAULT_COLLECTION),\n )\n : null\n // retried at each drain tick until all three exist\n const indexes = (): void => {\n if (model && enabled) void ensureOutboxIndexes(model, logger.warn)\n }\n indexes()\n const outbox: Outbox = model ? createOutbox(model) : createMemoryOutbox()\n const spill = createSpill()\n\n let hubUrlWarned = false\n /** Re-read at every attempt; null (missing config) when any value is empty or malformed. */\n const config = (): DeliveryConfig | null => {\n const e = env()\n const rawHub = opts.hubUrl ?? e['INR_HUB_URL']\n const hubUrl = hubOrigin(rawHub)\n if (rawHub && !hubUrl && !hubUrlWarned) {\n hubUrlWarned = true\n logger.warn('INR_HUB_URL_INVALID')\n }\n const siteKey = opts.siteKey ?? e['INR_SITE_KEY'] ?? ''\n const keyId = e['INR_KEY_ID'] || opts.keyId || ''\n const secret = e['INR_SITE_SECRET'] || opts.secret || ''\n if (!hubUrl || !SITE_KEY_RE.test(siteKey) || !KEY_ID_RE.test(keyId)) return null\n if (!SITE_SECRET_RE.test(secret)) return null\n return { hubUrl, siteKey, keyId, secret }\n }\n const delivery = createDelivery({\n config,\n timeoutMs: timeoutMsOf(opts.timeoutMs, env()['INR_TIMEOUT_MS']),\n outbox,\n spill,\n logger,\n })\n\n const inflight = new Set<Promise<unknown>>()\n const track = (work: Promise<unknown>): void => {\n const p: Promise<unknown> = work\n .catch((err: unknown) => {\n logger.warn('inr.report attempt failed', {\n error: err instanceof Error ? err.message : String(err),\n })\n })\n .finally(() => inflight.delete(p))\n inflight.add(p)\n }\n const start = (entry: OutboxEntry): void => track(delivery.chain(entry))\n const idle = async (): Promise<void> => {\n while (inflight.size > 0) await Promise.allSettled([...inflight])\n }\n\n let outboxWarnedAt = -Infinity\n const unavailable = (): void => {\n if (Date.now() - outboxWarnedAt < OUTBOX_WARN_EVERY_MS) return\n outboxWarnedAt = Date.now()\n logger.warn('INR_OUTBOX_UNAVAILABLE')\n }\n const drainer = createDrainer({ delivery, outbox, spill, unavailable, onTick: indexes })\n if (enabled) drainer.start()\n\n /** §5.9 erasure (addendum \"`forget(clickId)`\"). */\n async function forget(clickId: string): Promise<boolean> {\n if (typeof clickId !== 'string' || !CLICK_ID_RE.test(clickId)) return false\n const fail = (status: number, code: string | null): false => {\n logger.warn('INR_FORGET_FAILED', { status, code })\n return false\n }\n // first, so no later drain re-sends a report naming the erased id\n for (const e of spill.entries()) if (names(e, clickId)) spill.delete(e)\n if (!(await bounded(() => outbox.purge(clickId).then(() => true))))\n return fail(0, 'INR_OUTBOX_UNAVAILABLE')\n const req = { method: 'DELETE' as const, path: SIGNED_PATHS.forget + clickId, body: '' }\n let out: AttemptOutcome\n for (let i = 0; ; i++) {\n out = await delivery.request(req)\n // 2xx only: a 409 NONCE_REUSED (success for a report) confirms no erasure\n if ('status' in out && out.status >= 200 && out.status < 300) return true\n if (out.kind !== 'retryable' || i === RETRY_DELAYS_MS.length) break\n const ra = out.retryAfterMs ?? 0\n if (ra > IN_PROCESS_MAX_DELAY_MS) break\n await sleep(Math.max(RETRY_DELAYS_MS[i]!, ra))\n }\n return out.kind === 'nofetch' ? fail(0, 'INR_NO_FETCH') : fail(out.status, out.code)\n }\n\n /** The outbox write, bounded: `inserted`, `exists` (another sender owns the row) or `failed` (error, timeout). */\n const enqueue = async (entry: OutboxEntry): Promise<'inserted' | 'exists' | 'failed'> => {\n const inserted = await bounded(() => outbox.enqueue(entry))\n return inserted === undefined ? 'failed' : inserted ? 'inserted' : 'exists'\n }\n\n return {\n outbox,\n spill,\n bodyFor: buildConversionBody,\n async report(event) {\n try {\n const body = buildConversionBody(event)\n if ('error' in body) {\n logger.warn('inr.report dropped: invalid event', { error: body.error })\n return { status: 'invalid', error: body.error }\n }\n if (!enabled) return { status: 'disabled', body }\n const now = Date.now()\n const entry: OutboxEntry = {\n eventType: body.eventType,\n eventId: body.eventId,\n body,\n attempts: 0,\n nextAttemptAt: new Date(now + LEASE_MS),\n lastStatus: null,\n lastError: null,\n unauthorizedSince: null,\n createdAt: new Date(now),\n }\n const written = await enqueue(entry)\n const status = written === 'failed' ? 'spilled' : 'queued'\n if (written === 'failed') unavailable()\n // an existing row is the drainer's (its own lease) and a spilled event already has its sender, even when the\n // outbox is back: a second sender would only race them\n if (written === 'exists' || spill.has(entry)) return { status, body }\n if (written === 'failed') {\n const evicted = spill.add(entry)\n if (evicted)\n logger.warn('inr_outbox_dropped_total', {\n eventType: evicted.eventType,\n eventId: evicted.eventId,\n status: evicted.lastError?.status ?? null,\n code: evicted.lastError?.code ?? null,\n reason: 'memory_full',\n })\n }\n start(entry)\n return { status, body }\n } catch (err) {\n logger.warn('inr.report failed', {\n error: err instanceof Error ? err.message : String(err),\n })\n return { status: 'invalid', error: 'internal' }\n }\n },\n idle,\n forget,\n drainNow: drainer.drainNow,\n close: () => drainer.close(idle),\n landingRelay: createRelay({\n enabled,\n forward: (req) => track(delivery.request(req)),\n warn: logger.warn,\n }),\n }\n}\n"]}
|