{"version":3,"sources":["../../src/stores/redis.ts"],"sourcesContent":["import type { DPoPNonceStore } from \"./types.js\";\n\nconst DEFAULT_TTL = 300; // 5 minutes in seconds — matches default jtiTtl\nconst DEFAULT_KEY_PREFIX = \"dpop:jti:\";\n\n/** Minimal Redis client subset compatible with ioredis, node-redis, and @upstash/redis. */\nexport interface RedisClientLike {\n\tset(key: string, value: string, options?: { NX?: boolean; EX?: number }): Promise<string | null>;\n}\n\nexport interface RedisStoreOptions {\n\t/** Redis client instance (ioredis, node-redis, or @upstash/redis). */\n\tclient: RedisClientLike;\n\t/** Maximum TTL in seconds applied to each jti entry (default: 300 = 5 min). */\n\tttl?: number;\n\t/** Key prefix to namespace replay-cache entries (default: \"dpop:jti:\"). */\n\tkeyPrefix?: string;\n}\n\n/**\n * Redis-backed replay cache. Uses `SET key 1 NX EX <ttl>` for atomic insert-if-absent —\n * a single round-trip whose semantics match RFC 9449 §11.1: exactly one concurrent caller\n * sees `OK` (return true), the rest get `null` (return false).\n *\n * The TTL is the smaller of `expiresAt - now` and the configured `ttl` ceiling, so the\n * entry is auto-removed by Redis once the proof's freshness window closes. `purge()` is\n * therefore a no-op returning 0.\n */\nexport function redisStore(options: RedisStoreOptions): DPoPNonceStore {\n\tconst { client, ttl = DEFAULT_TTL, keyPrefix = DEFAULT_KEY_PREFIX } = options;\n\n\treturn {\n\t\tasync check(jti, expiresAt) {\n\t\t\tconst remainingSeconds = Math.ceil((expiresAt - Date.now()) / 1000);\n\t\t\tif (remainingSeconds <= 0) return false;\n\t\t\tconst ex = Math.min(ttl, remainingSeconds);\n\t\t\tconst result = await client.set(`${keyPrefix}${jti}`, \"1\", { NX: true, EX: ex });\n\t\t\treturn result === \"OK\";\n\t\t},\n\n\t\tasync purge() {\n\t\t\t// Redis handles expiration automatically via EX — no manual purge needed\n\t\t\treturn 0;\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAM,cAAc;AACpB,IAAM,qBAAqB;AAyBpB,SAAS,WAAW,SAA4C;AACtE,QAAM,EAAE,QAAQ,MAAM,aAAa,YAAY,mBAAmB,IAAI;AAEtE,SAAO;AAAA,IACN,MAAM,MAAM,KAAK,WAAW;AAC3B,YAAM,mBAAmB,KAAK,MAAM,YAAY,KAAK,IAAI,KAAK,GAAI;AAClE,UAAI,oBAAoB,EAAG,QAAO;AAClC,YAAM,KAAK,KAAK,IAAI,KAAK,gBAAgB;AACzC,YAAM,SAAS,MAAM,OAAO,IAAI,GAAG,SAAS,GAAG,GAAG,IAAI,KAAK,EAAE,IAAI,MAAM,IAAI,GAAG,CAAC;AAC/E,aAAO,WAAW;AAAA,IACnB;AAAA,IAEA,MAAM,QAAQ;AAEb,aAAO;AAAA,IACR;AAAA,EACD;AACD;","names":[]}