@agentunion/fastaun-browser 0.4.4 → 0.4.5

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 (45) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/_packed_docs/CHANGELOG.md +13 -0
  3. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
  4. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
  5. package/dist/aid-store.d.ts +1 -0
  6. package/dist/aid-store.d.ts.map +1 -1
  7. package/dist/aid-store.js +26 -9
  8. package/dist/aid-store.js.map +1 -1
  9. package/dist/auth.d.ts +8 -13
  10. package/dist/auth.d.ts.map +1 -1
  11. package/dist/auth.js +37 -130
  12. package/dist/auth.js.map +1 -1
  13. package/dist/bundle.js +644 -210
  14. package/dist/client.d.ts +5 -4
  15. package/dist/client.d.ts.map +1 -1
  16. package/dist/client.js +64 -66
  17. package/dist/client.js.map +1 -1
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/keystore/index.d.ts +45 -22
  23. package/dist/keystore/index.d.ts.map +1 -1
  24. package/dist/keystore/index.js +6 -1
  25. package/dist/keystore/index.js.map +1 -1
  26. package/dist/keystore/indexeddb.d.ts +11 -1
  27. package/dist/keystore/indexeddb.d.ts.map +1 -1
  28. package/dist/keystore/indexeddb.js +167 -18
  29. package/dist/keystore/indexeddb.js.map +1 -1
  30. package/dist/register-flow.d.ts +34 -0
  31. package/dist/register-flow.d.ts.map +1 -0
  32. package/dist/register-flow.js +355 -0
  33. package/dist/register-flow.js.map +1 -0
  34. package/dist/v2/session/keystore.d.ts +5 -0
  35. package/dist/v2/session/keystore.d.ts.map +1 -1
  36. package/dist/v2/session/keystore.js +29 -0
  37. package/dist/v2/session/keystore.js.map +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +1 -1
  41. package/_packed_docs/0.4.0_/345/267/256/345/274/202/346/240/270/345/256/236/345/206/263/347/255/226/350/256/260/345/275/225.md +0 -302
  42. package/_packed_docs/AUN_SDK_0.4.0_/350/256/276/350/256/241/345/257/271/346/257/224/345/210/206/346/236/220.md +0 -194
  43. package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/345/256/236/346/226/275/350/256/241/345/210/222.md +0 -596
  44. package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/350/256/276/350/256/241/346/226/271/346/241/210_v3.md +0 -1698
  45. package/_packed_docs/python-sdk-v2-only-changelog.md +0 -189
package/dist/bundle.js CHANGED
@@ -314,12 +314,12 @@ async function secretPut(storeName, key, value) {
314
314
  tx.oncomplete = () => db.close();
315
315
  });
316
316
  }
317
- var _noopLog6, SECRET_DB_NAME, SECRET_DB_VERSION, STORE_SECRETS, STORE_MASTER, IndexedDBSecretStore;
317
+ var _noopLog7, SECRET_DB_NAME, SECRET_DB_VERSION, STORE_SECRETS, STORE_MASTER, IndexedDBSecretStore;
318
318
  var init_indexeddb_store = __esm({
319
319
  "src/secret-store/indexeddb-store.ts"() {
320
320
  "use strict";
321
321
  init_crypto();
322
- _noopLog6 = { error: () => {
322
+ _noopLog7 = { error: () => {
323
323
  }, warn: () => {
324
324
  }, info: () => {
325
325
  }, debug: () => {
@@ -332,7 +332,7 @@ var init_indexeddb_store = __esm({
332
332
  constructor(encryptionSeed) {
333
333
  __publicField(this, "_encryptionSeed");
334
334
  __publicField(this, "_masterKeyPromise", null);
335
- __publicField(this, "_log", _noopLog6);
335
+ __publicField(this, "_log", _noopLog7);
336
336
  this._encryptionSeed = encryptionSeed;
337
337
  }
338
338
  setLogger(log) {
@@ -454,7 +454,7 @@ var init_indexeddb_store = __esm({
454
454
  });
455
455
 
456
456
  // src/version.ts
457
- var VERSION = "0.4.4";
457
+ var VERSION = "0.4.5";
458
458
 
459
459
  // src/types.ts
460
460
  var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
@@ -2031,13 +2031,14 @@ function gatewayHttpUrl(gatewayUrl, path) {
2031
2031
  var _AuthFlow = class _AuthFlow {
2032
2032
  constructor(opts) {
2033
2033
  __publicField(this, "_log", _noopLog4);
2034
- __publicField(this, "_keystore");
2034
+ __publicField(this, "_tokenStore");
2035
2035
  __publicField(this, "_crypto");
2036
2036
  __publicField(this, "_aid");
2037
2037
  __publicField(this, "_deviceId");
2038
2038
  __publicField(this, "_slotId");
2039
2039
  __publicField(this, "_rootCaPem");
2040
2040
  __publicField(this, "_verifySsl");
2041
+ __publicField(this, "_memIdentity", null);
2041
2042
  // 缓存
2042
2043
  __publicField(this, "_rootCerts", null);
2043
2044
  __publicField(this, "_gatewayChainCache", /* @__PURE__ */ new Map());
@@ -2046,7 +2047,7 @@ var _AuthFlow = class _AuthFlow {
2046
2047
  __publicField(this, "_chainVerifiedCache", /* @__PURE__ */ new Map());
2047
2048
  __publicField(this, "_chainCacheTtl");
2048
2049
  __publicField(this, "_gatewayCaVerified", /* @__PURE__ */ new Map());
2049
- this._keystore = opts.keystore;
2050
+ this._tokenStore = opts.tokenStore;
2050
2051
  this._crypto = opts.crypto;
2051
2052
  this._aid = opts.aid ?? null;
2052
2053
  this._deviceId = String(opts.deviceId ?? "").trim();
@@ -2059,13 +2060,18 @@ var _AuthFlow = class _AuthFlow {
2059
2060
  this._log = log;
2060
2061
  }
2061
2062
  // ── 公开 API ──────────────────────────────────────
2063
+ /** 注入内存私钥,禁止 AuthFlow 内部再走 tokenStore 解密 */
2064
+ setIdentity(identity) {
2065
+ this._memIdentity = identity;
2066
+ if (identity?.aid) this._aid = String(identity.aid);
2067
+ }
2062
2068
  /** 加载本地身份信息 */
2063
2069
  async loadIdentity(aid) {
2064
2070
  const tStart = Date.now();
2065
2071
  this._log.debug(`loadIdentity enter: aid=${aid ?? "<current>"}`);
2066
2072
  try {
2067
2073
  const identity = await this._loadIdentityOrRaise(aid);
2068
- const cert = await this._keystore.loadCert(identity.aid);
2074
+ const cert = await this._tokenStore.loadCert(identity.aid);
2069
2075
  if (cert) identity.cert = cert;
2070
2076
  const instanceState = await this._loadInstanceState(identity.aid);
2071
2077
  if (instanceState) {
@@ -2104,93 +2110,10 @@ var _AuthFlow = class _AuthFlow {
2104
2110
  this._deviceId = String(opts.deviceId ?? "").trim();
2105
2111
  this._slotId = String(opts.slotId ?? "").trim();
2106
2112
  }
2107
- /**
2108
- * 严格注册新 AID(对齐 TS registerAid / Go RegisterAID)。
2109
- *
2110
- * 注册与认证彻底分离:此方法绝不被 SDK 内部自动调用,
2111
- * 必须由应用层显式调用。
2112
- */
2113
- async registerAid(gatewayUrl, aid) {
2114
- const tStart = Date.now();
2115
- this._log.debug(`registerAid enter: aid=${aid} gateway=${gatewayUrl}`);
2116
- _AuthFlow._validateAidName(aid);
2117
- try {
2118
- const existing = await this._keystore.loadIdentity(aid);
2119
- if (existing && existing.private_key_pem && existing.public_key_der_b64) {
2120
- this._log.debug(`registerAid: local keypair exists, checking server: aid=${aid}`);
2121
- const localPubB642 = String(existing.public_key_der_b64);
2122
- const serverCertPem2 = await this._downloadRegisteredCert(gatewayUrl, aid);
2123
- if (serverCertPem2) {
2124
- const serverCert = parseCertDer(serverCertPem2);
2125
- const serverPubB64 = uint8ToBase64(serverCert.spkiBytes);
2126
- if (serverPubB64 !== localPubB642) {
2127
- throw new IdentityConflictError(
2128
- `AID '${aid}' is registered by another party on server (public key mismatch). Choose a different name.`
2129
- );
2130
- }
2131
- this._log.info(`registerAid: idempotent return for already-registered AID: aid=${aid}`);
2132
- if (!existing.cert) {
2133
- existing.cert = serverCertPem2;
2134
- await this._persistIdentity(existing);
2135
- }
2136
- this._aid = aid;
2137
- return { aid, cert: serverCertPem2 };
2138
- } else {
2139
- this._log.debug(`registerAid: server has no record, registering with existing keypair: aid=${aid}`);
2140
- const created2 = await this._createAid(gatewayUrl, existing);
2141
- const certPem2 = String(created2.cert ?? "");
2142
- if (!certPem2) {
2143
- throw new AuthError(`registerAid: server response missing cert for ${aid}`);
2144
- }
2145
- existing.cert = certPem2;
2146
- const returnedCert2 = parseCertDer(certPem2);
2147
- const certPubB642 = uint8ToBase64(returnedCert2.spkiBytes);
2148
- if (certPubB642 !== localPubB642) {
2149
- throw new AuthError(
2150
- `registerAid: server returned certificate with mismatched public key for ${aid}`
2151
- );
2152
- }
2153
- await this._persistIdentity(existing);
2154
- this._aid = aid;
2155
- this._log.debug(`registerAid exit (recovered): elapsed=${Date.now() - tStart}ms aid=${aid}`);
2156
- return { aid, cert: certPem2 };
2157
- }
2158
- }
2159
- const serverCertPem = await this._downloadRegisteredCert(gatewayUrl, aid);
2160
- if (serverCertPem) {
2161
- throw new IdentityConflictError(
2162
- `AID '${aid}' is already registered on server. Choose a different name, or if you own the keypair use a recovery flow.`
2163
- );
2164
- }
2165
- const identity = await this._crypto.generateIdentity();
2166
- identity.aid = aid;
2167
- const created = await this._createAid(gatewayUrl, identity);
2168
- const certPem = String(created.cert ?? "");
2169
- if (!certPem) {
2170
- throw new AuthError(`registerAid: server response missing cert for ${aid}`);
2171
- }
2172
- identity.cert = certPem;
2173
- const returnedCert = parseCertDer(certPem);
2174
- const certPubB64 = uint8ToBase64(returnedCert.spkiBytes);
2175
- const localPubB64 = String(identity.public_key_der_b64);
2176
- if (certPubB64 !== localPubB64) {
2177
- throw new AuthError(
2178
- `registerAid: server returned certificate with mismatched public key for ${aid}`
2179
- );
2180
- }
2181
- await this._persistIdentity(identity);
2182
- this._aid = aid;
2183
- this._log.debug(`registerAid exit: elapsed=${Date.now() - tStart}ms aid=${aid}`);
2184
- return { aid: identity.aid, cert: identity.cert };
2185
- } catch (err) {
2186
- this._log.debug(`registerAid exit (error): elapsed=${Date.now() - tStart}ms aid=${aid} err=${err instanceof Error ? err.message : String(err)}`);
2187
- throw err;
2188
- }
2189
- }
2190
2113
  /**
2191
2114
  * 认证已有 AID — login1/login2 双阶段流程。
2192
2115
  *
2193
- * 优先复用 keystore 里的 cached access_token(未过期且有 refresh_token),
2116
+ * 优先复用 tokenStore 里的 cached access_token(未过期且有 refresh_token),
2194
2117
  * 避免每次 authenticate 都走两阶段重登的网络往返。与 Python SDK 行为对齐。
2195
2118
  */
2196
2119
  async authenticate(gatewayUrl, aid) {
@@ -2584,15 +2507,6 @@ var _AuthFlow = class _AuthFlow {
2584
2507
  clearTimeout(timeoutId);
2585
2508
  }
2586
2509
  }
2587
- // ── 内部方法:AID 创建 ───────────────────────────
2588
- async _createAid(gatewayUrl, identity) {
2589
- const response = await this._shortRpc(gatewayUrl, "auth.create_aid", {
2590
- aid: identity.aid,
2591
- public_key: identity.public_key_der_b64,
2592
- curve: identity.curve ?? "P-256"
2593
- });
2594
- return { cert: response.cert };
2595
- }
2596
2510
  /**
2597
2511
  * 从服务端下载指定 AID 的证书(公开 API)。
2598
2512
  *
@@ -3104,52 +3018,53 @@ var _AuthFlow = class _AuthFlow {
3104
3018
  /** 加载身份,不存在或半成品时抛出异常 */
3105
3019
  async _loadIdentityOrRaise(aid) {
3106
3020
  const requestedAid = aid ?? this._aid;
3107
- if (requestedAid) {
3108
- const existing = await this._keystore.loadIdentity(requestedAid);
3109
- if (!existing) {
3110
- throw new StateError(`identity not found for aid: ${requestedAid}`);
3021
+ if (this._memIdentity) {
3022
+ const mem = this._memIdentity;
3023
+ if (requestedAid && String(mem.aid ?? "") !== requestedAid) {
3024
+ throw new StateError(`identity mismatch: requested ${requestedAid}, loaded ${mem.aid}`);
3111
3025
  }
3112
- if (!existing.private_key_pem || !existing.public_key_der_b64) {
3113
- throw new StateError(
3114
- `local identity for aid ${requestedAid} is incomplete (missing keypair); call auth.registerAid() first`
3115
- );
3026
+ if (!mem.private_key_pem || !mem.public_key_der_b64) {
3027
+ throw new StateError(`injected identity for aid ${mem.aid} is incomplete (missing keypair)`);
3116
3028
  }
3117
- this._aid = requestedAid;
3118
- if (!existing.aid) existing.aid = requestedAid;
3119
- return existing;
3029
+ if (requestedAid) this._aid = requestedAid;
3030
+ return { ...mem };
3031
+ }
3032
+ if (requestedAid) {
3033
+ throw new StateError(
3034
+ `no injected identity for aid ${requestedAid}; call AUNClient.loadIdentity(aid) first`
3035
+ );
3120
3036
  }
3121
- throw new StateError("no local identity found, call auth.registerAid() first");
3037
+ throw new StateError("no local identity found, call AUNClient.loadIdentity(aid) first");
3122
3038
  }
3123
3039
  // (_ensureIdentity 已移除:注册和登录彻底分离)
3124
3040
  async _loadInstanceState(aid) {
3125
- if (typeof this._keystore.loadInstanceState !== "function") {
3041
+ if (typeof this._tokenStore.loadInstanceState !== "function") {
3126
3042
  return null;
3127
3043
  }
3128
- return await this._keystore.loadInstanceState(aid, this._deviceId, this._slotId);
3044
+ return await this._tokenStore.loadInstanceState(aid, this._deviceId, this._slotId);
3129
3045
  }
3130
3046
  async _persistIdentity(identity) {
3131
3047
  const aid = String(identity.aid ?? "");
3132
3048
  if (!aid) {
3133
3049
  throw new StateError("identity missing aid");
3134
3050
  }
3135
- const persisted = { ...identity };
3136
3051
  const instanceState = {};
3137
3052
  const instanceStateRecord = instanceState;
3138
- const persistedRecord = persisted;
3053
+ const persistedRecord = { ...identity };
3139
3054
  for (const key of _AuthFlow._INSTANCE_STATE_FIELDS) {
3140
- if (key in persisted) {
3055
+ if (key in persistedRecord) {
3141
3056
  instanceStateRecord[key] = persistedRecord[key];
3142
3057
  delete persistedRecord[key];
3143
3058
  }
3144
3059
  }
3145
- for (const key of ["private_key_pem", "public_key_der_b64", "curve"]) {
3146
- delete persistedRecord[key];
3060
+ const certPem = String(persistedRecord.cert ?? "");
3061
+ if (certPem) {
3062
+ await this._tokenStore.saveCert(aid, certPem);
3147
3063
  }
3148
- await this._keystore.saveIdentity(aid, persisted);
3149
- if (Object.keys(instanceState).length === 0 || typeof this._keystore.updateInstanceState !== "function") {
3064
+ if (Object.keys(instanceState).length === 0 || typeof this._tokenStore.updateInstanceState !== "function") {
3150
3065
  return;
3151
3066
  }
3152
- await this._keystore.updateInstanceState(aid, this._deviceId, this._slotId, (current) => {
3067
+ await this._tokenStore.updateInstanceState(aid, this._deviceId, this._slotId, (current) => {
3153
3068
  Object.assign(current, instanceState);
3154
3069
  return current;
3155
3070
  });
@@ -3571,7 +3486,7 @@ function hasEncryptionSeed(seed) {
3571
3486
  return seed !== void 0;
3572
3487
  }
3573
3488
  var DB_NAME = "aun-keystore";
3574
- var DB_VERSION = 6;
3489
+ var DB_VERSION = 7;
3575
3490
  var STORE_KEY_PAIRS = "key_pairs";
3576
3491
  var STORE_CERTS = "certs";
3577
3492
  var STORE_METADATA = "metadata";
@@ -3582,10 +3497,18 @@ var STORE_GROUP_OLD_EPOCHS = "group_old_epochs";
3582
3497
  var STORE_SESSIONS = "e2ee_sessions";
3583
3498
  var STORE_GROUP_STATE = "group_state";
3584
3499
  var STORE_AGENT_MD_CACHE = "agent_md_cache";
3500
+ var STORE_PENDING_IDENTITIES = "pending_identities";
3585
3501
  var STRUCTURED_RECOVERY_RETENTION_MS = 7 * 24 * 3600 * 1e3;
3586
3502
  function metadataStoreKey(aid) {
3587
3503
  return safeAid(aid);
3588
3504
  }
3505
+ function randomHex(byteLength) {
3506
+ const bytes = crypto.getRandomValues(new Uint8Array(byteLength));
3507
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
3508
+ }
3509
+ function pendingIdentityPrefix(aid) {
3510
+ return `${safeAid(aid)}-`;
3511
+ }
3589
3512
  function normalizeCertFingerprint(certFingerprint) {
3590
3513
  const normalized = String(certFingerprint ?? "").trim().toLowerCase();
3591
3514
  if (!normalized) return "";
@@ -3751,6 +3674,9 @@ function openDB() {
3751
3674
  if (!db.objectStoreNames.contains(STORE_AGENT_MD_CACHE)) {
3752
3675
  db.createObjectStore(STORE_AGENT_MD_CACHE);
3753
3676
  }
3677
+ if (!db.objectStoreNames.contains(STORE_PENDING_IDENTITIES)) {
3678
+ db.createObjectStore(STORE_PENDING_IDENTITIES);
3679
+ }
3754
3680
  };
3755
3681
  request.onsuccess = () => {
3756
3682
  const db = request.result;
@@ -3885,9 +3811,9 @@ async function idbDelete(storeName, key) {
3885
3811
  var _IndexedDBKeyStore = class _IndexedDBKeyStore {
3886
3812
  constructor(opts) {
3887
3813
  __publicField(this, "_log", _noopLog5);
3888
- /** 私钥加密种子;为空时降级为明文存储(向后兼容) */
3814
+ /** 私钥加密种子;空字符串也是有效 seed,默认不再写入明文私钥。 */
3889
3815
  __publicField(this, "_encryptionSeed");
3890
- this._encryptionSeed = opts?.encryptionSeed;
3816
+ this._encryptionSeed = opts?.encryptionSeed ?? "";
3891
3817
  }
3892
3818
  setLogger(log) {
3893
3819
  this._log = log;
@@ -3901,7 +3827,13 @@ var _IndexedDBKeyStore = class _IndexedDBKeyStore {
3901
3827
  for (const row of rows) {
3902
3828
  if (!isRecord(row.value)) continue;
3903
3829
  const envelope = row.value._encrypted_pk;
3904
- if (!isRecord(envelope)) continue;
3830
+ if (!isRecord(envelope)) {
3831
+ const plain = row.value.private_key_pem;
3832
+ if (typeof plain === "string" && plain) {
3833
+ migrations.push({ key: row.key, value: deepClone(row.value), privateKeyPem: plain });
3834
+ }
3835
+ continue;
3836
+ }
3905
3837
  try {
3906
3838
  const privateKeyPem = await _decryptPEM(envelope, oldSeed);
3907
3839
  migrations.push({ key: row.key, value: deepClone(row.value), privateKeyPem });
@@ -4000,16 +3932,14 @@ var _IndexedDBKeyStore = class _IndexedDBKeyStore {
4000
3932
  result.private_key_pem = await _decryptPEM(envelope, this._encryptionSeed);
4001
3933
  delete result._encrypted_pk;
4002
3934
  } catch {
4003
- this._log.error(`[keystore] decrypt ${aid} private keyfailed, maybe encryptionSeed mismatch`);
3935
+ this._log.error(`[keystore] decrypt ${aid} private key failed, maybe encryptionSeed mismatch`);
3936
+ throw new Error(`private key decrypt failed for aid ${aid}: seed_password mismatch or IndexedDB record corrupted`);
4004
3937
  }
4005
3938
  } else if (
4006
3939
  // 透明迁移:旧版明文数据自动加密回写
4007
3940
  !epk && typeof result.private_key_pem === "string" && hasEncryptionSeed(this._encryptionSeed)
4008
3941
  ) {
4009
- try {
4010
- await this.saveKeyPair(aid, result);
4011
- } catch {
4012
- }
3942
+ await this.saveKeyPair(aid, result);
4013
3943
  }
4014
3944
  return result;
4015
3945
  }
@@ -4021,6 +3951,123 @@ var _IndexedDBKeyStore = class _IndexedDBKeyStore {
4021
3951
  }
4022
3952
  await idbPut(STORE_KEY_PAIRS, metadataStoreKey(aid), record);
4023
3953
  }
3954
+ // ── RegisterAID pending 身份 ─────────────────────────
3955
+ async pendingIdentityDir(aid) {
3956
+ const handle = `${pendingIdentityPrefix(aid)}${randomHex(4)}-${Math.floor(Date.now() / 1e3)}`;
3957
+ const now = Date.now();
3958
+ await idbPut(STORE_PENDING_IDENTITIES, handle, {
3959
+ aid,
3960
+ created_at: now,
3961
+ updated_at: now
3962
+ });
3963
+ return handle;
3964
+ }
3965
+ async listPendingIdentityDirs(aid) {
3966
+ const prefix = pendingIdentityPrefix(aid);
3967
+ const rows = await idbGetAllByPrefix(STORE_PENDING_IDENTITIES, prefix);
3968
+ return rows.filter((row) => row.key.startsWith(prefix) && isRecord(row.value) && String(row.value.aid ?? "") === aid).sort((a, b) => Number(b.value.updated_at ?? 0) - Number(a.value.updated_at ?? 0)).map((row) => row.key);
3969
+ }
3970
+ async savePendingKeyPair(handle, aid, keyPair) {
3971
+ const current = await this._loadPendingRecord(handle, aid);
3972
+ if (!current) throw new Error(`pending identity not found: ${handle}`);
3973
+ const record = deepClone(keyPair);
3974
+ const privateKeyPem = record.private_key_pem;
3975
+ if (typeof privateKeyPem !== "string" || !privateKeyPem) {
3976
+ throw new Error("savePendingKeyPair requires private_key_pem");
3977
+ }
3978
+ record._encrypted_pk = await _encryptPEM(privateKeyPem, this._encryptionSeed ?? "");
3979
+ delete record.private_key_pem;
3980
+ await idbPut(STORE_PENDING_IDENTITIES, handle, {
3981
+ ...current,
3982
+ aid,
3983
+ key_pair: record,
3984
+ updated_at: Date.now()
3985
+ });
3986
+ }
3987
+ async loadPendingKeyPair(handle, aid) {
3988
+ const current = await this._loadPendingRecord(handle, aid, false);
3989
+ if (!current || !isRecord(current.key_pair)) return null;
3990
+ const result = deepClone(current.key_pair);
3991
+ const encrypted = result._encrypted_pk;
3992
+ if (isRecord(encrypted)) {
3993
+ try {
3994
+ const envelope = encrypted;
3995
+ result.private_key_pem = await _decryptPEM(envelope, this._encryptionSeed ?? "");
3996
+ delete result._encrypted_pk;
3997
+ return result;
3998
+ } catch {
3999
+ this._log.error(`[keystore] decrypt pending ${aid} private key failed, maybe encryptionSeed mismatch`);
4000
+ throw new Error(`pending identity private key decrypt failed for aid ${aid}: seed_password mismatch or IndexedDB record corrupted`);
4001
+ }
4002
+ }
4003
+ if (typeof result.private_key_pem === "string" && result.private_key_pem) {
4004
+ await this.savePendingKeyPair(handle, aid, result);
4005
+ return result;
4006
+ }
4007
+ return result;
4008
+ }
4009
+ async savePendingCert(handle, certPem) {
4010
+ const current = await this._loadPendingRecord(handle, void 0);
4011
+ if (!current) throw new Error(`pending identity not found: ${handle}`);
4012
+ await idbPut(STORE_PENDING_IDENTITIES, handle, {
4013
+ ...current,
4014
+ cert: certPem,
4015
+ updated_at: Date.now()
4016
+ });
4017
+ }
4018
+ async promotePendingIdentity(handle, aid) {
4019
+ const current = await this._loadPendingRecord(handle, aid);
4020
+ if (!current) throw new Error(`pending identity not found: ${handle}`);
4021
+ if (!isRecord(current.key_pair)) {
4022
+ throw new Error(`promotePendingIdentity: missing pending key pair: ${handle}`);
4023
+ }
4024
+ const targetKey = metadataStoreKey(aid);
4025
+ const [existingKeyPair, existingCert, existingMetadata] = await Promise.all([
4026
+ idbGet(STORE_KEY_PAIRS, targetKey),
4027
+ idbGet(STORE_CERTS, certStoreKey(aid)),
4028
+ idbGet(STORE_METADATA, targetKey)
4029
+ ]);
4030
+ if (existingKeyPair || existingCert || existingMetadata) {
4031
+ throw new Error(`promotePendingIdentity: target exists: ${targetKey}`);
4032
+ }
4033
+ const keyPair = await this._protectedPendingKeyPair(current, aid);
4034
+ await idbPut(STORE_KEY_PAIRS, targetKey, keyPair);
4035
+ if (typeof current.cert === "string" && current.cert) {
4036
+ await idbPut(STORE_CERTS, certStoreKey(aid), current.cert);
4037
+ }
4038
+ await idbDelete(STORE_PENDING_IDENTITIES, handle);
4039
+ return targetKey;
4040
+ }
4041
+ async _protectedPendingKeyPair(current, aid) {
4042
+ if (!isRecord(current.key_pair)) {
4043
+ throw new Error(`pending identity missing key pair for ${aid}`);
4044
+ }
4045
+ const keyPair = deepClone(current.key_pair);
4046
+ const privateKeyPem = keyPair.private_key_pem;
4047
+ if (typeof privateKeyPem === "string" && privateKeyPem) {
4048
+ throw new Error(`pending identity private key is plaintext for ${aid}`);
4049
+ }
4050
+ if (!isRecord(keyPair._encrypted_pk)) {
4051
+ throw new Error(`pending identity private key is not encrypted for ${aid}`);
4052
+ }
4053
+ return keyPair;
4054
+ }
4055
+ async cleanupPendingDirs(maxAgeMs = 6e5) {
4056
+ const rows = await idbGetAll(STORE_PENDING_IDENTITIES);
4057
+ const now = Date.now();
4058
+ let removed = 0;
4059
+ for (const row of rows) {
4060
+ if (!isRecord(row.value)) continue;
4061
+ const updatedAt = Number(row.value.updated_at ?? row.value.created_at ?? 0);
4062
+ if (updatedAt && now - updatedAt < maxAgeMs) continue;
4063
+ await idbDelete(STORE_PENDING_IDENTITIES, row.key);
4064
+ removed++;
4065
+ }
4066
+ return removed;
4067
+ }
4068
+ async discardPendingIdentity(handle) {
4069
+ await idbDelete(STORE_PENDING_IDENTITIES, handle);
4070
+ }
4024
4071
  // ── 证书 ──────────────────────────────────────────
4025
4072
  async loadCert(aid, certFingerprint) {
4026
4073
  const tStart = Date.now();
@@ -4387,6 +4434,18 @@ var _IndexedDBKeyStore = class _IndexedDBKeyStore {
4387
4434
  });
4388
4435
  }
4389
4436
  // ── 内部辅助 ─────────────────────────────────────────
4437
+ async _loadPendingRecord(handle, aid, required = true) {
4438
+ const data = await idbGet(STORE_PENDING_IDENTITIES, handle);
4439
+ if (!isRecord(data)) {
4440
+ if (required) throw new Error(`pending identity not found: ${handle}`);
4441
+ return null;
4442
+ }
4443
+ const record = deepClone(data);
4444
+ if (aid !== void 0 && String(record.aid ?? "") !== aid) {
4445
+ throw new Error(`pending identity aid mismatch: ${handle}`);
4446
+ }
4447
+ return record;
4448
+ }
4390
4449
  async _loadKeyPairUnlocked(aid) {
4391
4450
  const data = await idbGet(STORE_KEY_PAIRS, metadataStoreKey(aid));
4392
4451
  if (!isRecord(data)) return null;
@@ -4397,16 +4456,14 @@ var _IndexedDBKeyStore = class _IndexedDBKeyStore {
4397
4456
  result.private_key_pem = await _decryptPEM(envelope, this._encryptionSeed);
4398
4457
  delete result._encrypted_pk;
4399
4458
  } catch {
4400
- this._log.error(`[keystore] decrypt ${aid} private keyfailed, maybe encryptionSeed mismatch`);
4459
+ this._log.error(`[keystore] decrypt ${aid} private key failed, maybe encryptionSeed mismatch`);
4460
+ throw new Error(`private key decrypt failed for aid ${aid}: seed_password mismatch or IndexedDB record corrupted`);
4401
4461
  }
4402
4462
  } else if (
4403
4463
  // 透明迁移:旧版明文数据自动加密回写
4404
4464
  !isRecord(result._encrypted_pk) && typeof result.private_key_pem === "string" && hasEncryptionSeed(this._encryptionSeed)
4405
4465
  ) {
4406
- try {
4407
- await this._saveKeyPairUnlocked(aid, result);
4408
- } catch {
4409
- }
4466
+ await this._saveKeyPairUnlocked(aid, result);
4410
4467
  }
4411
4468
  return result;
4412
4469
  }
@@ -5465,6 +5522,35 @@ var V2KeyStore = class _V2KeyStore {
5465
5522
  req.onerror = () => reject(req.error);
5466
5523
  });
5467
5524
  }
5525
+ async saveGroupIdentity(deviceId, groupAid, privateKeyPem, pubDer) {
5526
+ const record = {
5527
+ device_id: deviceId,
5528
+ key_type: "group_identity",
5529
+ group_id: groupAid,
5530
+ key_id: "",
5531
+ private_key: new TextEncoder().encode(privateKeyPem),
5532
+ public_key: pubDer,
5533
+ created_at: Date.now()
5534
+ };
5535
+ return new Promise((resolve, reject) => {
5536
+ const req = this.store("readwrite").put(record);
5537
+ req.onsuccess = () => resolve();
5538
+ req.onerror = () => reject(req.error);
5539
+ });
5540
+ }
5541
+ async loadGroupIdentity(deviceId, groupAid) {
5542
+ return new Promise((resolve, reject) => {
5543
+ const req = this.store("readonly").get([deviceId, "group_identity", groupAid, ""]);
5544
+ req.onsuccess = () => {
5545
+ const r = req.result;
5546
+ resolve(r ? {
5547
+ privateKeyPem: new TextDecoder().decode(r.private_key),
5548
+ pubDer: new Uint8Array(r.public_key)
5549
+ } : null);
5550
+ };
5551
+ req.onerror = () => reject(req.error);
5552
+ });
5553
+ }
5468
5554
  async markGroupSPKUploaded(deviceId, groupId, spkId) {
5469
5555
  const record = {
5470
5556
  device_id: deviceId,
@@ -10368,7 +10454,7 @@ var _AUNClient = class _AUNClient {
10368
10454
  __publicField(this, "_sessionOptions", { ...DEFAULT_SESSION_OPTIONS });
10369
10455
  __publicField(this, "_dispatcher");
10370
10456
  __publicField(this, "_discovery");
10371
- __publicField(this, "_keystore");
10457
+ __publicField(this, "_tokenStore");
10372
10458
  __publicField(this, "_auth");
10373
10459
  __publicField(this, "_transport");
10374
10460
  // E2EE 编排状态(内存缓存)
@@ -10450,7 +10536,7 @@ var _AUNClient = class _AUNClient {
10450
10536
  __publicField(this, "_clientLog");
10451
10537
  __publicField(this, "_logAuth");
10452
10538
  __publicField(this, "_logTransport");
10453
- __publicField(this, "_logKeystore");
10539
+ __publicField(this, "_tokenStoreLog");
10454
10540
  __publicField(this, "_logDiscovery");
10455
10541
  __publicField(this, "_logEvents");
10456
10542
  /**
@@ -10479,18 +10565,18 @@ var _AUNClient = class _AUNClient {
10479
10565
  this._clientLog = this._logger.for("aun_core.client");
10480
10566
  this._logAuth = this._logger.for("aun_core.auth");
10481
10567
  this._logTransport = this._logger.for("aun_core.transport");
10482
- this._logKeystore = this._logger.for("aun_core.keystore");
10568
+ this._tokenStoreLog = this._logger.for("aun_core.keystore");
10483
10569
  this._logDiscovery = this._logger.for("aun_core.discovery");
10484
10570
  this._logEvents = this._logger.for("aun_core.events");
10485
10571
  this._clientLog.info(`AUNClient initialized: debug=${_debug} aunPath=${this.configModel.aunPath} aid=${initAid ?? "-"}`);
10486
10572
  this._dispatcher = new EventDispatcher();
10487
10573
  this._discovery = new GatewayDiscovery();
10488
- this._keystore = new IndexedDBKeyStore({});
10574
+ this._tokenStore = new IndexedDBKeyStore({});
10489
10575
  this._slotId = inputAid?.slotId || "default";
10490
10576
  this._connectDeliveryMode = normalizeDeliveryModeConfig({ mode: "fanout" });
10491
10577
  this._defaultConnectDeliveryMode = { ...this._connectDeliveryMode };
10492
10578
  this._auth = new AuthFlow({
10493
- keystore: this._keystore,
10579
+ tokenStore: this._tokenStore,
10494
10580
  crypto: new CryptoProvider(),
10495
10581
  aid: initAid,
10496
10582
  deviceId: this._deviceId,
@@ -10518,6 +10604,7 @@ var _AUNClient = class _AUNClient {
10518
10604
  public_key_der_b64: inputAid.publicKey,
10519
10605
  cert: inputAid.certPem
10520
10606
  };
10607
+ this._auth.setIdentity(this._identity);
10521
10608
  this._state = "disconnected";
10522
10609
  }
10523
10610
  }
@@ -10527,8 +10614,8 @@ var _AUNClient = class _AUNClient {
10527
10614
  if (typeof this._discovery.setLogger === "function") {
10528
10615
  this._discovery.setLogger(this._logger.for("aun_core.discovery"));
10529
10616
  }
10530
- if (typeof this._keystore.setLogger === "function") {
10531
- this._keystore.setLogger(this._logKeystore);
10617
+ if (typeof this._tokenStore.setLogger === "function") {
10618
+ this._tokenStore.setLogger(this._tokenStoreLog);
10532
10619
  }
10533
10620
  this._dispatcher.subscribe("_raw.message.received", (data) => {
10534
10621
  this._onRawMessageReceived(data);
@@ -10719,7 +10806,7 @@ var _AUNClient = class _AUNClient {
10719
10806
  if (!target) throw new ValidationError("verifyAgentMd requires non-empty aid");
10720
10807
  let peer = target === this._currentAid?.aid ? this._currentAid : null;
10721
10808
  if (!peer) {
10722
- let certPem = String(await this._keystore.loadCert(target) ?? "").trim();
10809
+ let certPem = String(await this._tokenStore.loadCert(target) ?? "").trim();
10723
10810
  if (!certPem) {
10724
10811
  certPem = String(await this._fetchPeerCert(target) ?? "").trim();
10725
10812
  }
@@ -10866,11 +10953,11 @@ var _AUNClient = class _AUNClient {
10866
10953
  async _readAgentMdStorage(logicalKey) {
10867
10954
  const key = String(logicalKey ?? "").trim();
10868
10955
  if (!key) return null;
10869
- const load = this._keystore.loadAgentMdCache;
10956
+ const load = this._tokenStore.loadAgentMdCache;
10870
10957
  if (typeof load !== "function") {
10871
10958
  throw new Error("IndexedDB agent.md storage unavailable");
10872
10959
  }
10873
- const record = await load.call(this._keystore, this._agentMdRoot(), key);
10960
+ const record = await load.call(this._tokenStore, this._agentMdRoot(), key);
10874
10961
  if (record && Object.prototype.hasOwnProperty.call(record, "content")) {
10875
10962
  return String(record.content ?? "");
10876
10963
  }
@@ -10879,12 +10966,12 @@ var _AUNClient = class _AUNClient {
10879
10966
  async _writeAgentMdStorage(logicalKey, content) {
10880
10967
  const key = String(logicalKey ?? "").trim();
10881
10968
  if (!key) return;
10882
- const save = this._keystore.upsertAgentMdCache;
10969
+ const save = this._tokenStore.upsertAgentMdCache;
10883
10970
  if (typeof save !== "function") {
10884
10971
  throw new Error("IndexedDB agent.md storage unavailable");
10885
10972
  }
10886
10973
  const text = String(content ?? "");
10887
- await save.call(this._keystore, this._agentMdRoot(), key, {
10974
+ await save.call(this._tokenStore, this._agentMdRoot(), key, {
10888
10975
  content: text,
10889
10976
  local_etag: await this._agentMdContentEtag(text),
10890
10977
  fetched_at: Date.now()
@@ -11263,13 +11350,13 @@ var _AUNClient = class _AUNClient {
11263
11350
  this._clientLog = this._logger.for("aun_core.client");
11264
11351
  this._logAuth = this._logger.for("aun_core.auth");
11265
11352
  this._logTransport = this._logger.for("aun_core.transport");
11266
- this._logKeystore = this._logger.for("aun_core.keystore");
11353
+ this._tokenStoreLog = this._logger.for("aun_core.keystore");
11267
11354
  this._logDiscovery = this._logger.for("aun_core.discovery");
11268
11355
  this._logEvents = this._logger.for("aun_core.events");
11269
11356
  this._discovery = new GatewayDiscovery();
11270
- this._keystore = new IndexedDBKeyStore({});
11357
+ this._tokenStore = new IndexedDBKeyStore({});
11271
11358
  this._auth = new AuthFlow({
11272
- keystore: this._keystore,
11359
+ tokenStore: this._tokenStore,
11273
11360
  crypto: new CryptoProvider(),
11274
11361
  aid: aid.aid,
11275
11362
  deviceId: this._deviceId,
@@ -11293,8 +11380,8 @@ var _AUNClient = class _AUNClient {
11293
11380
  if (typeof this._discovery.setLogger === "function") {
11294
11381
  this._discovery.setLogger(this._logDiscovery);
11295
11382
  }
11296
- if (typeof this._keystore.setLogger === "function") {
11297
- this._keystore.setLogger(this._logKeystore);
11383
+ if (typeof this._tokenStore.setLogger === "function") {
11384
+ this._tokenStore.setLogger(this._tokenStoreLog);
11298
11385
  }
11299
11386
  }
11300
11387
  loadIdentity(aid) {
@@ -11312,6 +11399,7 @@ var _AUNClient = class _AUNClient {
11312
11399
  public_key_der_b64: aid.publicKey,
11313
11400
  cert: aid.certPem
11314
11401
  };
11402
+ this._auth.setIdentity(this._identity);
11315
11403
  this._state = "disconnected";
11316
11404
  this._closing = false;
11317
11405
  }
@@ -12571,8 +12659,8 @@ var _AUNClient = class _AUNClient {
12571
12659
  const keyEpoch = Number(d.key_epoch ?? 0);
12572
12660
  const membershipSnapshot = String(d.membership_snapshot ?? "").trim();
12573
12661
  const policySnapshot = String(d.policy_snapshot ?? "").trim();
12574
- const loadFn = this._keystore.loadGroupState;
12575
- const localState = loadFn ? await loadFn.call(this._keystore, groupId) : null;
12662
+ const loadFn = this._tokenStore.loadGroupState;
12663
+ const localState = loadFn ? await loadFn.call(this._tokenStore, groupId) : null;
12576
12664
  if (localState && localState.state_hash && localState.state_hash !== prevStateHash) {
12577
12665
  this._clientLog.warn(
12578
12666
  "[aun_core] state_hash \u94FE\u4E0D\u8FDE\u7EED group=%s local_sv=%d event_sv=%d",
@@ -12611,9 +12699,9 @@ var _AUNClient = class _AUNClient {
12611
12699
  return;
12612
12700
  }
12613
12701
  }
12614
- const saveFn2 = this._keystore.saveGroupState;
12702
+ const saveFn2 = this._tokenStore.saveGroupState;
12615
12703
  if (saveFn2) {
12616
- await saveFn2.call(this._keystore, groupId, {
12704
+ await saveFn2.call(this._tokenStore, groupId, {
12617
12705
  group_id: groupId,
12618
12706
  state_version: sv,
12619
12707
  state_hash: sHash,
@@ -12649,9 +12737,9 @@ var _AUNClient = class _AUNClient {
12649
12737
  );
12650
12738
  return;
12651
12739
  }
12652
- const saveFn = this._keystore.saveGroupState;
12740
+ const saveFn = this._tokenStore.saveGroupState;
12653
12741
  if (saveFn) {
12654
- await saveFn.call(this._keystore, groupId, {
12742
+ await saveFn.call(this._tokenStore, groupId, {
12655
12743
  group_id: groupId,
12656
12744
  state_version: stateVersion,
12657
12745
  state_hash: stateHash,
@@ -13022,7 +13110,7 @@ var _AUNClient = class _AUNClient {
13022
13110
  refreshAfter: now + PEER_CERT_CACHE_TTL
13023
13111
  });
13024
13112
  try {
13025
- await this._keystore.saveCert(aid, certPem, certFingerprint, { makeActive: false });
13113
+ await this._tokenStore.saveCert(aid, certPem, certFingerprint, { makeActive: false });
13026
13114
  } catch (exc) {
13027
13115
  this._clientLog.error(`write cert to keystore failed (aid=${aid}): ${String(exc)}`, exc instanceof Error ? exc : void 0);
13028
13116
  }
@@ -13039,7 +13127,7 @@ var _AUNClient = class _AUNClient {
13039
13127
  const cached = this._certCache.get(cacheKey);
13040
13128
  const now = Date.now() / 1e3;
13041
13129
  if (cached && now < cached.refreshAfter) return true;
13042
- const localCert = await this._keystore.loadCert(aid, certFingerprint);
13130
+ const localCert = await this._tokenStore.loadCert(aid, certFingerprint);
13043
13131
  if (localCert) {
13044
13132
  if (certFingerprint) {
13045
13133
  const actualFingerprint = await this._certFingerprint(localCert);
@@ -13062,7 +13150,7 @@ var _AUNClient = class _AUNClient {
13062
13150
  }
13063
13151
  try {
13064
13152
  const certPem = await this._fetchPeerCert(aid, certFingerprint);
13065
- await this._keystore.saveCert(aid, certPem, certFingerprint, { makeActive: false });
13153
+ await this._tokenStore.saveCert(aid, certPem, certFingerprint, { makeActive: false });
13066
13154
  return true;
13067
13155
  } catch (exc) {
13068
13156
  if (cached && now < cached.validatedAt + PEER_CERT_CACHE_TTL * 2) {
@@ -13258,8 +13346,8 @@ var _AUNClient = class _AUNClient {
13258
13346
  if (!target) throw new StateError("gateway discovery requires a loaded AID");
13259
13347
  if (this._gatewayUrl) return this._gatewayUrl;
13260
13348
  try {
13261
- const getMetadata = this._keystore.getMetadata;
13262
- const raw = typeof getMetadata === "function" ? String(await getMetadata.call(this._keystore, target, "gateway_url") ?? "").trim() : "";
13349
+ const getMetadata = this._tokenStore.getMetadata;
13350
+ const raw = typeof getMetadata === "function" ? String(await getMetadata.call(this._tokenStore, target, "gateway_url") ?? "").trim() : "";
13263
13351
  if (raw) {
13264
13352
  const gateway = raw.startsWith('"') && raw.endsWith('"') ? String(JSON.parse(raw)).trim() : raw;
13265
13353
  if (gateway) {
@@ -13282,9 +13370,9 @@ var _AUNClient = class _AUNClient {
13282
13370
  const gateway = await this._discovery.discover(url);
13283
13371
  this._gatewayUrl = gateway;
13284
13372
  try {
13285
- const setMetadata = this._keystore.setMetadata;
13373
+ const setMetadata = this._tokenStore.setMetadata;
13286
13374
  if (typeof setMetadata === "function") {
13287
- await setMetadata.call(this._keystore, target, "gateway_url", gateway);
13375
+ await setMetadata.call(this._tokenStore, target, "gateway_url", gateway);
13288
13376
  }
13289
13377
  } catch {
13290
13378
  }
@@ -13316,13 +13404,8 @@ var _AUNClient = class _AUNClient {
13316
13404
  return [gateway];
13317
13405
  }
13318
13406
  async _syncIdentityAfterConnect(accessToken) {
13319
- let identity = null;
13320
- try {
13321
- identity = await this._auth.loadIdentityOrNone(this._aid ?? void 0);
13322
- } catch {
13323
- }
13407
+ const identity = this._identity;
13324
13408
  if (!identity) {
13325
- this._identity = null;
13326
13409
  return;
13327
13410
  }
13328
13411
  identity.access_token = accessToken;
@@ -13332,8 +13415,6 @@ var _AUNClient = class _AUNClient {
13332
13415
  const persistIdentity = this._auth._persistIdentity;
13333
13416
  if (typeof persistIdentity === "function") {
13334
13417
  await persistIdentity.call(this._auth, identity);
13335
- } else {
13336
- await this._keystore.saveIdentity(String(identity.aid), identity);
13337
13418
  }
13338
13419
  }
13339
13420
  }
@@ -13803,8 +13884,7 @@ var _AUNClient = class _AUNClient {
13803
13884
  }
13804
13885
  // ── Named Group(命名群)高层 API ────────────────────────────
13805
13886
  /**
13806
- * 创建命名群:本地生成 P-256 keypair,调用 group.create 传入 public_key,
13807
- * 服务端签发群 AID 证书,返回后将证书和私钥存入 keystore。
13887
+ * 创建命名群:群/P2P 私钥由 V2 数据库存储,不写入 AID 身份私钥存储。
13808
13888
  */
13809
13889
  async createNamedGroup(groupName, opts = {}) {
13810
13890
  const tStart = Date.now();
@@ -13824,15 +13904,10 @@ var _AUNClient = class _AUNClient {
13824
13904
  const aidCert = result?.aid_cert;
13825
13905
  const groupAid = String(groupInfo?.group_aid ?? "");
13826
13906
  if (groupAid && aidCert) {
13827
- await this._keystore.saveIdentity(groupAid, {
13828
- private_key_pem: identity.private_key_pem,
13829
- public_key: identity.public_key_der_b64,
13830
- curve: "P-256",
13831
- type: "group_identity"
13832
- });
13907
+ await this._saveGroupIdentityToV2(groupAid, identity);
13833
13908
  const certPem = String(aidCert.cert ?? "");
13834
13909
  if (certPem) {
13835
- await this._keystore.saveCert(groupAid, certPem);
13910
+ await this._tokenStore.saveCert(groupAid, certPem);
13836
13911
  }
13837
13912
  }
13838
13913
  this._clientLog.debug(`createNamedGroup exit: elapsed=${Date.now() - tStart}ms group_aid=${groupAid}`);
@@ -13862,15 +13937,10 @@ var _AUNClient = class _AUNClient {
13862
13937
  const aidCert = result?.aid_cert;
13863
13938
  const groupAid = String(groupInfo?.group_aid ?? "");
13864
13939
  if (groupAid && aidCert) {
13865
- await this._keystore.saveIdentity(groupAid, {
13866
- private_key_pem: identity.private_key_pem,
13867
- public_key: identity.public_key_der_b64,
13868
- curve: "P-256",
13869
- type: "group_identity"
13870
- });
13940
+ await this._saveGroupIdentityToV2(groupAid, identity);
13871
13941
  const certPem = String(aidCert.cert ?? "");
13872
13942
  if (certPem) {
13873
- await this._keystore.saveCert(groupAid, certPem);
13943
+ await this._tokenStore.saveCert(groupAid, certPem);
13874
13944
  }
13875
13945
  }
13876
13946
  this._clientLog.debug(`bindGroupAid exit: elapsed=${Date.now() - tStart}ms group_aid=${groupAid}`);
@@ -13906,7 +13976,7 @@ var _AUNClient = class _AUNClient {
13906
13976
  const deviceId = this._deviceId;
13907
13977
  const slotId = this._slotId;
13908
13978
  try {
13909
- const loadAll = this._keystore.loadAllSeqs?.bind(this._keystore);
13979
+ const loadAll = this._tokenStore.loadAllSeqs?.bind(this._tokenStore);
13910
13980
  if (typeof loadAll === "function") {
13911
13981
  let state = await loadAll(aid, deviceId, slotId);
13912
13982
  if (this._seqTrackerContext !== context) return;
@@ -13916,7 +13986,7 @@ var _AUNClient = class _AUNClient {
13916
13986
  }
13917
13987
  return;
13918
13988
  }
13919
- const loader = this._keystore.loadInstanceState?.bind(this._keystore);
13989
+ const loader = this._tokenStore.loadInstanceState?.bind(this._tokenStore);
13920
13990
  if (typeof loader !== "function") return;
13921
13991
  const stateHolder = await loader(aid, deviceId, slotId);
13922
13992
  if (this._seqTrackerContext !== context) return;
@@ -13969,8 +14039,8 @@ var _AUNClient = class _AUNClient {
13969
14039
  const aid = this._aid;
13970
14040
  const deviceId = this._deviceId;
13971
14041
  const slotId = this._slotId;
13972
- const saver = this._keystore.saveSeq?.bind(this._keystore);
13973
- const deleter = this._keystore.deleteSeq?.bind(this._keystore);
14042
+ const saver = this._tokenStore.saveSeq?.bind(this._tokenStore);
14043
+ const deleter = this._tokenStore.deleteSeq?.bind(this._tokenStore);
13974
14044
  if (typeof saver === "function") {
13975
14045
  for (const [oldNs, newNs] of Object.entries(renameMap)) {
13976
14046
  if (typeof deleter === "function") {
@@ -14037,7 +14107,7 @@ var _AUNClient = class _AUNClient {
14037
14107
  const state = this._seqTracker.exportState();
14038
14108
  if (Object.keys(state).length === 0) return;
14039
14109
  try {
14040
- const saveFn = this._keystore.saveSeq?.bind(this._keystore);
14110
+ const saveFn = this._tokenStore.saveSeq?.bind(this._tokenStore);
14041
14111
  if (typeof saveFn === "function") {
14042
14112
  for (const [ns, seq] of Object.entries(state)) {
14043
14113
  saveFn(this._aid, this._deviceId, this._slotId, ns, seq).catch((exc) => {
@@ -14053,8 +14123,8 @@ var _AUNClient = class _AUNClient {
14053
14123
  }
14054
14124
  return;
14055
14125
  }
14056
- if (typeof this._keystore.updateInstanceState === "function") {
14057
- this._keystore.updateInstanceState(this._aid, this._deviceId, this._slotId, (current) => {
14126
+ if (typeof this._tokenStore.updateInstanceState === "function") {
14127
+ this._tokenStore.updateInstanceState(this._aid, this._deviceId, this._slotId, (current) => {
14058
14128
  current.seq_tracker_state = state;
14059
14129
  return current;
14060
14130
  }).catch((exc) => {
@@ -14083,15 +14153,15 @@ var _AUNClient = class _AUNClient {
14083
14153
  if (!this._aid || !ns) return;
14084
14154
  const seq = this._seqTracker.getContiguousSeq(ns);
14085
14155
  try {
14086
- if (seq > 0 && typeof this._keystore.saveSeq === "function") {
14087
- this._keystore.saveSeq(this._aid, this._deviceId, this._slotId, ns, seq).catch((exc) => {
14156
+ if (seq > 0 && typeof this._tokenStore.saveSeq === "function") {
14157
+ this._tokenStore.saveSeq(this._aid, this._deviceId, this._slotId, ns, seq).catch((exc) => {
14088
14158
  this._clientLog.debug(`persist repaired seq failed: ns=${ns} err=${formatCaughtError(exc)}`);
14089
14159
  });
14090
14160
  return;
14091
14161
  }
14092
- const deleteSeq = this._keystore.deleteSeq;
14162
+ const deleteSeq = this._tokenStore.deleteSeq;
14093
14163
  if (seq <= 0 && typeof deleteSeq === "function") {
14094
- deleteSeq.call(this._keystore, this._aid, this._deviceId, this._slotId, ns).catch((exc) => {
14164
+ deleteSeq.call(this._tokenStore, this._aid, this._deviceId, this._slotId, ns).catch((exc) => {
14095
14165
  this._clientLog.debug(`delete repaired seq failed: ns=${ns} err=${formatCaughtError(exc)}`);
14096
14166
  });
14097
14167
  return;
@@ -14190,6 +14260,25 @@ var _AUNClient = class _AUNClient {
14190
14260
  this._clientLog.debug(`V2 session initialized aid=${this._aid} device=${this._deviceId}`);
14191
14261
  this._safeAsync(this._v2AutoConfirmPendingProposals());
14192
14262
  }
14263
+ _v2StoreDeviceId() {
14264
+ return `aid:${encodeURIComponent(String(this._aid ?? ""))}|device:${encodeURIComponent(String(this._deviceId ?? ""))}`;
14265
+ }
14266
+ async _saveGroupIdentityToV2(groupAid, identity) {
14267
+ const privateKeyPem = String(identity.private_key_pem ?? "").trim();
14268
+ const publicKeyDerB642 = String(identity.public_key_der_b64 ?? "").trim();
14269
+ if (!groupAid || !privateKeyPem || !publicKeyDerB642) {
14270
+ throw new StateError("group identity is incomplete");
14271
+ }
14272
+ if (!this._v2KeyStore) {
14273
+ this._v2KeyStore = await V2KeyStore.open();
14274
+ }
14275
+ await this._v2KeyStore.saveGroupIdentity(
14276
+ this._v2StoreDeviceId(),
14277
+ groupAid,
14278
+ privateKeyPem,
14279
+ base64ToUint8(publicKeyDerB642)
14280
+ );
14281
+ }
14193
14282
  async _v2TrustedIKPubDer(aid) {
14194
14283
  const normalizedAid = String(aid ?? "").trim();
14195
14284
  if (!normalizedAid) throw new E2EEError("spk_aid_missing");
@@ -16086,6 +16175,334 @@ function _uuidV4() {
16086
16175
 
16087
16176
  // src/aid-store.ts
16088
16177
  init_crypto();
16178
+
16179
+ // src/register-flow.ts
16180
+ init_crypto();
16181
+ var _noopLog6 = { error: () => {
16182
+ }, warn: () => {
16183
+ }, info: () => {
16184
+ }, debug: () => {
16185
+ } };
16186
+ function _gatewayHttpUrl(gatewayUrl, path) {
16187
+ try {
16188
+ const parsed = new URL(gatewayUrl);
16189
+ const scheme = parsed.protocol === "wss:" ? "https:" : "http:";
16190
+ return `${scheme}//${parsed.host}${path}`;
16191
+ } catch {
16192
+ return gatewayUrl.replace(/^wss:/, "https:").replace(/^ws:/, "http:") + path;
16193
+ }
16194
+ }
16195
+ function _extractSpkiB64FromPem(certPem) {
16196
+ const der = new Uint8Array(pemToArrayBuffer(certPem));
16197
+ function readLen(data, offset) {
16198
+ const first = data[offset];
16199
+ if (!(first & 128)) return { value: first, lenBytes: 1 };
16200
+ const n = first & 127;
16201
+ let v = 0;
16202
+ for (let i = 0; i < n; i++) v = v << 8 | data[offset + 1 + i];
16203
+ return { value: v, lenBytes: 1 + n };
16204
+ }
16205
+ function skipTlv(data, offset) {
16206
+ const len = readLen(data, offset + 1);
16207
+ return offset + 1 + len.lenBytes + len.value;
16208
+ }
16209
+ const certLen = readLen(der, 1);
16210
+ const tbsStart = 1 + certLen.lenBytes;
16211
+ const tbsLen = readLen(der, tbsStart + 1);
16212
+ let pos = tbsStart + 1 + tbsLen.lenBytes;
16213
+ if (der[pos] === 160) pos = skipTlv(der, pos);
16214
+ pos = skipTlv(der, pos);
16215
+ pos = skipTlv(der, pos);
16216
+ pos = skipTlv(der, pos);
16217
+ pos = skipTlv(der, pos);
16218
+ pos = skipTlv(der, pos);
16219
+ const spkiLen = readLen(der, pos + 1);
16220
+ const spkiEnd = pos + 1 + spkiLen.lenBytes + spkiLen.value;
16221
+ return uint8ToBase64(der.slice(pos, spkiEnd));
16222
+ }
16223
+ var RegisterFlow = class {
16224
+ constructor(opts) {
16225
+ __publicField(this, "_keystore");
16226
+ __publicField(this, "_crypto");
16227
+ __publicField(this, "_logger");
16228
+ this._keystore = opts.keystore;
16229
+ this._crypto = opts.crypto;
16230
+ this._logger = opts.logger ?? _noopLog6;
16231
+ }
16232
+ async registerAid(gatewayUrl, aid) {
16233
+ const tStart = Date.now();
16234
+ AuthFlow._validateAidName(aid);
16235
+ this._logger.debug(`registerAid enter: aid=${aid}, gateway=${gatewayUrl}`);
16236
+ try {
16237
+ const existing = await this._keystore.loadIdentity(aid);
16238
+ if (existing && existing.private_key_pem && existing.public_key_der_b64) {
16239
+ this._logger.debug(`registerAid: local keypair exists, checking server: aid=${aid}`);
16240
+ const localPubB64 = String(existing.public_key_der_b64);
16241
+ const serverCertPem = await this._downloadRegisteredCert(gatewayUrl, aid);
16242
+ if (serverCertPem) {
16243
+ const serverPubB64 = _extractSpkiB64FromPem(serverCertPem);
16244
+ if (serverPubB64 !== localPubB64) {
16245
+ throw new IdentityConflictError(
16246
+ `AID '${aid}' is registered by another party on server (public key mismatch). Choose a different name.`
16247
+ );
16248
+ }
16249
+ this._logger.info(`registerAid: idempotent return for already-registered AID: aid=${aid}`);
16250
+ if (!existing.cert) {
16251
+ existing.cert = serverCertPem;
16252
+ await this._persistIdentity(existing);
16253
+ }
16254
+ this._logger.debug(`registerAid exit (idempotent): elapsed=${Date.now() - tStart}ms aid=${aid}`);
16255
+ return {
16256
+ aid,
16257
+ cert: serverCertPem,
16258
+ private_key_pem: String(existing.private_key_pem),
16259
+ public_key_der_b64: localPubB64,
16260
+ curve: String(existing.curve ?? "P-256")
16261
+ };
16262
+ } else {
16263
+ this._logger.debug(`registerAid: server has no record, registering with existing keypair: aid=${aid}`);
16264
+ const created2 = await this._createAid(gatewayUrl, existing);
16265
+ const certPem2 = String(created2.cert ?? "");
16266
+ if (!certPem2) throw new AuthError(`registerAid: server response missing cert for ${aid}`);
16267
+ existing.cert = certPem2;
16268
+ this._assertCertMatchesLocalKeypair(existing);
16269
+ await this._persistIdentity(existing);
16270
+ this._logger.debug(`registerAid exit (recovered): elapsed=${Date.now() - tStart}ms aid=${aid}`);
16271
+ return {
16272
+ aid,
16273
+ cert: certPem2,
16274
+ private_key_pem: String(existing.private_key_pem),
16275
+ public_key_der_b64: localPubB64,
16276
+ curve: String(existing.curve ?? "P-256")
16277
+ };
16278
+ }
16279
+ }
16280
+ const recovered = await this._tryRecoverPendingRegistration(gatewayUrl, aid);
16281
+ if (recovered !== null) {
16282
+ this._logger.info(`registerAid recovered from pending: aid=${aid}`);
16283
+ return recovered;
16284
+ }
16285
+ const existingCert = await this._downloadRegisteredCert(gatewayUrl, aid);
16286
+ if (existingCert) {
16287
+ throw new IdentityConflictError(
16288
+ `AID '${aid}' is already registered on server. Choose a different name, or if you own the keypair use a recovery flow.`
16289
+ );
16290
+ }
16291
+ const identity = await this._crypto.generateIdentity();
16292
+ identity.aid = aid;
16293
+ const pendingStore = this._pendingStore();
16294
+ const pendingHandle = await pendingStore.pendingIdentityDir(aid);
16295
+ await pendingStore.savePendingKeyPair(pendingHandle, aid, identity);
16296
+ let created;
16297
+ try {
16298
+ created = await this._createAid(gatewayUrl, identity);
16299
+ } catch (e) {
16300
+ this._logger.warn(`registerAid RPC failed (pending kept for recovery): aid=${aid}, pending=${pendingHandle}, error=${e instanceof Error ? e.message : String(e)}`);
16301
+ throw e;
16302
+ }
16303
+ const certPem = String(created.cert ?? "");
16304
+ if (!certPem) throw new AuthError(`registerAid: server response missing cert for ${aid}`);
16305
+ identity.cert = certPem;
16306
+ this._assertCertMatchesLocalKeypair(identity);
16307
+ await pendingStore.savePendingCert(pendingHandle, certPem);
16308
+ try {
16309
+ await pendingStore.promotePendingIdentity(pendingHandle, aid);
16310
+ } catch (e) {
16311
+ throw new IdentityConflictError(
16312
+ `AID '${aid}' was created by another process during registration; pending record kept for cleanup.`
16313
+ );
16314
+ }
16315
+ await this._persistIdentity(identity);
16316
+ this._logger.debug(`registerAid exit: elapsed=${Date.now() - tStart}ms aid=${aid}`);
16317
+ return {
16318
+ aid,
16319
+ cert: certPem,
16320
+ private_key_pem: String(identity.private_key_pem ?? ""),
16321
+ public_key_der_b64: String(identity.public_key_der_b64 ?? ""),
16322
+ curve: String(identity.curve ?? "P-256")
16323
+ };
16324
+ } catch (err) {
16325
+ this._logger.debug(`registerAid exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
16326
+ throw err;
16327
+ }
16328
+ }
16329
+ _pendingStore() {
16330
+ const store = this._keystore;
16331
+ for (const name of [
16332
+ "pendingIdentityDir",
16333
+ "listPendingIdentityDirs",
16334
+ "savePendingKeyPair",
16335
+ "loadPendingKeyPair",
16336
+ "savePendingCert",
16337
+ "promotePendingIdentity"
16338
+ ]) {
16339
+ if (typeof store[name] !== "function") {
16340
+ throw new AuthError(`keystore does not support pending registration: ${name}`);
16341
+ }
16342
+ }
16343
+ return store;
16344
+ }
16345
+ async _tryRecoverPendingRegistration(gatewayUrl, aid) {
16346
+ const pendingStore = this._pendingStore();
16347
+ const handles = await pendingStore.listPendingIdentityDirs(aid);
16348
+ for (const handle of handles) {
16349
+ let keyPair;
16350
+ try {
16351
+ keyPair = await pendingStore.loadPendingKeyPair(handle, aid);
16352
+ } catch (exc) {
16353
+ this._logger.warn(`pending identity keypair load failed; keeping pending for retry: aid=${aid}, pending=${handle}, error=${exc instanceof Error ? exc.message : String(exc)}`);
16354
+ throw exc;
16355
+ }
16356
+ const privateKeyPem = String(keyPair?.private_key_pem ?? "");
16357
+ const publicKeyDerB642 = String(keyPair?.public_key_der_b64 ?? "");
16358
+ if (!privateKeyPem || !publicKeyDerB642) {
16359
+ await pendingStore.discardPendingIdentity?.(handle);
16360
+ continue;
16361
+ }
16362
+ const serverCertPem = await this._downloadRegisteredCert(gatewayUrl, aid);
16363
+ if (!serverCertPem) {
16364
+ this._logger.info(`pending record found but server has no registration; cleaning up: ${handle}`);
16365
+ await pendingStore.discardPendingIdentity?.(handle);
16366
+ return null;
16367
+ }
16368
+ const serverPubB64 = _extractSpkiB64FromPem(serverCertPem);
16369
+ if (serverPubB64 !== publicKeyDerB642) {
16370
+ await pendingStore.discardPendingIdentity?.(handle);
16371
+ throw new IdentityConflictError(
16372
+ `AID '${aid}' has been registered by another party while local pending registration was incomplete; local pending key discarded.`
16373
+ );
16374
+ }
16375
+ const identity = {
16376
+ aid,
16377
+ cert: serverCertPem,
16378
+ private_key_pem: privateKeyPem,
16379
+ public_key_der_b64: publicKeyDerB642,
16380
+ curve: String(keyPair?.curve ?? "P-256")
16381
+ };
16382
+ await pendingStore.savePendingKeyPair(handle, aid, identity);
16383
+ await pendingStore.savePendingCert(handle, serverCertPem);
16384
+ try {
16385
+ await pendingStore.promotePendingIdentity(handle, aid);
16386
+ } catch (e) {
16387
+ throw new IdentityConflictError(
16388
+ `AID '${aid}' was created by another process during recovery; pending record kept for cleanup.`
16389
+ );
16390
+ }
16391
+ await this._persistIdentity(identity);
16392
+ return {
16393
+ aid,
16394
+ cert: serverCertPem,
16395
+ private_key_pem: privateKeyPem,
16396
+ public_key_der_b64: publicKeyDerB642,
16397
+ curve: String(keyPair?.curve ?? "P-256")
16398
+ };
16399
+ }
16400
+ return null;
16401
+ }
16402
+ async _downloadRegisteredCert(gatewayUrl, aid) {
16403
+ const certUrl = _gatewayHttpUrl(gatewayUrl, `/pki/cert/${aid}`);
16404
+ const controller = new AbortController();
16405
+ const timer = setTimeout(() => controller.abort(), 5e3);
16406
+ try {
16407
+ const resp = await fetch(certUrl, { signal: controller.signal });
16408
+ if (!resp.ok) return null;
16409
+ const certPem = await resp.text();
16410
+ if (!certPem || !certPem.includes("BEGIN CERTIFICATE")) return null;
16411
+ return certPem;
16412
+ } catch {
16413
+ return null;
16414
+ } finally {
16415
+ clearTimeout(timer);
16416
+ }
16417
+ }
16418
+ async _createAid(gatewayUrl, identity) {
16419
+ const response = await this._shortRpc(gatewayUrl, "auth.create_aid", {
16420
+ aid: identity.aid,
16421
+ public_key: identity.public_key_der_b64,
16422
+ curve: identity.curve ?? "P-256"
16423
+ });
16424
+ return { cert: response.cert };
16425
+ }
16426
+ _shortRpc(gatewayUrl, method, params) {
16427
+ return new Promise((resolve, reject) => {
16428
+ let ws;
16429
+ try {
16430
+ ws = new WebSocket(gatewayUrl);
16431
+ } catch {
16432
+ reject(new AuthError(`WebSocket \u8FDE\u63A5\u5931\u8D25: ${gatewayUrl}`));
16433
+ return;
16434
+ }
16435
+ let receivedChallenge = false;
16436
+ const timeout = globalThis.setTimeout(() => {
16437
+ try {
16438
+ ws.close();
16439
+ } catch {
16440
+ }
16441
+ reject(new AuthError(`shortRpc \u8D85\u65F6: ${method}`));
16442
+ }, 1e4);
16443
+ ws.onerror = () => {
16444
+ globalThis.clearTimeout(timeout);
16445
+ reject(new AuthError(`WebSocket \u8FDE\u63A5\u9519\u8BEF: ${gatewayUrl}`));
16446
+ };
16447
+ ws.onmessage = (event) => {
16448
+ try {
16449
+ const msg = typeof event.data === "string" ? JSON.parse(event.data) : event.data;
16450
+ if (!receivedChallenge) {
16451
+ receivedChallenge = true;
16452
+ ws.send(JSON.stringify({ jsonrpc: "2.0", id: `pre-${method}`, method, params }));
16453
+ return;
16454
+ }
16455
+ globalThis.clearTimeout(timeout);
16456
+ try {
16457
+ ws.close();
16458
+ } catch {
16459
+ }
16460
+ if (msg.error) {
16461
+ reject(mapRemoteError(msg.error));
16462
+ return;
16463
+ }
16464
+ const result = msg.result;
16465
+ if (!isJsonObject(result)) {
16466
+ reject(new ValidationError(`invalid pre-auth response for ${method}`));
16467
+ return;
16468
+ }
16469
+ if (result.success === false) {
16470
+ reject(new AuthError(String(result.error ?? `${method} failed`)));
16471
+ return;
16472
+ }
16473
+ resolve(result);
16474
+ } catch (e) {
16475
+ globalThis.clearTimeout(timeout);
16476
+ try {
16477
+ ws.close();
16478
+ } catch {
16479
+ }
16480
+ reject(e instanceof Error ? e : new AuthError(String(e)));
16481
+ }
16482
+ };
16483
+ });
16484
+ }
16485
+ _assertCertMatchesLocalKeypair(identity) {
16486
+ const aid = identity.aid ?? "?";
16487
+ const certPem = identity.cert;
16488
+ const localPubB64 = identity.public_key_der_b64;
16489
+ if (!certPem || !localPubB64) {
16490
+ throw new AuthError(`identity for aid ${aid} missing cert or public key`);
16491
+ }
16492
+ const certPubB64 = _extractSpkiB64FromPem(certPem);
16493
+ if (certPubB64 !== localPubB64) {
16494
+ throw new AuthError(`local certificate public key does not match local keypair for aid ${aid}`);
16495
+ }
16496
+ }
16497
+ async _persistIdentity(identity) {
16498
+ const aid = String(identity.aid ?? "");
16499
+ if (!aid) return;
16500
+ const certPem = String(identity.cert ?? "");
16501
+ if (certPem) await this._keystore.saveCert(aid, certPem);
16502
+ }
16503
+ };
16504
+
16505
+ // src/aid-store.ts
16089
16506
  function _derReadLength(data, offset) {
16090
16507
  if (offset >= data.length) return null;
16091
16508
  const first = data[offset];
@@ -16311,6 +16728,7 @@ var AIDStore = class {
16311
16728
  __publicField(this, "_encryptionSeed");
16312
16729
  __publicField(this, "_keystore");
16313
16730
  __publicField(this, "_auth");
16731
+ __publicField(this, "_registerFlow");
16314
16732
  __publicField(this, "_crypto");
16315
16733
  __publicField(this, "_discovery");
16316
16734
  __publicField(this, "_verifySsl");
@@ -16328,13 +16746,18 @@ var AIDStore = class {
16328
16746
  this._crypto = new CryptoProvider();
16329
16747
  this._discovery = new GatewayDiscovery();
16330
16748
  this._auth = new AuthFlow({
16331
- keystore: this._keystore,
16749
+ tokenStore: this._keystore,
16332
16750
  crypto: this._crypto,
16333
16751
  deviceId: this.deviceId,
16334
16752
  slotId: this.slotId,
16335
16753
  rootCaPem: opts.rootCaPem ?? null,
16336
16754
  verifySsl: this._verifySsl
16337
16755
  });
16756
+ this._registerFlow = new RegisterFlow({
16757
+ keystore: this._keystore,
16758
+ crypto: this._crypto,
16759
+ verifySsl: this._verifySsl
16760
+ });
16338
16761
  }
16339
16762
  close() {
16340
16763
  const close = this._keystore.close;
@@ -16453,7 +16876,17 @@ var AIDStore = class {
16453
16876
  try {
16454
16877
  validateRegisterAidName(target);
16455
16878
  const gatewayUrl = await this._resolveGateway(target);
16456
- await this._auth.registerAid(gatewayUrl, target);
16879
+ const result = await this._registerFlow.registerAid(gatewayUrl, target);
16880
+ if (result.cert) {
16881
+ await this._keystore.saveCert(target, result.cert);
16882
+ }
16883
+ if (result.private_key_pem || result.public_key_der_b64) {
16884
+ await this._keystore.saveKeyPair(target, {
16885
+ private_key_pem: result.private_key_pem,
16886
+ public_key_der_b64: result.public_key_der_b64,
16887
+ curve: result.curve
16888
+ });
16889
+ }
16457
16890
  return resultOk({ registered: true });
16458
16891
  } catch (exc) {
16459
16892
  if (exc instanceof IdentityConflictError) {
@@ -16656,18 +17089,18 @@ var AIDStore = class {
16656
17089
  return resultErr(PRIVATE_KEY_REQUIRED, `private key required for aid: ${target}`);
16657
17090
  }
16658
17091
  try {
16659
- const identity = await this._auth.loadIdentityOrNone(target);
16660
- if (!identity?.cert || !identity.private_key_pem) {
17092
+ const aidObj = loaded.data.aid;
17093
+ if (!aidObj.certPem || !aidObj.privateKeyPem) {
16661
17094
  return resultErr(PRIVATE_KEY_REQUIRED, `private key required for aid: ${target}`);
16662
17095
  }
16663
17096
  const gatewayUrl = await this._resolveGateway(target);
16664
17097
  const clientNonce = this._crypto.newClientNonce();
16665
17098
  const phase1 = await this._auth._shortRpc(gatewayUrl, "auth.aid_login1", {
16666
17099
  aid: target,
16667
- cert: identity.cert,
17100
+ cert: aidObj.certPem,
16668
17101
  client_nonce: clientNonce
16669
17102
  });
16670
- const [signature, clientTime] = await this._crypto.signLoginNonce(identity.private_key_pem, String(phase1.nonce ?? ""));
17103
+ const [signature, clientTime] = await this._crypto.signLoginNonce(aidObj.privateKeyPem, String(phase1.nonce ?? ""));
16671
17104
  const response = await this._auth._shortRpc(gatewayUrl, "auth.renew_cert", {
16672
17105
  aid: target,
16673
17106
  request_id: String(phase1.request_id ?? ""),
@@ -16696,8 +17129,8 @@ var AIDStore = class {
16696
17129
  return resultErr(PRIVATE_KEY_REQUIRED, `private key required for aid: ${target}`);
16697
17130
  }
16698
17131
  try {
16699
- const identity = await this._auth.loadIdentityOrNone(target);
16700
- if (!identity?.cert || !identity.private_key_pem) {
17132
+ const oldAid = loaded.data.aid;
17133
+ if (!oldAid.certPem || !oldAid.privateKeyPem) {
16701
17134
  return resultErr(PRIVATE_KEY_REQUIRED, `private key required for aid: ${target}`);
16702
17135
  }
16703
17136
  const gatewayUrl = await this._resolveGateway(target);
@@ -16705,7 +17138,7 @@ var AIDStore = class {
16705
17138
  const clientNonce = this._crypto.newClientNonce();
16706
17139
  const phase1 = await this._auth._shortRpc(gatewayUrl, "auth.aid_login1", {
16707
17140
  aid: target,
16708
- cert: identity.cert,
17141
+ cert: oldAid.certPem,
16709
17142
  client_nonce: clientNonce
16710
17143
  });
16711
17144
  const signPayload = `${String(phase1.nonce ?? "")}${newIdentity.public_key_der_b64}`;
@@ -16886,6 +17319,7 @@ export {
16886
17319
  ROOT_CA_PEM,
16887
17320
  RPCTransport,
16888
17321
  RateLimitError,
17322
+ RegisterFlow,
16889
17323
  STATE_PREFIX,
16890
17324
  SeedMigrationError,
16891
17325
  SerializationError,