@proof-holdings/delegation-verifier 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -85,7 +85,9 @@ presented as *"X says it authorized this"*, never as *verified*.
85
85
  1. **Trust policy** — the token's `iss` must be one you named. No trust list, no verification.
86
86
  2. **Signature** — RS256/ES256 against the issuer's JWKS. The algorithm is chosen by the
87
87
  verifier, never read from the token, so `alg: none` and HMAC forgeries die before any key is
88
- fetched. Key sets are cached; an unknown `kid` triggers at most one refetch per 30s.
88
+ fetched. Key sets are cached; an unknown `kid` triggers at most one refetch per 30s. The
89
+ signing key's purpose, window and tombstone are checked here too — see
90
+ [Key rotation](#key-rotation-and-the-key-set-cache).
89
91
  3. **Claims** — `token_type`, schema version, `exp`/`iat` (5s tolerance by default), and the
90
92
  required claim set.
91
93
  4. **Principal** — pinned to the domain you expect, when you supply one. See above: without it
@@ -121,6 +123,56 @@ than before.
121
123
  `POST <statusEndpoint>` with `{"proof_token": "<jwt>"}` answering JSON with at least
122
124
  `{"valid": boolean}` and optionally `{"reason": "revoked" | "suspended" | ...}`.
123
125
 
126
+ ## Key rotation and the key-set cache
127
+
128
+ An issuer's JWKS may carry several keys at once. Beside the standard members, a key may declare
129
+ `proof_purpose` (`proof`, `delegation` or `status-list`), a window (`not_before`, `not_after`,
130
+ `max_token_lifetime` — integer seconds) or `proof_legacy: true`; revoked keys are listed in a
131
+ top-level `proof_tombstones: [{ "kid", "revoked_at" }]`. A key set without these members verifies
132
+ exactly as before. Once any key carries `proof_purpose`:
133
+
134
+ - a delegation must be signed by a `delegation` key or a legacy one (`wrong_key_purpose`);
135
+ - its `iat` must lie in the key's window, ± 5 minutes (`outside_key_window`), and its `exp` no later
136
+ than `iat + max_token_lifetime` (`token_lifetime_exceeded`) — legacy keys skip both;
137
+ - a token without `kid` is tried against legacy keys only.
138
+
139
+ The status list's own signing key is held to the same rules as a `status-list` key; a list signed by
140
+ a key that fails them counts as unreadable, exactly like a list that could not be fetched.
141
+
142
+ **One response is never trusted for long.** A new key verifies from its first sighting, so an
143
+ emergency key works at once. But the verifier only *remembers* a key carrying `proof_purpose` or
144
+ `proof_legacy` — keeps it after it disappears from the JWKS, refuses new key material under its
145
+ `kid`, refuses whole a document that widens its window — once two fetches at least 5 minutes apart
146
+ served it unchanged; until then the next document replaces or drops it. A narrower window and a
147
+ tombstone wait for the same confirmation: a tombstone applies only when a fetch at least 5 minutes
148
+ after its first sighting still carries it (a fetch in between that drops it starts over;
149
+ `refreshJwks` forces the second fetch), and once applied it stays until `revoked_at` + 365 days or
150
+ `clearTombstones()`, whatever later documents say.
151
+
152
+ The key set is refetched every 10 minutes. When a refetch fails, the cache's confirmed keys keep
153
+ answering until it is `maxJwksAgeMs` old, then the answer is `jwks_stale`; an applied tombstone
154
+ answers `key_revoked` at any age. A failed refetch of a cached set is retried at most once per 30s.
155
+ The cache lives in the process, keyed by `jwksUri`.
156
+
157
+ | Option | Default | Meaning |
158
+ | --- | --- | --- |
159
+ | `maxJwksAgeMs` | 24 h | How old the cache may be when a refetch fails. Above 25 days, non-integer or ≤ 0 is `invalid_options`. |
160
+ | `keySetStore` | none | `{ load(jwksUri), save(jwksUri, state) }`, sync or async, opaque string state. Persists the key set — tombstones included — across restarts and cold starts. A failing store never fails a verification. |
161
+ | `onJwksEvent` | ignored | Receives `{ type, jwksUri, kid?, message }`: `tombstone_pending`, `tombstone_applied`, `tombstone_for_live_key`, `window_narrowing_pending`, `window_narrowing_applied`, `window_widening_rejected`, `key_material_changed`, `kid_vanished`, `store_error`. |
162
+ | `timeoutMs` | 5000 | Bounds each network request and each `keySetStore` call. |
163
+
164
+ Exported alongside `verifyDelegation`:
165
+
166
+ - `refreshJwks({ jwksUri, fetch?, timeoutMs?, keySetStore?, onJwksEvent? })` — refetch now,
167
+ ignoring the TTL and cooldowns; resolves `{ ok: true }` or `{ ok: false, message }`. The method a
168
+ `jwks_stale` result's `refreshHint` names.
169
+ - `clearTombstones({ jwksUri?, keySetStore? })` — the manual reset: forgets applied and pending
170
+ tombstones for one key set (and its persisted copy), or for every set in memory.
171
+ - `getJwksDiagnostics(jwksUri)` — cache age, whether the registry is live, vanished keys, pending and
172
+ applied tombstones; `null` for a key set this process has never used.
173
+ - `DEFAULT_MAX_JWKS_AGE_MS`, `MAX_JWKS_AGE_CAP_MS` — to validate your own configuration against the
174
+ same bounds.
175
+
124
176
  ## Failure reasons
125
177
 
126
178
  Every failure carries an `outcome: 'invalid' | 'unconfirmed'` beside `reason` —
@@ -138,7 +190,12 @@ because they occur in practice).
138
190
  | `untrusted_issuer` | `invalid` | Signed by someone you did not name. |
139
191
  | `unsupported_algorithm` | `invalid` | The token asked for an algorithm this verifier does not accept. |
140
192
  | `unknown_key` / `bad_signature` | `invalid` | No matching key, or the signature does not hold. |
141
- | `jwks_unavailable` | `unconfirmed` | Could not read the key set — "I could not check", not "it is bad". |
193
+ | `jwks_unavailable` | `unconfirmed` | Could not read the key set, or could not refetch it for an unknown `kid` — "I could not check", not "it is bad". |
194
+ | `jwks_stale` | `unconfirmed` | A refetch failed and the cached key set is older than `maxJwksAgeMs`. Carries `cacheAgeSeconds` (null when unknown) and `refreshHint: { jwksUri, method: 'refreshJwks' }`. |
195
+ | `key_revoked` | `invalid` | The issuer revoked the signing key (an applied JWKS tombstone). Carries `pullHint: { issuerOrigin, handle }` — where to ask for a re-signed token. The handle is read from a token whose signature was not checked: an address to ask, not a verified identity. |
196
+ | `wrong_key_purpose` | `invalid` | The signing key belongs to another key family than a delegation. |
197
+ | `outside_key_window` | `invalid` | The token's `iat` lies outside the signing key's window (5 minutes of skew allowed). |
198
+ | `token_lifetime_exceeded` | `invalid` | `exp` lies beyond `iat` plus the signing key's `max_token_lifetime`. |
142
199
  | `not_a_delegation` / `unsupported_schema` | `invalid` | Wrong token type or a schema major this version does not understand. |
143
200
  | `expired` / `not_yet_valid` / `malformed_claims` | `invalid` | Claim-level rejections. |
144
201
  | `principal_mismatch` | `invalid` | Issued by a different domain than you expected. |
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../src/delegate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAA6B,CAAC;AAEhF,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAQpD,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAIjE;AAqGD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAyB7D"}
1
+ {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../src/delegate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAA6B,CAAC;AAEhF,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAQpD,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAIjE;AAsGD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAyB7D"}
package/dist/delegate.js CHANGED
@@ -116,10 +116,11 @@ function canonicalizeUrl(value) {
116
116
  throw new DelegateIdentifierError('delegate URL must not carry a fragment');
117
117
  }
118
118
  // URL() already lowercases the host and strips an explicit default port; pathname keeps its
119
- // case. Trailing slash is canonicalized away except at the root, where it is always '/'.
119
+ // case. Trailing slash is canonicalized away except at the root, where it is always '/' — a
120
+ // path of slashes only collapses to that root, so the result is idempotent.
120
121
  let pathname = parsed.pathname;
121
122
  if (pathname.length > 1 && pathname.endsWith('/')) {
122
- pathname = pathname.replace(/\/+$/, '');
123
+ pathname = pathname.replace(/\/+$/, '') || '/';
123
124
  }
124
125
  return enforceLength(`https://${parsed.host}${pathname}`);
125
126
  }
@@ -1 +1 @@
1
- {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../src/delegate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../src/delegate.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -29,9 +29,9 @@ export type { FoundPublication } from './publication.js';
29
29
  export { parseDelegationPointer, pointerRecordName, POINTER_VERSION, POINTER_RECORD_PREFIX, } from './publication.js';
30
30
  export type { PointerParseResult, PointerRejection } from './publication.js';
31
31
  export { canonicalizeDelegate, canonicalizeScopes, DelegateIdentifierError, DELEGATE_TYPES, DELEGATE_MAX_LENGTH, } from './delegate.js';
32
- export { resetJwksCache, SUPPORTED_ALGORITHMS } from './jwks.js';
33
- export type { SupportedAlgorithm } from './jwks.js';
32
+ export { clearTombstones, DEFAULT_MAX_JWKS_AGE_MS, getJwksDiagnostics, MAX_JWKS_AGE_CAP_MS, refreshJwks, resetJwksCache, SUPPORTED_ALGORITHMS, } from './jwks.js';
33
+ export type { JwksDiagnostics, SupportedAlgorithm } from './jwks.js';
34
34
  export { readStatusSlot } from './status.js';
35
35
  export { classifyFailureReason } from './types.js';
36
- export type { DelegateInput, DelegateType, FailureOutcome, FailureReason, FetchLike, TrustedIssuer, VerificationFailure, VerificationResult, VerificationSuccess, VerifiedDelegation, VerifyOptions, } from './types.js';
36
+ export type { DelegateInput, DelegateType, FailureOutcome, FailureReason, FetchLike, JwksEvent, JwksEventType, KeySetStore, TrustedIssuer, VerificationFailure, VerificationResult, VerificationSuccess, VerifiedDelegation, VerifyOptions, } from './types.js';
37
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD;;;;;GAKG;AACH,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD;;;;;GAKG;AACH,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,aAAa,EACb,SAAS,EACT,SAAS,EACT,aAAa,EACb,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ export { verifyPublishedDelegation, extractDelegationPublications, DELEGATION_ME
27
27
  */
28
28
  export { parseDelegationPointer, pointerRecordName, POINTER_VERSION, POINTER_RECORD_PREFIX, } from './publication.js';
29
29
  export { canonicalizeDelegate, canonicalizeScopes, DelegateIdentifierError, DELEGATE_TYPES, DELEGATE_MAX_LENGTH, } from './delegate.js';
30
- export { resetJwksCache, SUPPORTED_ALGORITHMS } from './jwks.js';
30
+ export { clearTombstones, DEFAULT_MAX_JWKS_AGE_MS, getJwksDiagnostics, MAX_JWKS_AGE_CAP_MS, refreshJwks, resetJwksCache, SUPPORTED_ALGORITHMS, } from './jwks.js';
31
31
  export { readStatusSlot } from './status.js';
32
32
  export { classifyFailureReason } from './types.js';
33
33
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAE1B;;;;;GAKG;AACH,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,wBAAwB,EACxB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAE1B;;;;;GAKG;AACH,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,oBAAoB,GACrB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
package/dist/jwks.d.ts CHANGED
@@ -1,47 +1,148 @@
1
1
  /**
2
- * JWKS retrieval and key cache.
2
+ * JWKS retrieval and key cache — the I/O half. The rules a fetched key set is held to (merge,
3
+ * tombstones, purpose, window) live in `keyset.ts`; this file decides WHEN to fetch and what to
4
+ * answer when a fetch fails.
3
5
  *
4
- * Three behaviours here are load-bearing rather than tidy, all learned from the hand-rolled Go
5
- * verifier that shipped before this package:
6
+ * Behaviours that are load-bearing rather than tidy, the first three learned from the hand-rolled
7
+ * Go verifier that shipped before this package:
6
8
  *
7
9
  * - The algorithm is chosen from THIS list, never from the token's own header. A token that
8
10
  * asks for `none` or for an HMAC is refused before any key is looked up.
9
- * - An unknown `kid` is indistinguishable from a rotated key, so a miss triggers at most one
10
- * refetch per cooldown window. Without it every junk-kid token costs one outbound request
11
- * and a busy verifier trips the issuer's rate limit — failing its GOOD tokens too.
11
+ * - An unknown `kid` is indistinguishable from a rotated (or emergency) key, so a miss triggers
12
+ * at most one refetch per cooldown window. Without it every junk-kid token costs one outbound
13
+ * request and a busy verifier trips the issuer's rate limit — failing its GOOD tokens too.
12
14
  * - Concurrent misses share ONE in-flight fetch per key set, with the cache re-checked after
13
15
  * it resolves. Serialising is what makes the cooldown hold under concurrency.
16
+ * - A failed refetch does not discard a cached key set. Under `maxJwksAgeMs` its CONFIRMED keys
17
+ * keep answering (a kid they do not cover is `jwks_unavailable`: it may be new); over it the answer
18
+ * is `jwks_stale` — except for an applied tombstone, which is `key_revoked` at any age. A set
19
+ * that was never fetched has no cache to fall back on, so its failure stays `jwks_unavailable`
20
+ * and is retried on every call.
21
+ * - Age is measured on a monotonic clock in-process. Only what is persisted uses wall clock.
14
22
  */
15
- import type { FetchLike } from './types.js';
23
+ import type { KeyFamily, KeyPolicyViolation, KeyRecord } from './keyset.js';
24
+ import type { FetchLike, JwksEvent, KeySetStore } from './types.js';
16
25
  export declare const SUPPORTED_ALGORITHMS: readonly ["RS256", "ES256"];
17
26
  export type SupportedAlgorithm = (typeof SUPPORTED_ALGORITHMS)[number];
18
- /** How long a `kid` miss suppresses further refetches of the same key set. */
27
+ /** How long a `kid` miss — or a failed refetch of a cached set — suppresses further fetches. */
19
28
  export declare const KEY_MISS_COOLDOWN_MS = 30000;
20
29
  /** How long a successfully fetched key set is reused without refetching. */
21
30
  export declare const KEY_SET_TTL_MS: number;
31
+ /** Default `maxJwksAgeMs`. */
32
+ export declare const DEFAULT_MAX_JWKS_AGE_MS: number;
33
+ /** Largest accepted `maxJwksAgeMs` — below the issuer's ~30-day lead on its next key. */
34
+ export declare const MAX_JWKS_AGE_CAP_MS: number;
22
35
  /**
23
36
  * A key set is kilobytes. Anything larger is not a JWKS, and the request is driven by input the
24
37
  * verifier does not control, so it is capped rather than streamed to completion.
25
38
  */
26
39
  export declare const MAX_REMOTE_BODY_BYTES: number;
27
- /** Test seam — drops every cached key set. */
40
+ export interface JwksClock {
41
+ monotonicMs(): number;
42
+ wallMs(): number;
43
+ }
44
+ /** Test seam — replaces both clocks; `null` restores the system clocks. Not exported publicly. */
45
+ export declare function setJwksClockForTests(replacement: JwksClock | null): void;
46
+ /** The per-call knobs that shape key-set handling. */
47
+ export interface KeySetOptions {
48
+ maxJwksAgeMs: number;
49
+ keySetStore?: KeySetStore;
50
+ onJwksEvent?: (event: JwksEvent) => void;
51
+ }
52
+ /** Test seam — drops every cached key set, tombstones included. */
28
53
  export declare function resetJwksCache(): void;
29
54
  export declare class JwksUnavailableError extends Error {
30
55
  constructor(message: string);
31
56
  }
32
57
  export declare function isSupportedAlgorithm(alg: unknown): alg is SupportedAlgorithm;
58
+ export interface KeyCandidate {
59
+ key: CryptoKey;
60
+ record: KeyRecord;
61
+ }
62
+ export type KeyResolution = {
63
+ kind: 'keys';
64
+ candidates: KeyCandidate[];
65
+ registryLive: boolean;
66
+ } | {
67
+ kind: 'revoked';
68
+ kid: string;
69
+ } | {
70
+ kind: 'wrong_purpose';
71
+ kid: string;
72
+ } | {
73
+ kind: 'unknown';
74
+ } | {
75
+ kind: 'stale';
76
+ cacheAgeSeconds: number | null;
77
+ } | {
78
+ kind: 'unavailable';
79
+ message: string;
80
+ };
33
81
  /**
34
- * Candidate verification keys for `kid`, fetching the key set at most once per cooldown.
35
- * Returns an empty array when the key is genuinely unknown; throws `JwksUnavailableError`
36
- * when the key set could not be read at all ("I could not check" is not "the token is bad").
82
+ * The keys that may verify a token of `family` carrying `kid` — or why none may. Fetches the key
83
+ * set when it is older than the TTL, or once per cooldown when `kid` is unknown.
37
84
  */
38
- export declare function getVerificationKeys(params: {
85
+ export declare function resolveVerificationKeys(params: {
39
86
  jwksUri: string;
40
87
  kid?: string;
41
88
  alg: SupportedAlgorithm;
89
+ family: KeyFamily;
42
90
  fetch: FetchLike;
43
91
  timeoutMs: number;
44
- }): Promise<CryptoKey[]>;
92
+ } & KeySetOptions): Promise<KeyResolution>;
45
93
  /** Verify a JWS signature against one candidate key. */
46
94
  export declare function verifySignature(key: CryptoKey, alg: SupportedAlgorithm, signingInput: string, signature: Uint8Array): Promise<boolean>;
95
+ /**
96
+ * Signature first, then the window and lifetime of the key that verified it — so a forged token
97
+ * is reported as `bad_signature`, not as a policy violation of a key it never came from.
98
+ */
99
+ export declare function verifyWithCandidates(resolution: Extract<KeyResolution, {
100
+ kind: 'keys';
101
+ }>, alg: SupportedAlgorithm, signingInput: string, signature: Uint8Array, token: {
102
+ iat: unknown;
103
+ exp: unknown;
104
+ }): Promise<'ok' | 'bad_signature' | KeyPolicyViolation>;
105
+ /**
106
+ * Refetch a key set now, ignoring the TTL and cooldowns — the method a `jwks_stale` answer names.
107
+ * Resolves with the outcome rather than throwing.
108
+ */
109
+ export declare function refreshJwks(params: {
110
+ jwksUri: string;
111
+ fetch?: FetchLike;
112
+ timeoutMs?: number;
113
+ keySetStore?: KeySetStore;
114
+ onJwksEvent?: (event: JwksEvent) => void;
115
+ }): Promise<{
116
+ ok: true;
117
+ } | {
118
+ ok: false;
119
+ message: string;
120
+ }>;
121
+ /**
122
+ * Forget every applied and pending tombstone — the documented manual reset. With `jwksUri`, only
123
+ * that key set (and, given a `keySetStore`, its persisted copy); without, every set in memory.
124
+ */
125
+ export declare function clearTombstones(params?: {
126
+ jwksUri?: string;
127
+ keySetStore?: KeySetStore;
128
+ }): Promise<void>;
129
+ export interface JwksDiagnostics {
130
+ jwksUri: string;
131
+ /** Age of the cached set in seconds; null when never fetched or the persisted age is unknown. */
132
+ cacheAgeSeconds: number | null;
133
+ registryLive: boolean;
134
+ /** Confirmed registry kids no longer served before their retention ended — kept with last-known state. */
135
+ vanishedKids: string[];
136
+ pendingTombstones: Array<{
137
+ kid: string;
138
+ revokedAt: number;
139
+ pendingForSeconds: number;
140
+ }>;
141
+ appliedTombstones: Array<{
142
+ kid: string;
143
+ revokedAt: number;
144
+ }>;
145
+ }
146
+ /** What the verifier currently holds for one key set, or null if it has never been used. */
147
+ export declare function getJwksDiagnostics(jwksUri: string): JwksDiagnostics | null;
47
148
  //# sourceMappingURL=jwks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwks.d.ts","sourceRoot":"","sources":["../src/jwks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,oBAAoB,6BAA8B,CAAC;AAChE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAC3C,4EAA4E;AAC5E,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAchD,8CAA8C;AAC9C,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAkBD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,kBAAkB,CAE5E;AA8ED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,kBAAkB,CAAC;IACxB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAmDvB;AAED,wDAAwD;AACxD,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,GAAG,EAAE,kBAAkB,EACvB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAYlB"}
1
+ {"version":3,"file":"jwks.d.ts","sourceRoot":"","sources":["../src/jwks.ts"],"names":[],"mappings":"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"}