@agentunion/fastaun-browser 0.2.13

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 (82) hide show
  1. package/README.md +604 -0
  2. package/dist/auth.d.ts +150 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +1388 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/certs/root.d.ts +2 -0
  7. package/dist/certs/root.d.ts.map +1 -0
  8. package/dist/certs/root.js +16 -0
  9. package/dist/certs/root.js.map +1 -0
  10. package/dist/client.d.ts +341 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +4061 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/config.d.ts +37 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +85 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/crypto.d.ts +41 -0
  19. package/dist/crypto.d.ts.map +1 -0
  20. package/dist/crypto.js +132 -0
  21. package/dist/crypto.js.map +1 -0
  22. package/dist/discovery.d.ts +20 -0
  23. package/dist/discovery.d.ts.map +1 -0
  24. package/dist/discovery.js +75 -0
  25. package/dist/discovery.js.map +1 -0
  26. package/dist/e2ee-group.d.ts +221 -0
  27. package/dist/e2ee-group.d.ts.map +1 -0
  28. package/dist/e2ee-group.js +1174 -0
  29. package/dist/e2ee-group.js.map +1 -0
  30. package/dist/e2ee.d.ts +187 -0
  31. package/dist/e2ee.d.ts.map +1 -0
  32. package/dist/e2ee.js +1067 -0
  33. package/dist/e2ee.js.map +1 -0
  34. package/dist/errors.d.ts +118 -0
  35. package/dist/errors.d.ts.map +1 -0
  36. package/dist/errors.js +250 -0
  37. package/dist/errors.js.map +1 -0
  38. package/dist/events.d.ts +33 -0
  39. package/dist/events.d.ts.map +1 -0
  40. package/dist/events.js +68 -0
  41. package/dist/events.js.map +1 -0
  42. package/dist/index.d.ts +22 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +32 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/keystore/index.d.ts +88 -0
  47. package/dist/keystore/index.d.ts.map +1 -0
  48. package/dist/keystore/index.js +3 -0
  49. package/dist/keystore/index.js.map +1 -0
  50. package/dist/keystore/indexeddb.d.ts +94 -0
  51. package/dist/keystore/indexeddb.d.ts.map +1 -0
  52. package/dist/keystore/indexeddb.js +1434 -0
  53. package/dist/keystore/indexeddb.js.map +1 -0
  54. package/dist/namespaces/auth.d.ts +52 -0
  55. package/dist/namespaces/auth.d.ts.map +1 -0
  56. package/dist/namespaces/auth.js +237 -0
  57. package/dist/namespaces/auth.js.map +1 -0
  58. package/dist/namespaces/custody.d.ts +48 -0
  59. package/dist/namespaces/custody.d.ts.map +1 -0
  60. package/dist/namespaces/custody.js +230 -0
  61. package/dist/namespaces/custody.js.map +1 -0
  62. package/dist/secret-store/index.d.ts +20 -0
  63. package/dist/secret-store/index.d.ts.map +1 -0
  64. package/dist/secret-store/index.js +12 -0
  65. package/dist/secret-store/index.js.map +1 -0
  66. package/dist/secret-store/indexeddb-store.d.ts +22 -0
  67. package/dist/secret-store/indexeddb-store.d.ts.map +1 -0
  68. package/dist/secret-store/indexeddb-store.js +133 -0
  69. package/dist/secret-store/indexeddb-store.js.map +1 -0
  70. package/dist/seq-tracker.d.ts +30 -0
  71. package/dist/seq-tracker.d.ts.map +1 -0
  72. package/dist/seq-tracker.js +219 -0
  73. package/dist/seq-tracker.js.map +1 -0
  74. package/dist/transport.d.ts +45 -0
  75. package/dist/transport.d.ts.map +1 -0
  76. package/dist/transport.js +251 -0
  77. package/dist/transport.js.map +1 -0
  78. package/dist/types.d.ts +171 -0
  79. package/dist/types.d.ts.map +1 -0
  80. package/dist/types.js +10 -0
  81. package/dist/types.js.map +1 -0
  82. package/package.json +37 -0
@@ -0,0 +1,230 @@
1
+ import { AUNError, ValidationError } from '../errors.js';
2
+ import { isJsonObject } from '../types.js';
3
+ const CUSTODY_HTTP_TIMEOUT_MS = 30_000;
4
+ function issuerDomainFromAid(aid) {
5
+ const parts = String(aid || '').trim().split('.', 2);
6
+ return parts.length > 1 ? parts[1] : parts[0] || '';
7
+ }
8
+ function custodyWellKnownUrls(aid, discoveryPort, verifySsl) {
9
+ const portSuffix = discoveryPort ? `:${discoveryPort}` : '';
10
+ const issuerDomain = issuerDomainFromAid(aid);
11
+ const aidUrl = `https://${aid}${portSuffix}/.well-known/aun-custody`;
12
+ const fallbackUrl = `https://aid_custody.${issuerDomain}${portSuffix}/.well-known/aun-custody`;
13
+ const urls = verifySsl ? [aidUrl, fallbackUrl] : [fallbackUrl, aidUrl];
14
+ return [...new Set(urls)];
15
+ }
16
+ function extractCustodyUrl(payload) {
17
+ for (const key of ['custody_url', 'custodyUrl', 'url']) {
18
+ const value = String(payload[key] ?? '').trim();
19
+ if (value)
20
+ return value;
21
+ }
22
+ if (isJsonObject(payload.custody)) {
23
+ const value = String(payload.custody.url ?? '').trim();
24
+ if (value)
25
+ return value;
26
+ }
27
+ for (const key of ['custody_services', 'custodyServices', 'services']) {
28
+ const items = payload[key];
29
+ if (Array.isArray(items)) {
30
+ const candidates = items
31
+ .filter(isJsonObject)
32
+ .sort((a, b) => Number(a.priority ?? 999) - Number(b.priority ?? 999));
33
+ for (const item of candidates) {
34
+ const value = String(item.url ?? '').trim();
35
+ if (value)
36
+ return value;
37
+ }
38
+ }
39
+ }
40
+ throw new ValidationError('custody well-known missing custody url');
41
+ }
42
+ function normalizeCustodyUrl(url) {
43
+ const value = String(url ?? '').trim().replace(/\/+$/, '');
44
+ if (!value)
45
+ return null;
46
+ try {
47
+ const parsed = new URL(value);
48
+ if ((parsed.protocol !== 'http:' && parsed.protocol !== 'https:') || !parsed.hostname) {
49
+ return null;
50
+ }
51
+ return value;
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ async function fetchJsonWithTimeout(input, init, timeoutMs = CUSTODY_HTTP_TIMEOUT_MS) {
58
+ const controller = new AbortController();
59
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
60
+ try {
61
+ const response = await fetch(input, { ...init, signal: controller.signal });
62
+ const payload = await response.json();
63
+ if (response.ok) {
64
+ return payload;
65
+ }
66
+ const error = isJsonObject(payload) && isJsonObject(payload.error) ? payload.error : null;
67
+ const code = String(error?.code ?? '');
68
+ const message = String(error?.message ?? '');
69
+ throw new AUNError(message ? `custody ${code || response.status}: ${message}` : `custody HTTP ${response.status}`);
70
+ }
71
+ catch (error) {
72
+ if (controller.signal.aborted) {
73
+ throw new AUNError(`custody request timed out after ${timeoutMs}ms`);
74
+ }
75
+ throw error;
76
+ }
77
+ finally {
78
+ clearTimeout(timer);
79
+ }
80
+ }
81
+ export class CustodyNamespace {
82
+ _client;
83
+ _custodyUrl = '';
84
+ constructor(client) {
85
+ this._client = client;
86
+ }
87
+ get _internal() {
88
+ return this._client;
89
+ }
90
+ setUrl(url) {
91
+ this._custodyUrl = String(url ?? '').trim().replace(/\/+$/, '');
92
+ }
93
+ configureUrl(url) {
94
+ this.setUrl(url);
95
+ }
96
+ async discoverUrl(params = {}) {
97
+ const aid = String(params.aid ?? this._client.aid ?? '').trim();
98
+ if (!aid) {
99
+ throw new ValidationError('custody.discoverUrl requires aid or authenticated client');
100
+ }
101
+ let lastError = null;
102
+ const urls = custodyWellKnownUrls(aid, this._client.configModel.discoveryPort, this._client.configModel.verifySsl);
103
+ for (const wellKnownUrl of urls) {
104
+ try {
105
+ const payload = await fetchJsonWithTimeout(wellKnownUrl, { method: 'GET' }, params.timeout ?? 5_000);
106
+ if (!isJsonObject(payload)) {
107
+ throw new ValidationError('custody well-known returned invalid payload');
108
+ }
109
+ const custodyUrl = normalizeCustodyUrl(extractCustodyUrl(payload));
110
+ if (!custodyUrl) {
111
+ throw new ValidationError('custody well-known returned invalid custody url');
112
+ }
113
+ this._custodyUrl = custodyUrl;
114
+ return custodyUrl;
115
+ }
116
+ catch (error) {
117
+ lastError = error;
118
+ }
119
+ }
120
+ throw new AUNError(`custody discovery failed for ${aid}: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
121
+ }
122
+ async _resolveCustodyUrl(aid) {
123
+ const custodyUrl = normalizeCustodyUrl(this._custodyUrl);
124
+ if (custodyUrl) {
125
+ if (custodyUrl !== this._custodyUrl) {
126
+ this._custodyUrl = custodyUrl;
127
+ }
128
+ return custodyUrl;
129
+ }
130
+ return this.discoverUrl({ aid });
131
+ }
132
+ _getAccessToken() {
133
+ const identity = this._internal._identity;
134
+ if (identity) {
135
+ const token = String(identity.access_token ?? '').trim();
136
+ if (token)
137
+ return token;
138
+ }
139
+ throw new ValidationError('no access_token available: call auth.authenticate() first');
140
+ }
141
+ async _post(path, body, opts = {}) {
142
+ const headers = { 'Content-Type': 'application/json' };
143
+ const token = String(opts.token ?? '').trim();
144
+ if (token) {
145
+ headers.Authorization = `Bearer ${token}`;
146
+ }
147
+ const payload = await fetchJsonWithTimeout(`${await this._resolveCustodyUrl(String(body.aid ?? '') || this._client.aid)}${path}`, {
148
+ method: 'POST',
149
+ headers,
150
+ body: JSON.stringify(body),
151
+ });
152
+ if (!isJsonObject(payload)) {
153
+ throw new AUNError('custody returned invalid JSON payload');
154
+ }
155
+ return payload;
156
+ }
157
+ async sendCode(params) {
158
+ const phone = String(params.phone ?? '').trim();
159
+ const aid = String(params.aid ?? '').trim();
160
+ if (!phone) {
161
+ throw new ValidationError('custody.sendCode requires non-empty phone');
162
+ }
163
+ const body = { phone };
164
+ let token = null;
165
+ if (aid) {
166
+ body.aid = aid;
167
+ }
168
+ else {
169
+ token = this._getAccessToken();
170
+ }
171
+ return this._post('/custody/accounts/send-code', body, { token });
172
+ }
173
+ async bindPhone(params) {
174
+ const phone = String(params.phone ?? '').trim();
175
+ const code = String(params.code ?? '').trim();
176
+ const cert = String(params.cert ?? '').trim();
177
+ const key = String(params.key ?? '').trim();
178
+ if (!phone || !code || !cert || !key) {
179
+ throw new ValidationError('custody.bindPhone requires phone, code, cert and key');
180
+ }
181
+ const body = { phone, code, cert, key };
182
+ if (params.metadata && isJsonObject(params.metadata)) {
183
+ body.metadata = params.metadata;
184
+ }
185
+ return this._post('/custody/accounts/bind-phone', body, {
186
+ token: this._getAccessToken(),
187
+ });
188
+ }
189
+ async restorePhone(params) {
190
+ const phone = String(params.phone ?? '').trim();
191
+ const code = String(params.code ?? '').trim();
192
+ const aid = String(params.aid ?? '').trim();
193
+ if (!phone || !code || !aid) {
194
+ throw new ValidationError('custody.restorePhone requires phone, code and aid');
195
+ }
196
+ return this._post('/custody/accounts/restore-phone', { phone, code, aid });
197
+ }
198
+ async createDeviceCopy(params = {}) {
199
+ const aid = String(params.aid ?? this._client.aid ?? '').trim();
200
+ if (!aid) {
201
+ throw new ValidationError('custody.createDeviceCopy requires aid or authenticated client');
202
+ }
203
+ return this._post('/custody/transfers', { aid }, { token: this._getAccessToken() });
204
+ }
205
+ async uploadDeviceCopyMaterials(params) {
206
+ const transferCode = String(params.transferCode ?? '').trim();
207
+ const aid = String(params.aid ?? this._client.aid ?? '').trim();
208
+ const cert = String(params.cert ?? '').trim();
209
+ const key = String(params.key ?? '').trim();
210
+ if (!transferCode || !aid || !cert || !key) {
211
+ throw new ValidationError('custody.uploadDeviceCopyMaterials requires transferCode, aid, cert and key');
212
+ }
213
+ const body = { aid, cert, key };
214
+ if (params.metadata && isJsonObject(params.metadata)) {
215
+ body.metadata = params.metadata;
216
+ }
217
+ return this._post(`/custody/transfers/${encodeURIComponent(transferCode)}/materials`, body, {
218
+ token: this._getAccessToken(),
219
+ });
220
+ }
221
+ async claimDeviceCopy(params) {
222
+ const aid = String(params.aid ?? '').trim();
223
+ const transferCode = String(params.transferCode ?? '').trim();
224
+ if (!aid || !transferCode) {
225
+ throw new ValidationError('custody.claimDeviceCopy requires aid and transferCode');
226
+ }
227
+ return this._post('/custody/transfers/claim', { aid, transfer_code: transferCode });
228
+ }
229
+ }
230
+ //# sourceMappingURL=custody.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custody.js","sourceRoot":"","sources":["../../src/namespaces/custody.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { SecretRecord } from '../types.js';
2
+ /**
3
+ * 密钥保护存储接口。
4
+ *
5
+ * 浏览器环境下所有方法均为异步(SubtleCrypto / IndexedDB 要求),
6
+ * 与 Python SDK 的同步接口不同。
7
+ */
8
+ export interface SecretStore {
9
+ /** 保护(加密)敏感数据 */
10
+ protect(scope: string, name: string, plaintext: Uint8Array): Promise<SecretRecord>;
11
+ /** 还原(解密)敏感数据 */
12
+ reveal(scope: string, name: string, record: SecretRecord): Promise<Uint8Array | null>;
13
+ }
14
+ /**
15
+ * 创建默认 SecretStore 实例。
16
+ *
17
+ * 浏览器环境下使用 IndexedDBSecretStore(基于 PBKDF2 + AES-256-GCM)。
18
+ */
19
+ export declare function createDefaultSecretStore(encryptionSeed?: string | null): Promise<SecretStore>;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/secret-store/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,iBAAiB;IACjB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnF,iBAAiB;IACjB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CACvF;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC7B,OAAO,CAAC,WAAW,CAAC,CAItB"}
@@ -0,0 +1,12 @@
1
+ // ── SecretStore 接口定义(浏览器版 — 全异步)──────────────
2
+ /**
3
+ * 创建默认 SecretStore 实例。
4
+ *
5
+ * 浏览器环境下使用 IndexedDBSecretStore(基于 PBKDF2 + AES-256-GCM)。
6
+ */
7
+ export async function createDefaultSecretStore(encryptionSeed) {
8
+ // 延迟导入,避免循环依赖
9
+ const { IndexedDBSecretStore } = await import('./indexeddb-store.js');
10
+ return new IndexedDBSecretStore(encryptionSeed ?? undefined);
11
+ }
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/secret-store/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAiBhD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,cAA8B;IAE9B,cAAc;IACd,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IACtE,OAAO,IAAI,oBAAoB,CAAC,cAAc,IAAI,SAAS,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { SecretStore } from './index.js';
2
+ import type { SecretRecord } from '../types.js';
3
+ /**
4
+ * 基于 IndexedDB + SubtleCrypto 的 SecretStore。
5
+ *
6
+ * 使用 PBKDF2 从种子派生主密钥,AES-256-GCM 加解密。
7
+ * 主密钥存储在 IndexedDB 的 'master' 仓库中(首次自动生成)。
8
+ */
9
+ export declare class IndexedDBSecretStore implements SecretStore {
10
+ private _encryptionSeed;
11
+ private _masterKeyPromise;
12
+ constructor(encryptionSeed?: string);
13
+ /** 获取或生成主密钥(惰性初始化,只初始化一次) */
14
+ private _getMasterKey;
15
+ private _initMasterKey;
16
+ private _deriveKeyFromSeed;
17
+ /** 加密并存储 */
18
+ protect(scope: string, name: string, plaintext: Uint8Array): Promise<SecretRecord>;
19
+ /** 解密还原 */
20
+ reveal(scope: string, name: string, record: SecretRecord): Promise<Uint8Array | null>;
21
+ }
22
+ //# sourceMappingURL=indexeddb-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-store.d.ts","sourceRoot":"","sources":["../../src/secret-store/indexeddb-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmDhD;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,iBAAiB,CAAmC;gBAEhD,cAAc,CAAC,EAAE,MAAM;IAInC,6BAA6B;IAC7B,OAAO,CAAC,aAAa;YAOP,cAAc;YAoBd,kBAAkB;IAwBhC,YAAY;IACN,OAAO,CACX,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,YAAY,CAAC;IAyBxB,WAAW;IACL,MAAM,CACV,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAwB9B"}
@@ -0,0 +1,133 @@
1
+ // ── IndexedDB SecretStore 实现 ──────────────────────────
2
+ import { uint8ToBase64, base64ToUint8, toBufferSource } from '../crypto.js';
3
+ const SECRET_DB_NAME = 'aun-secret-store';
4
+ const SECRET_DB_VERSION = 1;
5
+ const STORE_SECRETS = 'secrets';
6
+ const STORE_MASTER = 'master';
7
+ /** 打开 secret store 数据库 */
8
+ function openSecretDB() {
9
+ return new Promise((resolve, reject) => {
10
+ const request = indexedDB.open(SECRET_DB_NAME, SECRET_DB_VERSION);
11
+ request.onupgradeneeded = () => {
12
+ const db = request.result;
13
+ if (!db.objectStoreNames.contains(STORE_SECRETS)) {
14
+ db.createObjectStore(STORE_SECRETS);
15
+ }
16
+ if (!db.objectStoreNames.contains(STORE_MASTER)) {
17
+ db.createObjectStore(STORE_MASTER);
18
+ }
19
+ };
20
+ request.onsuccess = () => resolve(request.result);
21
+ request.onerror = () => reject(request.error);
22
+ });
23
+ }
24
+ /** 读取 */
25
+ async function secretGet(storeName, key) {
26
+ const db = await openSecretDB();
27
+ return new Promise((resolve, reject) => {
28
+ const tx = db.transaction(storeName, 'readonly');
29
+ const store = tx.objectStore(storeName);
30
+ const req = store.get(key);
31
+ req.onsuccess = () => resolve(req.result ?? null);
32
+ req.onerror = () => reject(req.error);
33
+ tx.oncomplete = () => db.close();
34
+ });
35
+ }
36
+ /** 写入 */
37
+ async function secretPut(storeName, key, value) {
38
+ const db = await openSecretDB();
39
+ return new Promise((resolve, reject) => {
40
+ const tx = db.transaction(storeName, 'readwrite');
41
+ const store = tx.objectStore(storeName);
42
+ const req = store.put(value, key);
43
+ req.onsuccess = () => resolve();
44
+ req.onerror = () => reject(req.error);
45
+ tx.oncomplete = () => db.close();
46
+ });
47
+ }
48
+ /**
49
+ * 基于 IndexedDB + SubtleCrypto 的 SecretStore。
50
+ *
51
+ * 使用 PBKDF2 从种子派生主密钥,AES-256-GCM 加解密。
52
+ * 主密钥存储在 IndexedDB 的 'master' 仓库中(首次自动生成)。
53
+ */
54
+ export class IndexedDBSecretStore {
55
+ _encryptionSeed;
56
+ _masterKeyPromise = null;
57
+ constructor(encryptionSeed) {
58
+ this._encryptionSeed = encryptionSeed;
59
+ }
60
+ /** 获取或生成主密钥(惰性初始化,只初始化一次) */
61
+ _getMasterKey() {
62
+ if (!this._masterKeyPromise) {
63
+ this._masterKeyPromise = this._initMasterKey();
64
+ }
65
+ return this._masterKeyPromise;
66
+ }
67
+ async _initMasterKey() {
68
+ // 如果提供了 encryptionSeed,通过 PBKDF2 派生
69
+ if (this._encryptionSeed) {
70
+ return this._deriveKeyFromSeed(this._encryptionSeed);
71
+ }
72
+ // 否则尝试从 IndexedDB 加载已有的种子
73
+ const storedSeed = await secretGet(STORE_MASTER, 'seed');
74
+ if (typeof storedSeed === 'string' && storedSeed) {
75
+ return this._deriveKeyFromSeed(storedSeed);
76
+ }
77
+ // 首次使用:生成随机种子并持久化
78
+ const seedBytes = new Uint8Array(32);
79
+ crypto.getRandomValues(seedBytes);
80
+ const seed = uint8ToBase64(seedBytes);
81
+ await secretPut(STORE_MASTER, 'seed', seed);
82
+ return this._deriveKeyFromSeed(seed);
83
+ }
84
+ async _deriveKeyFromSeed(seed) {
85
+ const encoder = new TextEncoder();
86
+ const keyMaterial = await crypto.subtle.importKey('raw', toBufferSource(encoder.encode(seed)), 'PBKDF2', false, ['deriveKey']);
87
+ return crypto.subtle.deriveKey({
88
+ name: 'PBKDF2',
89
+ salt: toBufferSource(encoder.encode('aun-secret-store-salt')),
90
+ iterations: 100000,
91
+ hash: 'SHA-256',
92
+ }, keyMaterial, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
93
+ }
94
+ /** 加密并存储 */
95
+ async protect(scope, name, plaintext) {
96
+ const masterKey = await this._getMasterKey();
97
+ const iv = new Uint8Array(12);
98
+ crypto.getRandomValues(iv);
99
+ const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: toBufferSource(iv) }, masterKey, toBufferSource(plaintext));
100
+ const record = {
101
+ scheme: 'indexeddb_aes_gcm',
102
+ name,
103
+ iv: uint8ToBase64(iv),
104
+ ciphertext: uint8ToBase64(new Uint8Array(ciphertext)),
105
+ persisted: true,
106
+ };
107
+ const storeKey = `${scope}:${name}`;
108
+ await secretPut(STORE_SECRETS, storeKey, record);
109
+ return record;
110
+ }
111
+ /** 解密还原 */
112
+ async reveal(scope, name, record) {
113
+ if (record.scheme !== 'indexeddb_aes_gcm')
114
+ return null;
115
+ if (String(record.name ?? '') !== name)
116
+ return null;
117
+ const ivB64 = record.iv;
118
+ const ctB64 = record.ciphertext;
119
+ if (!ivB64 || !ctB64)
120
+ return null;
121
+ try {
122
+ const masterKey = await this._getMasterKey();
123
+ const iv = base64ToUint8(ivB64);
124
+ const ciphertext = base64ToUint8(ctB64);
125
+ const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: toBufferSource(iv) }, masterKey, toBufferSource(ciphertext));
126
+ return new Uint8Array(plaintext);
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ }
133
+ //# sourceMappingURL=indexeddb-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexeddb-store.js","sourceRoot":"","sources":["../../src/secret-store/indexeddb-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { JsonObject } from './types.js';
2
+ export declare class SeqTracker {
3
+ private _trackers;
4
+ private _get;
5
+ getContiguousSeq(ns: string): number;
6
+ getMaxSeenSeq(ns: string): number;
7
+ /** S2: 从持久化(keystore 最近 ack seq)恢复 baseline,
8
+ * 以便首条 push 消息能构造 [baseline+1, seq-1] 的历史 gap。
9
+ * 必须在收到首条消息前调用。 */
10
+ setBaseline(ns: string, baselineSeq: number): void;
11
+ /** 记录收到的 seq,返回 true 表示需要 pull 补齐空洞 */
12
+ onMessageSeq(ns: string, seq: number): boolean;
13
+ /** pull 返回后更新 tracker 状态 */
14
+ onPullResult(ns: string, messages: JsonObject[]): void;
15
+ private _tryAdvance;
16
+ private _shouldProbe;
17
+ /** S2: 服务端明确告知某区间无消息(tombstone)→ 将 gap 标记为 resolved */
18
+ markGapResolvedByTombstone(ns: string, gapStart: number, gapEnd: number): void;
19
+ /** 删除指定命名空间的所有跟踪状态(群组解散时使用) */
20
+ removeNamespace(ns: string): void;
21
+ /** 强制跳过不连续区间,将 contiguousSeq 拨到指定位置。
22
+ * 当服务端返回 server_ack_seq 且本地 contiguousSeq 落后时调用,
23
+ * 跳过 [contiguousSeq, server_ack_seq) 这段不连续区间。 */
24
+ forceContiguousSeq(ns: string, seq: number): void;
25
+ /** 导出各命名空间的 contiguousSeq,用于持久化 */
26
+ exportState(): Record<string, number>;
27
+ /** 从持久化数据恢复各命名空间的 contiguousSeq */
28
+ restoreState(state: Record<string, number>): void;
29
+ }
30
+ //# sourceMappingURL=seq-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seq-tracker.d.ts","sourceRoot":"","sources":["../src/seq-tracker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA8B7C,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAwC;IAEzD,OAAO,CAAC,IAAI;IASZ,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAIpC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAIjC;;wBAEoB;IACpB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IASlD,uCAAuC;IACvC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAyD9C,4BAA4B;IAC5B,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI;IAoCtD,OAAO,CAAC,WAAW;IAoBnB,OAAO,CAAC,YAAY;IASpB,uDAAuD;IACvD,0BAA0B,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAU9E,+BAA+B;IAC/B,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIjC;;sDAEkD;IAClD,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAmBjD,mCAAmC;IACnC,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQrC,mCAAmC;IACnC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;CASlD"}