decane-connect-kit 2.2.1 → 2.2.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/dist/index.js CHANGED
@@ -1916,7 +1916,11 @@ var EventEmitter = class {
1916
1916
  init_errors();
1917
1917
  var ERROR_MAP = {
1918
1918
  INVALID_API_KEY: InvalidApiKeyError,
1919
- ORIGIN_NOT_ALLOWED: OriginNotAllowedError
1919
+ ORIGIN_NOT_ALLOWED: OriginNotAllowedError,
1920
+ // The backend's authMiddleware code for an expired/revoked JWT. Surfacing it
1921
+ // as ReconnectRequiredError routes callers to the sign-in UI instead of a
1922
+ // generic failure message.
1923
+ UNAUTHORIZED: ReconnectRequiredError
1920
1924
  };
1921
1925
  var ApiClient = class {
1922
1926
  constructor(baseUrl, apiKey, appId) {
@@ -2202,11 +2206,22 @@ var TeeClient = class {
2202
2206
  this.attested = false;
2203
2207
  /** Mirrors what the signer confirmed for this session, not what we asked for. */
2204
2208
  this.assertionPerSignature = false;
2209
+ /** The signer's authoritative remaining lifetime (seconds), null until a session opens. */
2210
+ this.sessionExpiresInSec = null;
2205
2211
  }
2206
2212
  /** Whether this session actually got per-signature assertions. */
2207
2213
  requiresAssertionPerSignature() {
2208
2214
  return this.assertionPerSignature;
2209
2215
  }
2216
+ /**
2217
+ * The lifetime the signer granted this session, in seconds — which can be
2218
+ * shorter than the client's configured duration when the JWT expires first.
2219
+ * Null if the signer didn't report one (older build). Callers clamp their own
2220
+ * countdown to this so it never promises time the handle doesn't have.
2221
+ */
2222
+ sessionExpiresIn() {
2223
+ return this.sessionExpiresInSec;
2224
+ }
2210
2225
  async ensureAttested() {
2211
2226
  if (this.attested) return;
2212
2227
  const nonce = crypto.getRandomValues(new Uint8Array(16));
@@ -2235,6 +2250,7 @@ var TeeClient = class {
2235
2250
  const body = await res.json();
2236
2251
  this.handle = body.handle;
2237
2252
  this.assertionPerSignature = body.requireAssertionPerSignature === true;
2253
+ this.sessionExpiresInSec = typeof body.expiresIn === "number" ? body.expiresIn : null;
2238
2254
  return body.addresses ?? null;
2239
2255
  }
2240
2256
  /**
@@ -2277,6 +2293,7 @@ var TeeClient = class {
2277
2293
  headers: { Authorization: `Bearer ${jwt}`, "Content-Type": "application/json" },
2278
2294
  body: JSON.stringify({ rpId: window.location.hostname })
2279
2295
  });
2296
+ if (res.status === 401) throw new ReconnectRequiredError();
2280
2297
  if (!res.ok) throw new ExportNotAuthorizedError();
2281
2298
  const { challengeId, options } = await res.json();
2282
2299
  let assertion;
@@ -2328,8 +2345,9 @@ var TeeClient = class {
2328
2345
  /**
2329
2346
  * `jwt` is only needed when this session requires per-signature assertions —
2330
2347
  * it authenticates the challenge request. Passed per call rather than cached
2331
- * on the instance deliberately: the backend's JWTs are shorter-lived than the
2332
- * TEE session TTL, so a stored copy would go stale mid-session.
2348
+ * on the instance deliberately: JWT lifetime is configured independently of
2349
+ * the TEE session TTL (they are aligned at 30min by default, but an operator
2350
+ * can shorten JWT_EXPIRY_SECONDS), so a stored copy could go stale mid-session.
2333
2351
  */
2334
2352
  async sign(req, jwt) {
2335
2353
  if (!this.handle) throw new Error("no session");
@@ -2419,12 +2437,14 @@ var SessionManager = class {
2419
2437
  }
2420
2438
  this.evmAddress = addresses.evm;
2421
2439
  this.solanaAddress = addresses.solana;
2422
- this.expiresAt = Date.now() + this.durationMs;
2440
+ const serverTtlMs = this.tee.sessionExpiresIn();
2441
+ const effectiveMs = serverTtlMs != null ? Math.min(this.durationMs, serverTtlMs * 1e3) : this.durationMs;
2442
+ this.expiresAt = Date.now() + effectiveMs;
2423
2443
  if (this.timeoutId) clearTimeout(this.timeoutId);
2424
2444
  this.timeoutId = setTimeout(() => {
2425
2445
  this.end();
2426
2446
  this.events.emit("session-expired");
2427
- }, this.durationMs);
2447
+ }, effectiveMs);
2428
2448
  this.events.emit("session-started");
2429
2449
  return addresses;
2430
2450
  }