@orangecheck/me-client 0.32.4 → 0.33.0

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/dist/server.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SessionPayload, VerifyOcOptions, SessionRequestHeaders } from '@orangecheck/auth-core';
2
2
  export { BondClaim, SessionPayload, VerifyOcOptions, bondMeets, readBondClaim, verifyOcToken } from '@orangecheck/auth-core';
3
- export { A as ActivityAttestation, a as ActivityAttestationBundle, b as ActivityVerifyCheck, c as ActivityVerifyResult, V as VerifyActivityOptions, i as identity, r as refreshEnvelopeJwks, v as verifyActivityAttestation } from './identity-6pjtyKYh.mjs';
3
+ export { A as ActivityAttestation, a as ActivityAttestationBundle, b as ActivityVerifyCheck, c as ActivityVerifyResult, V as VerifyActivityOptions, i as identity, r as refreshEnvelopeJwks, v as verifyActivityAttestation } from './identity-DfxCvxuH.mjs';
4
4
 
5
5
  declare function getOcSession(headers: SessionRequestHeaders | Headers, options?: VerifyOcOptions): Promise<SessionPayload | null>;
6
6
  interface NextApiRequestLike {
package/dist/server.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SessionPayload, VerifyOcOptions, SessionRequestHeaders } from '@orangecheck/auth-core';
2
2
  export { BondClaim, SessionPayload, VerifyOcOptions, bondMeets, readBondClaim, verifyOcToken } from '@orangecheck/auth-core';
3
- export { A as ActivityAttestation, a as ActivityAttestationBundle, b as ActivityVerifyCheck, c as ActivityVerifyResult, V as VerifyActivityOptions, i as identity, r as refreshEnvelopeJwks, v as verifyActivityAttestation } from './identity-6pjtyKYh.js';
3
+ export { A as ActivityAttestation, a as ActivityAttestationBundle, b as ActivityVerifyCheck, c as ActivityVerifyResult, V as VerifyActivityOptions, i as identity, r as refreshEnvelopeJwks, v as verifyActivityAttestation } from './identity-DfxCvxuH.js';
4
4
 
5
5
  declare function getOcSession(headers: SessionRequestHeaders | Headers, options?: VerifyOcOptions): Promise<SessionPayload | null>;
6
6
  interface NextApiRequestLike {
package/dist/server.js CHANGED
@@ -9,46 +9,27 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
9
9
  // node_modules/jose/dist/webapi/lib/buffer_utils.js
10
10
  new TextEncoder();
11
11
  var decoder = new TextDecoder();
12
-
13
- // node_modules/jose/dist/webapi/lib/base64.js
14
- function decodeBase64(encoded) {
15
- if (Uint8Array.fromBase64) {
16
- return Uint8Array.fromBase64(encoded);
12
+ new TextDecoder("utf-8", { fatal: true });
13
+ function decodeBase64(encoded, url = false) {
14
+ if (Uint8Array.fromBase64)
15
+ return Uint8Array.fromBase64(encoded, { alphabet: url ? "base64url" : "base64" });
16
+ if (url) {
17
+ if (encoded.includes("+") || encoded.includes("/"))
18
+ throw new TypeError("Invalid base64url");
19
+ encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
17
20
  }
18
- const binary = atob(encoded);
19
- const bytes = new Uint8Array(binary.length);
20
- for (let i = 0; i < binary.length; i++) {
21
+ const binary = atob(encoded), bytes = new Uint8Array(binary.length);
22
+ for (let i = 0; i < binary.length; i++)
21
23
  bytes[i] = binary.charCodeAt(i);
22
- }
23
24
  return bytes;
24
25
  }
25
26
 
26
- // node_modules/jose/dist/webapi/util/base64url.js
27
- function decode(input) {
28
- if (Uint8Array.fromBase64) {
29
- return Uint8Array.fromBase64(typeof input === "string" ? input : decoder.decode(input), {
30
- alphabet: "base64url"
31
- });
32
- }
33
- let encoded = input;
34
- if (encoded instanceof Uint8Array) {
35
- encoded = decoder.decode(encoded);
36
- }
37
- encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
38
- try {
39
- return decodeBase64(encoded);
40
- } catch {
41
- throw new TypeError("The input to be decoded is not correctly encoded.");
42
- }
43
- }
44
-
45
27
  // node_modules/jose/dist/webapi/util/errors.js
46
28
  var JOSEError = class extends Error {
47
29
  constructor(message, options) {
48
30
  super(message, options);
49
31
  __publicField(this, "code", "ERR_JOSE_GENERIC");
50
- this.name = this.constructor.name;
51
- Error.captureStackTrace?.(this, this.constructor);
32
+ this.name = this.constructor.name, Error.captureStackTrace?.(this, this.constructor);
52
33
  }
53
34
  };
54
35
  __publicField(JOSEError, "code", "ERR_JOSE_GENERIC");
@@ -63,166 +44,258 @@ var _a, _b;
63
44
  var JWKSMultipleMatchingKeys = class extends (_b = JOSEError, _a = Symbol.asyncIterator, _b) {
64
45
  constructor(message = "multiple matching keys found in the JSON Web Key Set", options) {
65
46
  super(message, options);
66
- __publicField(this, _a);
47
+ __publicField(this, _a, async function* () {
48
+ });
67
49
  __publicField(this, "code", "ERR_JWKS_MULTIPLE_MATCHING_KEYS");
68
50
  }
69
51
  };
70
52
  __publicField(JWKSMultipleMatchingKeys, "code", "ERR_JWKS_MULTIPLE_MATCHING_KEYS");
71
53
 
72
- // node_modules/jose/dist/webapi/lib/type_checks.js
73
- var isObjectLike = (value) => typeof value === "object" && value !== null;
54
+ // node_modules/jose/dist/webapi/util/base64url.js
55
+ var invalid = "The input to be decoded is not correctly encoded.";
56
+ function decode(input) {
57
+ try {
58
+ return decodeBase64(typeof input == "string" ? input : decoder.decode(input), true);
59
+ } catch (cause) {
60
+ throw new TypeError(invalid, { cause });
61
+ }
62
+ }
63
+
64
+ // node_modules/jose/dist/webapi/lib/validate.js
74
65
  function isObject(input) {
75
- if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") {
66
+ if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]")
76
67
  return false;
77
- }
78
- if (Object.getPrototypeOf(input) === null) {
79
- return true;
80
- }
81
- let proto = input;
82
- while (Object.getPrototypeOf(proto) !== null) {
83
- proto = Object.getPrototypeOf(proto);
84
- }
85
- return Object.getPrototypeOf(input) === proto;
68
+ const prototype = Object.getPrototypeOf(input);
69
+ return prototype === null || Object.getPrototypeOf(prototype) === null;
86
70
  }
87
71
 
88
- // node_modules/jose/dist/webapi/lib/jwk_to_key.js
89
- var unsupportedAlg = 'Invalid or unsupported JWK "alg" (Algorithm) Parameter value';
90
- function subtleMapping(jwk) {
91
- let algorithm;
92
- let keyUsages;
93
- switch (jwk.kty) {
94
- case "AKP": {
95
- switch (jwk.alg) {
96
- case "ML-DSA-44":
97
- case "ML-DSA-65":
98
- case "ML-DSA-87":
99
- algorithm = { name: jwk.alg };
100
- keyUsages = jwk.priv ? ["sign"] : ["verify"];
101
- break;
102
- default:
103
- throw new JOSENotSupported(unsupportedAlg);
104
- }
105
- break;
106
- }
107
- case "RSA": {
108
- switch (jwk.alg) {
109
- case "PS256":
110
- case "PS384":
111
- case "PS512":
112
- algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` };
113
- keyUsages = jwk.d ? ["sign"] : ["verify"];
114
- break;
115
- case "RS256":
116
- case "RS384":
117
- case "RS512":
118
- algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` };
119
- keyUsages = jwk.d ? ["sign"] : ["verify"];
120
- break;
121
- case "RSA-OAEP":
122
- case "RSA-OAEP-256":
123
- case "RSA-OAEP-384":
124
- case "RSA-OAEP-512":
125
- algorithm = {
126
- name: "RSA-OAEP",
127
- hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`
128
- };
129
- keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
130
- break;
131
- default:
132
- throw new JOSENotSupported(unsupportedAlg);
133
- }
134
- break;
135
- }
136
- case "EC": {
137
- switch (jwk.alg) {
138
- case "ES256":
139
- case "ES384":
140
- case "ES512":
141
- algorithm = {
142
- name: "ECDSA",
143
- namedCurve: { ES256: "P-256", ES384: "P-384", ES512: "P-521" }[jwk.alg]
144
- };
145
- keyUsages = jwk.d ? ["sign"] : ["verify"];
146
- break;
147
- case "ECDH-ES":
148
- case "ECDH-ES+A128KW":
149
- case "ECDH-ES+A192KW":
150
- case "ECDH-ES+A256KW":
151
- algorithm = { name: "ECDH", namedCurve: jwk.crv };
152
- keyUsages = jwk.d ? ["deriveBits"] : [];
153
- break;
154
- default:
155
- throw new JOSENotSupported(unsupportedAlg);
156
- }
157
- break;
158
- }
159
- case "OKP": {
160
- switch (jwk.alg) {
161
- case "Ed25519":
162
- case "EdDSA":
163
- algorithm = { name: "Ed25519" };
164
- keyUsages = jwk.d ? ["sign"] : ["verify"];
165
- break;
166
- case "ECDH-ES":
167
- case "ECDH-ES+A128KW":
168
- case "ECDH-ES+A192KW":
169
- case "ECDH-ES+A256KW":
170
- algorithm = { name: jwk.crv };
171
- keyUsages = jwk.d ? ["deriveBits"] : [];
172
- break;
173
- default:
174
- throw new JOSENotSupported(unsupportedAlg);
175
- }
176
- break;
177
- }
178
- default:
179
- throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
180
- }
181
- return { algorithm, keyUsages };
72
+ // node_modules/jose/dist/webapi/lib/key.js
73
+ function snapshotJwk(jwk) {
74
+ return { __proto__: null, ...jwk };
182
75
  }
183
- async function jwkToKey(jwk) {
184
- if (!jwk.alg) {
185
- throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
76
+ function normalizeJwk(jwk) {
77
+ const normalized = snapshotJwk(jwk);
78
+ if (normalized.ext !== void 0 && typeof normalized.ext != "boolean")
79
+ throw new TypeError('"ext" (Extractable) Parameter must be a boolean');
80
+ if (normalized.key_ops !== void 0) {
81
+ const value = normalized.key_ops, keyOps = Array.isArray(value) ? [...value] : void 0;
82
+ if (!keyOps || keyOps.some((operation) => typeof operation != "string") || new Set(keyOps).size !== keyOps.length)
83
+ throw new TypeError('"key_ops" (Key Operations) Parameter must be an array of unique strings');
84
+ normalized.key_ops = keyOps;
186
85
  }
187
- const { algorithm, keyUsages } = subtleMapping(jwk);
188
- const keyData = { ...jwk };
189
- if (keyData.kty !== "AKP") {
190
- delete keyData.alg;
191
- }
192
- delete keyData.use;
193
- return crypto.subtle.importKey("jwk", keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);
86
+ return normalized;
87
+ }
88
+ async function jwkToKey(entry, jwk, extractable) {
89
+ if (!entry.kty.includes(jwk.kty))
90
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
91
+ const algorithm = entry.resolve?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle, isPrivate = !!(jwk.d || jwk.priv), keyData = { ...jwk, ext: jwk.ext };
92
+ return keyData.kty !== "AKP" && delete keyData.alg, delete keyData.use, crypto.subtle.importKey("jwk", keyData, algorithm, keyData.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
93
+ }
94
+
95
+ // node_modules/jose/dist/webapi/lib/key_descriptor.js
96
+ function table(entries) {
97
+ const out = { __proto__: null };
98
+ for (const alg in entries)
99
+ out[alg] = { ...entries[alg], alg };
100
+ return out;
101
+ }
102
+
103
+ // node_modules/jose/dist/webapi/lib/jwe_algorithms.js
104
+ var wrap = [
105
+ ["encrypt", "wrapKey"],
106
+ ["decrypt", "unwrapKey"]
107
+ ];
108
+ var derive = [[], ["deriveBits"]];
109
+ var none = [[], []];
110
+ function rsaes(bits) {
111
+ return {
112
+ kty: ["RSA"],
113
+ mode: "key-encryption",
114
+ subtle: { name: "RSA-OAEP", hash: `SHA-${bits}` },
115
+ usages: wrap,
116
+ ops: ["wrapKey", "unwrapKey"]
117
+ };
118
+ }
119
+ function ecdh(mode) {
120
+ return {
121
+ kty: ["EC", "OKP"],
122
+ mode,
123
+ subtle: { name: "ECDH" },
124
+ resolve: ({ kty, crv, asymmetricKeyType }) => {
125
+ if (crv === "X25519" || asymmetricKeyType === "x25519")
126
+ return { name: "X25519" };
127
+ if (kty === "OKP")
128
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
129
+ return { name: "ECDH", namedCurve: crv };
130
+ },
131
+ usages: derive,
132
+ ops: [void 0, "deriveBits"]
133
+ };
134
+ }
135
+ function aeskw(bits, gcm = false) {
136
+ return {
137
+ kty: ["oct"],
138
+ mode: "key-wrapping",
139
+ secret: true,
140
+ subtle: { name: gcm ? "AES-GCM" : "AES-KW", length: bits },
141
+ usages: none,
142
+ ops: gcm ? ["encrypt", "decrypt"] : ["wrapKey", "unwrapKey"]
143
+ };
144
+ }
145
+ function pbes2() {
146
+ return {
147
+ kty: ["oct"],
148
+ mode: "key-wrapping",
149
+ secret: true,
150
+ subtle: { name: "PBKDF2" },
151
+ usages: none,
152
+ ops: ["deriveBits", "deriveBits"]
153
+ };
154
+ }
155
+ var JWE = table({
156
+ dir: {
157
+ kty: ["oct"],
158
+ mode: "direct-encryption",
159
+ secret: true,
160
+ subtle: { name: "AES-GCM" },
161
+ usages: none,
162
+ ops: ["encrypt", "decrypt"]
163
+ },
164
+ "RSA-OAEP": rsaes(1),
165
+ "RSA-OAEP-256": rsaes(256),
166
+ "RSA-OAEP-384": rsaes(384),
167
+ "RSA-OAEP-512": rsaes(512),
168
+ "ECDH-ES": ecdh("direct-key-agreement"),
169
+ "ECDH-ES+A128KW": ecdh("key-agreement-with-key-wrapping"),
170
+ "ECDH-ES+A192KW": ecdh("key-agreement-with-key-wrapping"),
171
+ "ECDH-ES+A256KW": ecdh("key-agreement-with-key-wrapping"),
172
+ A128KW: aeskw(128),
173
+ A192KW: aeskw(192),
174
+ A256KW: aeskw(256),
175
+ A128GCMKW: aeskw(128, true),
176
+ A192GCMKW: aeskw(192, true),
177
+ A256GCMKW: aeskw(256, true),
178
+ "PBES2-HS256+A128KW": pbes2(),
179
+ "PBES2-HS384+A192KW": pbes2(),
180
+ "PBES2-HS512+A256KW": pbes2()
181
+ });
182
+ var contentOps = ["encrypt", "decrypt"];
183
+ function contentEncryption(bits, cbc = false) {
184
+ return {
185
+ kty: ["oct"],
186
+ secret: true,
187
+ subtle: { name: cbc ? "AES-CBC" : "AES-GCM", length: bits },
188
+ usages: none,
189
+ ops: contentOps,
190
+ cekBits: bits,
191
+ ivBits: cbc ? 128 : 96,
192
+ cbc
193
+ };
194
+ }
195
+ table({
196
+ A128GCM: contentEncryption(128),
197
+ A192GCM: contentEncryption(192),
198
+ A256GCM: contentEncryption(256),
199
+ "A128CBC-HS256": contentEncryption(256, true),
200
+ "A192CBC-HS384": contentEncryption(384, true),
201
+ "A256CBC-HS512": contentEncryption(512, true)
202
+ });
203
+
204
+ // node_modules/jose/dist/webapi/lib/jws_algorithms.js
205
+ var sig = [["verify"], ["sign"]];
206
+ function hmac(bits) {
207
+ const subtle = { name: "HMAC", hash: `SHA-${bits}` };
208
+ return { kty: ["oct"], secret: true, subtle, signing: subtle, usages: sig };
209
+ }
210
+ function rsa(bits, saltLength) {
211
+ const subtle = { name: saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5", hash: `SHA-${bits}` };
212
+ return {
213
+ kty: ["RSA"],
214
+ subtle,
215
+ signing: saltLength ? { ...subtle, saltLength } : subtle,
216
+ usages: sig,
217
+ minRsaBits: 2048
218
+ };
219
+ }
220
+ function ecdsa(crv, bits) {
221
+ return {
222
+ kty: ["EC"],
223
+ crv,
224
+ subtle: { name: "ECDSA", namedCurve: crv },
225
+ signing: { name: "ECDSA", hash: `SHA-${bits}` },
226
+ usages: sig
227
+ };
228
+ }
229
+ function eddsa() {
230
+ const subtle = { name: "Ed25519" };
231
+ return {
232
+ kty: ["OKP"],
233
+ crv: "Ed25519",
234
+ subtle,
235
+ signing: subtle,
236
+ usages: sig
237
+ };
238
+ }
239
+ function mldsa(parameterSet) {
240
+ const subtle = { name: `ML-DSA-${parameterSet}` };
241
+ return {
242
+ kty: ["AKP"],
243
+ subtle,
244
+ signing: subtle,
245
+ usages: sig
246
+ };
247
+ }
248
+ var JWS = table({
249
+ HS256: hmac(256),
250
+ HS384: hmac(384),
251
+ HS512: hmac(512),
252
+ RS256: rsa(256),
253
+ RS384: rsa(384),
254
+ RS512: rsa(512),
255
+ PS256: rsa(256, 32),
256
+ PS384: rsa(384, 48),
257
+ PS512: rsa(512, 64),
258
+ ES256: ecdsa("P-256", 256),
259
+ ES384: ecdsa("P-384", 384),
260
+ ES512: ecdsa("P-521", 512),
261
+ EdDSA: eddsa(),
262
+ Ed25519: eddsa(),
263
+ "ML-DSA-44": mldsa(44),
264
+ "ML-DSA-65": mldsa(65),
265
+ "ML-DSA-87": mldsa(87)
266
+ });
267
+
268
+ // node_modules/jose/dist/webapi/lib/key_algorithm.js
269
+ function unsupportedAlg(source = 'JWK "alg" (Algorithm) Parameter') {
270
+ throw new JOSENotSupported(`Invalid or unsupported ${source} value`);
271
+ }
272
+ function keyAlgorithm(alg, source) {
273
+ return (typeof alg == "string" ? JWS[alg] ?? JWE[alg] : void 0) ?? unsupportedAlg(source);
194
274
  }
195
275
 
196
276
  // node_modules/jose/dist/webapi/key/import.js
197
277
  async function importJWK(jwk, alg, options) {
198
- if (!isObject(jwk)) {
278
+ if (!isObject(jwk))
199
279
  throw new TypeError("JWK must be an object");
200
- }
201
- let ext;
202
- ext ?? (ext = jwk.ext);
203
- switch (jwk.kty) {
280
+ const normalized = normalizeJwk(jwk), { alg: jwkAlg } = normalized;
281
+ if (normalized.kty !== "oct" && !alg)
282
+ ;
283
+ switch (normalized.kty) {
204
284
  case "oct":
205
- if (typeof jwk.k !== "string" || !jwk.k) {
285
+ if (typeof normalized.k != "string")
206
286
  throw new TypeError('missing "k" (Key Value) Parameter value');
207
- }
208
- return decode(jwk.k);
209
- case "RSA":
210
- if ("oth" in jwk && jwk.oth !== void 0) {
211
- throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
212
- }
213
- return jwkToKey({ ...jwk, alg, ext });
287
+ return decode(normalized.k);
214
288
  case "AKP": {
215
- if (typeof jwk.alg !== "string" || !jwk.alg) {
289
+ if (typeof jwkAlg != "string" || !jwkAlg)
216
290
  throw new TypeError('missing "alg" (Algorithm) Parameter value');
217
- }
218
- if (alg !== jwk.alg) {
291
+ if (alg !== jwkAlg)
219
292
  throw new TypeError("JWK alg and alg option value mismatch");
220
- }
221
- return jwkToKey({ ...jwk, ext });
293
+ return jwkToKey(keyAlgorithm(alg), normalized);
222
294
  }
295
+ case "RSA":
223
296
  case "EC":
224
297
  case "OKP":
225
- return jwkToKey({ ...jwk, alg, ext });
298
+ return jwkToKey(keyAlgorithm(alg), normalized);
226
299
  default:
227
300
  throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
228
301
  }
@@ -231,10 +304,13 @@ async function importJWK(jwk, alg, options) {
231
304
  // src/identity.ts
232
305
  var DEFAULT_ISSUER = "https://me.ochk.io";
233
306
  var DEFAULT_TTL_MS = 60 * 60 * 1e3;
307
+ var DEFAULT_MAX_STALE_MS = 6 * 60 * 60 * 1e3;
308
+ var FORCED_REFRESH_MIN_INTERVAL_MS = 6e4;
234
309
  var ENVELOPE_JWKS_PATH = "/.well-known/oc-envelope-jwks.json";
235
310
  var jwksCache = /* @__PURE__ */ new Map();
236
311
  var inflight = /* @__PURE__ */ new Map();
237
- async function fetchEnvelopeJwks(issuer, ttlMs) {
312
+ var lastForcedRefresh = /* @__PURE__ */ new Map();
313
+ async function fetchEnvelopeJwks(issuer, ttlMs, maxStaleMs = DEFAULT_MAX_STALE_MS) {
238
314
  const cached = jwksCache.get(issuer);
239
315
  if (cached && Date.now() - cached.fetchedAt < ttlMs) return cached;
240
316
  const existing = inflight.get(issuer);
@@ -261,7 +337,7 @@ async function fetchEnvelopeJwks(issuer, ttlMs) {
261
337
  return entry;
262
338
  } catch (err) {
263
339
  const stale = jwksCache.get(issuer);
264
- if (stale) return stale;
340
+ if (stale && Date.now() - stale.fetchedAt < maxStaleMs) return stale;
265
341
  throw err;
266
342
  }
267
343
  })().finally(() => {
@@ -310,14 +386,14 @@ function toArrayBuffer(view) {
310
386
  new Uint8Array(buf).set(view);
311
387
  return buf;
312
388
  }
313
- async function verifyEd25519(key, sig, msg) {
389
+ async function verifyEd25519(key, sig2, msg) {
314
390
  const subtle = typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle ? globalThis.crypto.subtle : null;
315
391
  if (!subtle) return false;
316
392
  try {
317
393
  return await subtle.verify(
318
394
  "Ed25519",
319
395
  key,
320
- toArrayBuffer(sig),
396
+ toArrayBuffer(sig2),
321
397
  toArrayBuffer(msg)
322
398
  );
323
399
  } catch {
@@ -427,12 +503,13 @@ async function verifyActivityAttestation(bundle, options = {}) {
427
503
  } else {
428
504
  const issuer = options.issuer ?? DEFAULT_ISSUER;
429
505
  const ttl = options.jwksCacheTtlMs ?? DEFAULT_TTL_MS;
506
+ const maxStale = options.jwksMaxStaleMs ?? DEFAULT_MAX_STALE_MS;
430
507
  try {
431
- let entry = await fetchEnvelopeJwks(issuer, ttl);
508
+ let entry = await fetchEnvelopeJwks(issuer, ttl, maxStale);
432
509
  key = entry.keys[bundle.kid] ?? null;
433
- if (!key) {
434
- jwksCache.delete(issuer);
435
- entry = await fetchEnvelopeJwks(issuer, ttl);
510
+ if (!key && Date.now() - (lastForcedRefresh.get(issuer) ?? 0) >= FORCED_REFRESH_MIN_INTERVAL_MS) {
511
+ lastForcedRefresh.set(issuer, Date.now());
512
+ entry = await fetchEnvelopeJwks(issuer, 0, maxStale);
436
513
  key = entry.keys[bundle.kid] ?? null;
437
514
  }
438
515
  checks.push({