@agentunion/fastaun-browser 0.2.17 → 0.2.18

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.
Files changed (56) hide show
  1. package/dist/auth.d.ts +3 -0
  2. package/dist/auth.d.ts.map +1 -1
  3. package/dist/auth.js +293 -211
  4. package/dist/auth.js.map +1 -1
  5. package/dist/client.d.ts +11 -0
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +1080 -812
  8. package/dist/client.js.map +1 -1
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +3 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/discovery.d.ts +3 -0
  13. package/dist/discovery.d.ts.map +1 -1
  14. package/dist/discovery.js +15 -1
  15. package/dist/discovery.js.map +1 -1
  16. package/dist/e2ee-group.d.ts +4 -0
  17. package/dist/e2ee-group.d.ts.map +1 -1
  18. package/dist/e2ee-group.js +327 -201
  19. package/dist/e2ee-group.js.map +1 -1
  20. package/dist/e2ee.d.ts +4 -0
  21. package/dist/e2ee.d.ts.map +1 -1
  22. package/dist/e2ee.js +176 -117
  23. package/dist/e2ee.js.map +1 -1
  24. package/dist/events.d.ts +3 -0
  25. package/dist/events.d.ts.map +1 -1
  26. package/dist/events.js +4 -1
  27. package/dist/events.js.map +1 -1
  28. package/dist/keystore/indexeddb.d.ts +3 -0
  29. package/dist/keystore/indexeddb.d.ts.map +1 -1
  30. package/dist/keystore/indexeddb.js +153 -97
  31. package/dist/keystore/indexeddb.js.map +1 -1
  32. package/dist/logger.d.ts +37 -0
  33. package/dist/logger.d.ts.map +1 -0
  34. package/dist/logger.js +112 -0
  35. package/dist/logger.js.map +1 -0
  36. package/dist/namespaces/auth.d.ts +4 -0
  37. package/dist/namespaces/auth.d.ts.map +1 -1
  38. package/dist/namespaces/auth.js +214 -101
  39. package/dist/namespaces/auth.js.map +1 -1
  40. package/dist/namespaces/custody.d.ts +3 -0
  41. package/dist/namespaces/custody.d.ts.map +1 -1
  42. package/dist/namespaces/custody.js +147 -75
  43. package/dist/namespaces/custody.js.map +1 -1
  44. package/dist/namespaces/meta.d.ts +3 -0
  45. package/dist/namespaces/meta.d.ts.map +1 -1
  46. package/dist/namespaces/meta.js +94 -43
  47. package/dist/namespaces/meta.js.map +1 -1
  48. package/dist/secret-store/indexeddb-store.d.ts +3 -0
  49. package/dist/secret-store/indexeddb-store.d.ts.map +1 -1
  50. package/dist/secret-store/indexeddb-store.js +57 -29
  51. package/dist/secret-store/indexeddb-store.js.map +1 -1
  52. package/dist/transport.d.ts +3 -0
  53. package/dist/transport.d.ts.map +1 -1
  54. package/dist/transport.js +74 -4
  55. package/dist/transport.js.map +1 -1
  56. package/package.json +1 -1
package/dist/auth.js CHANGED
@@ -4,6 +4,7 @@
4
4
  import { base64ToUint8, uint8ToBase64, pemToArrayBuffer, toBufferSource } from './crypto.js';
5
5
  import { AuthError, StateError, ValidationError, mapRemoteError } from './errors.js';
6
6
  import { ROOT_CA_PEM } from './certs/root.js';
7
+ const _noopLog = { error: () => { }, warn: () => { }, info: () => { }, debug: () => { } };
7
8
  import { isJsonObject, } from './types.js';
8
9
  // ── ASN.1 / PEM 工具 ────────────────────────────────────
9
10
  /** 拆分 PEM bundle 为独立的 PEM 字符串数组 */
@@ -334,6 +335,8 @@ function gatewayHttpUrl(gatewayUrl, path) {
334
335
  * - 证书自动续期
335
336
  */
336
337
  export class AuthFlow {
338
+ _log = _noopLog;
339
+ setLogger(log) { this._log = log; }
337
340
  static _INSTANCE_STATE_FIELDS = [
338
341
  'access_token',
339
342
  'refresh_token',
@@ -368,14 +371,23 @@ export class AuthFlow {
368
371
  // ── 公开 API ──────────────────────────────────────
369
372
  /** 加载本地身份信息 */
370
373
  async loadIdentity(aid) {
371
- const identity = await this._loadIdentityOrRaise(aid);
372
- const cert = await this._keystore.loadCert(identity.aid);
373
- if (cert)
374
- identity.cert = cert;
375
- const instanceState = await this._loadInstanceState(identity.aid);
376
- if (instanceState)
377
- Object.assign(identity, instanceState);
378
- return identity;
374
+ const tStart = Date.now();
375
+ this._log.debug(`loadIdentity enter: aid=${aid ?? '<current>'}`);
376
+ try {
377
+ const identity = await this._loadIdentityOrRaise(aid);
378
+ const cert = await this._keystore.loadCert(identity.aid);
379
+ if (cert)
380
+ identity.cert = cert;
381
+ const instanceState = await this._loadInstanceState(identity.aid);
382
+ if (instanceState)
383
+ Object.assign(identity, instanceState);
384
+ this._log.debug(`loadIdentity exit: elapsed=${Date.now() - tStart}ms aid=${identity.aid} has_cert=${!!identity.cert}`);
385
+ return identity;
386
+ }
387
+ catch (err) {
388
+ this._log.debug(`loadIdentity exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
389
+ throw err;
390
+ }
379
391
  }
380
392
  /** 加载身份,不存在时返回 null */
381
393
  async loadIdentityOrNull(aid) {
@@ -410,265 +422,335 @@ export class AuthFlow {
410
422
  * 3. 保存返回的证书
411
423
  */
412
424
  async createAid(gatewayUrl, aid) {
425
+ const tStart = Date.now();
426
+ this._log.debug(`createAid enter: aid=${aid} gateway=${gatewayUrl}`);
413
427
  AuthFlow._validateAidName(aid);
414
- const identity = await this._ensureLocalIdentity(aid);
415
- if (identity.cert) {
416
- return { aid: identity.aid, cert: identity.cert };
417
- }
418
- // 本地有密钥但无证书 — 尝试注册
419
428
  try {
420
- const created = await this._createAid(gatewayUrl, identity);
421
- Object.assign(identity, created);
422
- }
423
- catch (e) {
424
- if (e instanceof Error && e.message.includes('already exists')) {
425
- // AID 已在服务端注册,尝试下载证书恢复
426
- try {
427
- const recovered = await this._recoverCertViaDownload(gatewayUrl, identity);
428
- Object.assign(identity, recovered);
429
+ const identity = await this._ensureLocalIdentity(aid);
430
+ if (identity.cert) {
431
+ this._log.debug(`createAid exit: elapsed=${Date.now() - tStart}ms aid=${aid} reason=already_has_cert`);
432
+ return { aid: identity.aid, cert: identity.cert };
433
+ }
434
+ // 本地有密钥但无证书 — 尝试注册
435
+ try {
436
+ const created = await this._createAid(gatewayUrl, identity);
437
+ Object.assign(identity, created);
438
+ }
439
+ catch (e) {
440
+ if (e instanceof Error && e.message.includes('already exists')) {
441
+ // AID 已在服务端注册,尝试下载证书恢复
442
+ try {
443
+ const recovered = await this._recoverCertViaDownload(gatewayUrl, identity);
444
+ Object.assign(identity, recovered);
445
+ }
446
+ catch {
447
+ this._log.debug(`createAid exit (error): elapsed=${Date.now() - tStart}ms aid=${aid} err=already_registered_recover_failed`);
448
+ throw new StateError(`AID ${aid} already registered on server but local certificate is missing. ` +
449
+ `Certificate download recovery failed. Options: ` +
450
+ `(1) use a different AID name, or ` +
451
+ `(2) restart server to clear registration.`);
452
+ }
429
453
  }
430
- catch {
431
- throw new StateError(`AID ${aid} already registered on server but local certificate is missing. ` +
432
- `Certificate download recovery failed. Options: ` +
433
- `(1) use a different AID name, or ` +
434
- `(2) restart server to clear registration.`);
454
+ else {
455
+ throw e;
435
456
  }
436
457
  }
437
- else {
438
- throw e;
439
- }
458
+ await this._persistIdentity(identity);
459
+ this._aid = identity.aid;
460
+ this._log.debug(`createAid exit: elapsed=${Date.now() - tStart}ms aid=${aid}`);
461
+ return { aid: identity.aid, cert: identity.cert };
462
+ }
463
+ catch (err) {
464
+ this._log.debug(`createAid exit (error): elapsed=${Date.now() - tStart}ms aid=${aid} err=${err instanceof Error ? err.message : String(err)}`);
465
+ throw err;
440
466
  }
441
- await this._persistIdentity(identity);
442
- this._aid = identity.aid;
443
- return { aid: identity.aid, cert: identity.cert };
444
467
  }
445
468
  /**
446
469
  * 认证已有 AID — login1/login2 双阶段流程。
447
470
  */
448
471
  async authenticate(gatewayUrl, aid) {
449
- const identity = await this._loadIdentityOrRaise(aid);
450
- if (!identity.cert) {
451
- // 尝试下载恢复证书
472
+ const tStart = Date.now();
473
+ this._log.debug(`authenticate enter: aid=${aid ?? '<current>'} gateway=${gatewayUrl}`);
474
+ try {
475
+ const identity = await this._loadIdentityOrRaise(aid);
476
+ if (!identity.cert) {
477
+ // 尝试下载恢复证书
478
+ try {
479
+ const recovered = await this._recoverCertViaDownload(gatewayUrl, identity);
480
+ Object.assign(identity, recovered);
481
+ await this._persistIdentity(identity);
482
+ }
483
+ catch (e) {
484
+ throw new StateError(`local certificate missing and recovery failed: ${e}. ` +
485
+ `Run auth.createAid() to register a new identity.`);
486
+ }
487
+ }
488
+ let login;
452
489
  try {
453
- const recovered = await this._recoverCertViaDownload(gatewayUrl, identity);
454
- Object.assign(identity, recovered);
455
- await this._persistIdentity(identity);
490
+ login = await this._login(gatewayUrl, identity);
456
491
  }
457
492
  catch (e) {
458
- throw new StateError(`local certificate missing and recovery failed: ${e}. ` +
459
- `Run auth.createAid() to register a new identity.`);
493
+ // 证书未在服务端注册或公钥不匹配 自动重新注册
494
+ if (e instanceof AuthError && (String(e.message).includes('not registered') || String(e.message).includes('public key mismatch'))) {
495
+ this._log.warn(`[auth] cert not registered on server, auto re-register: aid=${identity.aid}`);
496
+ const created = await this._createAid(gatewayUrl, identity);
497
+ identity.cert = created.cert;
498
+ await this._persistIdentity(identity);
499
+ login = await this._login(gatewayUrl, identity);
500
+ }
501
+ else {
502
+ throw e;
503
+ }
460
504
  }
505
+ this._rememberTokens(identity, login);
506
+ await this._validateNewCert(identity, gatewayUrl);
507
+ await this._persistIdentity(identity);
508
+ this._aid = identity.aid;
509
+ this._log.debug(`authenticate exit: elapsed=${Date.now() - tStart}ms aid=${identity.aid}`);
510
+ return {
511
+ aid: identity.aid,
512
+ access_token: identity.access_token,
513
+ refresh_token: identity.refresh_token,
514
+ expires_at: identity.access_token_expires_at,
515
+ gateway: gatewayUrl,
516
+ };
461
517
  }
462
- let login;
463
- try {
464
- login = await this._login(gatewayUrl, identity);
465
- }
466
- catch (e) {
467
- // 证书未在服务端注册或公钥不匹配 — 自动重新注册
468
- if (e instanceof AuthError && (String(e.message).includes('not registered') || String(e.message).includes('public key mismatch'))) {
469
- console.warn(`[auth] 证书未在服务端注册,自动重新注册: aid=${identity.aid}`);
470
- const created = await this._createAid(gatewayUrl, identity);
471
- identity.cert = created.cert;
472
- await this._persistIdentity(identity);
473
- login = await this._login(gatewayUrl, identity);
474
- }
475
- else {
476
- throw e;
477
- }
518
+ catch (err) {
519
+ this._log.debug(`authenticate exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
520
+ throw err;
478
521
  }
479
- this._rememberTokens(identity, login);
480
- await this._validateNewCert(identity, gatewayUrl);
481
- await this._persistIdentity(identity);
482
- this._aid = identity.aid;
483
- return {
484
- aid: identity.aid,
485
- access_token: identity.access_token,
486
- refresh_token: identity.refresh_token,
487
- expires_at: identity.access_token_expires_at,
488
- gateway: gatewayUrl,
489
- };
490
522
  }
491
523
  /**
492
524
  * 确保已认证(如无身份则先注册再登录)。
493
525
  */
494
526
  async ensureAuthenticated(gatewayUrl) {
495
- const identity = await this._ensureIdentity();
496
- if (!identity.cert) {
497
- const created = await this._createAid(gatewayUrl, identity);
498
- Object.assign(identity, created);
527
+ const tStart = Date.now();
528
+ this._log.debug(`ensureAuthenticated enter: gateway=${gatewayUrl}`);
529
+ try {
530
+ const identity = await this._ensureIdentity();
531
+ if (!identity.cert) {
532
+ const created = await this._createAid(gatewayUrl, identity);
533
+ Object.assign(identity, created);
534
+ await this._persistIdentity(identity);
535
+ }
536
+ const login = await this._login(gatewayUrl, identity);
537
+ this._rememberTokens(identity, login);
538
+ await this._validateNewCert(identity, gatewayUrl);
499
539
  await this._persistIdentity(identity);
540
+ const token = (identity.access_token || identity.token || identity.kite_token);
541
+ if (!token)
542
+ throw new AuthError('login2 did not return access token');
543
+ this._log.debug(`ensureAuthenticated exit: elapsed=${Date.now() - tStart}ms aid=${identity.aid}`);
544
+ return { token, identity };
545
+ }
546
+ catch (err) {
547
+ this._log.debug(`ensureAuthenticated exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
548
+ throw err;
500
549
  }
501
- const login = await this._login(gatewayUrl, identity);
502
- this._rememberTokens(identity, login);
503
- await this._validateNewCert(identity, gatewayUrl);
504
- await this._persistIdentity(identity);
505
- const token = (identity.access_token || identity.token || identity.kite_token);
506
- if (!token)
507
- throw new AuthError('login2 did not return access token');
508
- return { token, identity };
509
550
  }
510
551
  /**
511
552
  * 使用已有 token 初始化 WebSocket 会话。
512
553
  */
513
554
  async initializeWithToken(transport, challenge, accessToken, opts) {
514
- const params = isJsonObject(challenge?.params) ? challenge.params : {};
515
- const nonce = String(params.nonce ?? '');
516
- if (!nonce)
517
- throw new AuthError('gateway challenge missing nonce');
518
- this.setInstanceContext({
519
- deviceId: String(opts?.deviceId ?? this._deviceId ?? ''),
520
- slotId: String(opts?.slotId ?? this._slotId ?? ''),
521
- });
522
- await this._initializeSession(transport, nonce, accessToken, {
523
- deviceId: String(opts?.deviceId ?? this._deviceId ?? ''),
524
- slotId: String(opts?.slotId ?? this._slotId ?? ''),
525
- deliveryMode: opts?.deliveryMode ?? null,
526
- });
555
+ const tStart = Date.now();
556
+ this._log.debug(`initializeWithToken enter: device_id=${opts?.deviceId ?? this._deviceId} slot_id=${opts?.slotId ?? this._slotId}`);
557
+ try {
558
+ const params = isJsonObject(challenge?.params) ? challenge.params : {};
559
+ const nonce = String(params.nonce ?? '');
560
+ if (!nonce)
561
+ throw new AuthError('gateway challenge missing nonce');
562
+ this.setInstanceContext({
563
+ deviceId: String(opts?.deviceId ?? this._deviceId ?? ''),
564
+ slotId: String(opts?.slotId ?? this._slotId ?? ''),
565
+ });
566
+ await this._initializeSession(transport, nonce, accessToken, {
567
+ deviceId: String(opts?.deviceId ?? this._deviceId ?? ''),
568
+ slotId: String(opts?.slotId ?? this._slotId ?? ''),
569
+ deliveryMode: opts?.deliveryMode ?? null,
570
+ });
571
+ this._log.debug(`initializeWithToken exit: elapsed=${Date.now() - tStart}ms`);
572
+ }
573
+ catch (err) {
574
+ this._log.debug(`initializeWithToken exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
575
+ throw err;
576
+ }
527
577
  }
528
578
  /**
529
579
  * 连接会话 — 多策略认证:显式 token → 缓存 token → refresh → 重新登录。
530
580
  */
531
581
  async connectSession(transport, challenge, gatewayUrl, accessToken) {
532
- const params = isJsonObject(challenge?.params) ? challenge.params : {};
533
- const nonce = String(params.nonce ?? '');
534
- if (!nonce)
535
- throw new AuthError('gateway challenge missing nonce');
536
- const connectOptions = isJsonObject(accessToken)
537
- ? accessToken
538
- : { accessToken };
539
- const deviceId = String(connectOptions.deviceId ?? this._deviceId ?? '');
540
- const slotId = String(connectOptions.slotId ?? this._slotId ?? '');
541
- const deliveryMode = connectOptions.deliveryMode ?? null;
542
- this.setInstanceContext({ deviceId, slotId });
543
- let identity;
582
+ const tStart = Date.now();
583
+ const explicitTokenInput = isJsonObject(accessToken) ? !!accessToken.accessToken : !!accessToken;
584
+ this._log.debug(`connectSession enter: gateway=${gatewayUrl} has_explicit_token=${explicitTokenInput}`);
544
585
  try {
545
- identity = await this.loadIdentity();
546
- }
547
- catch {
548
- identity = null;
549
- }
550
- // 策略 1: 显式 token
551
- const explicitToken = String(connectOptions.accessToken ?? '');
552
- if (explicitToken && identity !== null) {
586
+ const params = isJsonObject(challenge?.params) ? challenge.params : {};
587
+ const nonce = String(params.nonce ?? '');
588
+ if (!nonce)
589
+ throw new AuthError('gateway challenge missing nonce');
590
+ const connectOptions = isJsonObject(accessToken)
591
+ ? accessToken
592
+ : { accessToken };
593
+ const deviceId = String(connectOptions.deviceId ?? this._deviceId ?? '');
594
+ const slotId = String(connectOptions.slotId ?? this._slotId ?? '');
595
+ const deliveryMode = connectOptions.deliveryMode ?? null;
596
+ this.setInstanceContext({ deviceId, slotId });
597
+ let identity;
553
598
  try {
554
- await this._initializeSession(transport, nonce, explicitToken, {
555
- deviceId,
556
- slotId,
557
- deliveryMode,
558
- });
559
- identity.access_token = explicitToken;
560
- await this._persistIdentity(identity);
561
- return { token: explicitToken, identity };
599
+ identity = await this.loadIdentity();
562
600
  }
563
- catch (e) {
564
- if (!(e instanceof AuthError))
565
- throw e;
566
- // 显式 token 失败,继续尝试其他方式
601
+ catch {
602
+ identity = null;
567
603
  }
568
- }
569
- // 无本地身份 先注册 + 登录
570
- if (identity === null) {
571
- const authContext = await this.ensureAuthenticated(gatewayUrl);
572
- const token = authContext.token;
573
- await this._initializeSession(transport, nonce, token, {
574
- deviceId,
575
- slotId,
576
- deliveryMode,
577
- });
578
- return authContext;
579
- }
580
- // 策略 2: 缓存 token
581
- const cachedToken = this._getCachedAccessToken(identity);
582
- if (cachedToken) {
583
- try {
584
- await this._initializeSession(transport, nonce, cachedToken, {
604
+ // 策略 1: 显式 token
605
+ const explicitToken = String(connectOptions.accessToken ?? '');
606
+ if (explicitToken && identity !== null) {
607
+ try {
608
+ await this._initializeSession(transport, nonce, explicitToken, {
609
+ deviceId,
610
+ slotId,
611
+ deliveryMode,
612
+ });
613
+ identity.access_token = explicitToken;
614
+ await this._persistIdentity(identity);
615
+ this._log.debug(`connectSession exit: elapsed=${Date.now() - tStart}ms strategy=explicit_token aid=${identity.aid}`);
616
+ return { token: explicitToken, identity };
617
+ }
618
+ catch (e) {
619
+ if (!(e instanceof AuthError))
620
+ throw e;
621
+ // 显式 token 失败,继续尝试其他方式
622
+ }
623
+ }
624
+ // 无本地身份 — 先注册 + 登录
625
+ if (identity === null) {
626
+ const authContext = await this.ensureAuthenticated(gatewayUrl);
627
+ const token = authContext.token;
628
+ await this._initializeSession(transport, nonce, token, {
585
629
  deviceId,
586
630
  slotId,
587
631
  deliveryMode,
588
632
  });
589
- return { token: cachedToken, identity };
633
+ this._log.debug(`connectSession exit: elapsed=${Date.now() - tStart}ms strategy=ensure_authenticated`);
634
+ return authContext;
590
635
  }
591
- catch (e) {
592
- if (!(e instanceof AuthError))
593
- throw e;
594
- // 缓存 token 失败,尝试刷新
595
- }
596
- }
597
- // 策略 3: refresh token
598
- const refreshToken = String(identity.refresh_token ?? '');
599
- if (refreshToken) {
600
- try {
601
- identity = await this.refreshCachedTokens(gatewayUrl, identity);
602
- const refreshedToken = this._getCachedAccessToken(identity);
603
- if (refreshedToken) {
604
- await this._initializeSession(transport, nonce, refreshedToken, {
636
+ // 策略 2: 缓存 token
637
+ const cachedToken = this._getCachedAccessToken(identity);
638
+ if (cachedToken) {
639
+ try {
640
+ await this._initializeSession(transport, nonce, cachedToken, {
605
641
  deviceId,
606
642
  slotId,
607
643
  deliveryMode,
608
644
  });
609
- return { token: refreshedToken, identity };
645
+ this._log.debug(`connectSession exit: elapsed=${Date.now() - tStart}ms strategy=cached_token aid=${identity.aid}`);
646
+ return { token: cachedToken, identity };
647
+ }
648
+ catch (e) {
649
+ if (!(e instanceof AuthError))
650
+ throw e;
651
+ // 缓存 token 失败,尝试刷新
610
652
  }
611
653
  }
612
- catch (e) {
613
- if (!(e instanceof AuthError))
614
- throw e;
615
- // refresh 失败,重新登录
654
+ // 策略 3: refresh token
655
+ const refreshToken = String(identity.refresh_token ?? '');
656
+ if (refreshToken) {
657
+ try {
658
+ identity = await this.refreshCachedTokens(gatewayUrl, identity);
659
+ const refreshedToken = this._getCachedAccessToken(identity);
660
+ if (refreshedToken) {
661
+ await this._initializeSession(transport, nonce, refreshedToken, {
662
+ deviceId,
663
+ slotId,
664
+ deliveryMode,
665
+ });
666
+ this._log.debug(`connectSession exit: elapsed=${Date.now() - tStart}ms strategy=refresh aid=${identity.aid}`);
667
+ return { token: refreshedToken, identity };
668
+ }
669
+ }
670
+ catch (e) {
671
+ if (!(e instanceof AuthError))
672
+ throw e;
673
+ // refresh 失败,重新登录
674
+ }
616
675
  }
676
+ // 策略 4: 重新登录
677
+ const login = await this.authenticate(gatewayUrl, identity.aid);
678
+ const token = String(login.access_token ?? '');
679
+ if (!token)
680
+ throw new AuthError('authenticate did not return access_token');
681
+ await this._initializeSession(transport, nonce, token, {
682
+ deviceId,
683
+ slotId,
684
+ deliveryMode,
685
+ });
686
+ identity = await this.loadIdentity(identity.aid);
687
+ this._log.debug(`connectSession exit: elapsed=${Date.now() - tStart}ms strategy=re_login aid=${identity.aid}`);
688
+ return { token, identity };
689
+ }
690
+ catch (err) {
691
+ this._log.debug(`connectSession exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
692
+ throw err;
617
693
  }
618
- // 策略 4: 重新登录
619
- const login = await this.authenticate(gatewayUrl, identity.aid);
620
- const token = String(login.access_token ?? '');
621
- if (!token)
622
- throw new AuthError('authenticate did not return access_token');
623
- await this._initializeSession(transport, nonce, token, {
624
- deviceId,
625
- slotId,
626
- deliveryMode,
627
- });
628
- identity = await this.loadIdentity(identity.aid);
629
- return { token, identity };
630
694
  }
631
695
  /**
632
696
  * 刷新 token。
633
697
  */
634
698
  async refreshCachedTokens(gatewayUrl, identity) {
635
- const refreshToken = String(identity.refresh_token ?? '');
636
- if (!refreshToken)
637
- throw new AuthError('missing refresh_token');
638
- const refreshed = await this._refreshAccessToken(gatewayUrl, refreshToken);
639
- this._rememberTokens(identity, refreshed);
640
- await this._validateNewCert(identity, gatewayUrl);
641
- await this._persistIdentity(identity);
642
- return identity;
699
+ const tStart = Date.now();
700
+ this._log.debug(`refreshCachedTokens enter: aid=${identity.aid} gateway=${gatewayUrl}`);
701
+ try {
702
+ const refreshToken = String(identity.refresh_token ?? '');
703
+ if (!refreshToken)
704
+ throw new AuthError('missing refresh_token');
705
+ const refreshed = await this._refreshAccessToken(gatewayUrl, refreshToken);
706
+ this._rememberTokens(identity, refreshed);
707
+ await this._validateNewCert(identity, gatewayUrl);
708
+ await this._persistIdentity(identity);
709
+ this._log.debug(`refreshCachedTokens exit: elapsed=${Date.now() - tStart}ms aid=${identity.aid}`);
710
+ return identity;
711
+ }
712
+ catch (err) {
713
+ this._log.debug(`refreshCachedTokens exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
714
+ throw err;
715
+ }
643
716
  }
644
717
  /**
645
718
  * 统一的对端证书验证入口:时间有效性 + 链验证 + CRL + OCSP + AID 绑定。
646
719
  */
647
720
  async verifyPeerCertificate(gatewayUrl, certPem, expectedAid) {
648
- const cert = parseCertDer(certPem);
649
- const now = Date.now() / 1000;
650
- ensureCertTimeValid(cert, 'peer certificate', now);
651
- await this._verifyAuthCertChain(gatewayUrl, cert, expectedAid);
652
- try {
653
- await this._verifyAuthCertRevocation(gatewayUrl, cert, expectedAid);
654
- }
655
- catch (e) {
656
- const errMsg = e instanceof Error ? e.message : String(e);
657
- if (/revoked/i.test(errMsg))
658
- throw e instanceof AuthError ? e : new AuthError(errMsg);
659
- console.warn('[aun_core.auth] CRL 检查不可用,降级继续:', errMsg);
660
- }
721
+ const tStart = Date.now();
722
+ this._log.debug(`verifyPeerCertificate enter: aid=${expectedAid} gateway=${gatewayUrl}`);
661
723
  try {
662
- await this._verifyAuthCertOcsp(gatewayUrl, cert, expectedAid);
663
- }
664
- catch (e) {
665
- const errMsg = e instanceof Error ? e.message : String(e);
666
- if (/revoked/i.test(errMsg))
667
- throw e instanceof AuthError ? e : new AuthError(errMsg);
668
- console.warn('[aun_core.auth] OCSP 检查不可用,降级继续:', errMsg);
724
+ const cert = parseCertDer(certPem);
725
+ const now = Date.now() / 1000;
726
+ ensureCertTimeValid(cert, 'peer certificate', now);
727
+ await this._verifyAuthCertChain(gatewayUrl, cert, expectedAid);
728
+ try {
729
+ await this._verifyAuthCertRevocation(gatewayUrl, cert, expectedAid);
730
+ }
731
+ catch (e) {
732
+ const errMsg = e instanceof Error ? e.message : String(e);
733
+ if (/revoked/i.test(errMsg))
734
+ throw e instanceof AuthError ? e : new AuthError(errMsg);
735
+ this._log.warn('[aun_core.auth] CRL check unavailable, degrade and continue:', errMsg);
736
+ }
737
+ try {
738
+ await this._verifyAuthCertOcsp(gatewayUrl, cert, expectedAid);
739
+ }
740
+ catch (e) {
741
+ const errMsg = e instanceof Error ? e.message : String(e);
742
+ if (/revoked/i.test(errMsg))
743
+ throw e instanceof AuthError ? e : new AuthError(errMsg);
744
+ this._log.warn('[aun_core.auth] OCSP check unavailable, degrade and continue:', errMsg);
745
+ }
746
+ if (cert.subjectCN !== expectedAid) {
747
+ throw new AuthError(`peer cert CN mismatch: expected ${expectedAid}, got ${cert.subjectCN || 'none'}`);
748
+ }
749
+ this._log.debug(`verifyPeerCertificate exit: elapsed=${Date.now() - tStart}ms aid=${expectedAid}`);
669
750
  }
670
- if (cert.subjectCN !== expectedAid) {
671
- throw new AuthError(`peer cert CN mismatch: expected ${expectedAid}, got ${cert.subjectCN || 'none'}`);
751
+ catch (err) {
752
+ this._log.debug(`verifyPeerCertificate exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
753
+ throw err;
672
754
  }
673
755
  }
674
756
  // ── 内部方法:短连接 RPC ──────────────────────────
@@ -889,7 +971,7 @@ export class AuthFlow {
889
971
  const errMsg = e instanceof Error ? e.message : String(e);
890
972
  if (/revoked/i.test(errMsg))
891
973
  throw e instanceof AuthError ? e : new AuthError(errMsg);
892
- console.warn('[aun_core.auth] CRL 检查不可用,降级继续:', errMsg);
974
+ this._log.warn('[aun_core.auth] CRL check unavailable, degrade and continue:', errMsg);
893
975
  }
894
976
  // 验证 OCSP
895
977
  try {
@@ -899,7 +981,7 @@ export class AuthFlow {
899
981
  const errMsg = e instanceof Error ? e.message : String(e);
900
982
  if (/revoked/i.test(errMsg))
901
983
  throw e instanceof AuthError ? e : new AuthError(errMsg);
902
- console.warn('[aun_core.auth] OCSP 检查不可用,降级继续:', errMsg);
984
+ this._log.warn('[aun_core.auth] OCSP check unavailable, degrade and continue:', errMsg);
903
985
  }
904
986
  // 验证 client_nonce 签名
905
987
  try {
@@ -1224,7 +1306,7 @@ export class AuthFlow {
1224
1306
  const errMsg = e instanceof Error ? e.message : String(e);
1225
1307
  if (/revoked/i.test(errMsg))
1226
1308
  throw e instanceof AuthError ? e : new AuthError(errMsg);
1227
- console.warn('[aun_core.auth] CRL 检查不可用,降级继续:', errMsg);
1309
+ this._log.warn('[aun_core.auth] CRL check unavailable, degrade and continue:', errMsg);
1228
1310
  }
1229
1311
  try {
1230
1312
  await this._verifyAuthCertOcsp(gatewayUrl, cert);
@@ -1233,7 +1315,7 @@ export class AuthFlow {
1233
1315
  const errMsg = e instanceof Error ? e.message : String(e);
1234
1316
  if (/revoked/i.test(errMsg))
1235
1317
  throw e instanceof AuthError ? e : new AuthError(errMsg);
1236
- console.warn('[aun_core.auth] OCSP 检查不可用,降级继续:', errMsg);
1318
+ this._log.warn('[aun_core.auth] OCSP check unavailable, degrade and continue:', errMsg);
1237
1319
  }
1238
1320
  }
1239
1321
  // 验证通过,正式接受
@@ -1241,7 +1323,7 @@ export class AuthFlow {
1241
1323
  }
1242
1324
  catch (e) {
1243
1325
  // 验证失败,静默拒绝(不影响主流程)
1244
- console.warn(`拒绝服务端返回的 new_cert (${identity.aid}):`, e);
1326
+ this._log.warn(`reject server-returned new_cert (${identity.aid}):`, e);
1245
1327
  }
1246
1328
  // active_cert 同步:验证公钥匹配后更新本地 cert
1247
1329
  const activeCertPem = identity._pending_active_cert;
@@ -1256,12 +1338,12 @@ export class AuthFlow {
1256
1338
  identity.cert = activeCertPem;
1257
1339
  }
1258
1340
  else {
1259
- console.warn(`[auth] 服务端 active_cert 公钥与本地私钥不匹配,拒绝同步 (aid=${identity.aid})`);
1341
+ this._log.warn(`[auth] active_cert public key mismatches local private key, reject sync (aid=${identity.aid})`);
1260
1342
  }
1261
1343
  }
1262
1344
  }
1263
1345
  catch (e) {
1264
- console.warn(`[auth] active_cert 同步异常 (${identity.aid}):`, e);
1346
+ this._log.warn(`[auth] active_cert sync exception (${identity.aid}):`, e);
1265
1347
  }
1266
1348
  }
1267
1349
  }