@invisible-labs/sdk 0.6.0-devnet.1

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 (54) hide show
  1. package/README.md +210 -0
  2. package/dist/chunk-7DSVN3MV.js +1145 -0
  3. package/dist/chunk-7DSVN3MV.js.map +1 -0
  4. package/dist/chunk-JNNVPZEU.js +599 -0
  5. package/dist/chunk-JNNVPZEU.js.map +1 -0
  6. package/dist/chunk-JRMKCE3S.js +50 -0
  7. package/dist/chunk-JRMKCE3S.js.map +1 -0
  8. package/dist/chunk-LBC7ALYO.js +3783 -0
  9. package/dist/chunk-LBC7ALYO.js.map +1 -0
  10. package/dist/chunk-NCY4FCYU.js +1911 -0
  11. package/dist/chunk-NCY4FCYU.js.map +1 -0
  12. package/dist/chunk-OHIM2YWU.js +126 -0
  13. package/dist/chunk-OHIM2YWU.js.map +1 -0
  14. package/dist/chunk-SZAYO2L5.js +123 -0
  15. package/dist/chunk-SZAYO2L5.js.map +1 -0
  16. package/dist/chunk-TQNNTV5F.js +17 -0
  17. package/dist/chunk-TQNNTV5F.js.map +1 -0
  18. package/dist/chunk-VR6T6OJS.js +24 -0
  19. package/dist/chunk-VR6T6OJS.js.map +1 -0
  20. package/dist/chunk-XUWBGET5.js +221 -0
  21. package/dist/chunk-XUWBGET5.js.map +1 -0
  22. package/dist/coordinator-7Y45MCCZ.js +4 -0
  23. package/dist/coordinator-7Y45MCCZ.js.map +1 -0
  24. package/dist/createSession-D3ym-Ira.d.ts +177 -0
  25. package/dist/dkgWorker.d.ts +2 -0
  26. package/dist/dkgWorker.js +61 -0
  27. package/dist/dkgWorker.js.map +1 -0
  28. package/dist/events.d.ts +54 -0
  29. package/dist/events.js +143 -0
  30. package/dist/events.js.map +1 -0
  31. package/dist/frostRuntime-JESDHN6O.js +4 -0
  32. package/dist/frostRuntime-JESDHN6O.js.map +1 -0
  33. package/dist/index.d.ts +499 -0
  34. package/dist/index.js +132 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/lp.d.ts +388 -0
  37. package/dist/lp.js +1711 -0
  38. package/dist/lp.js.map +1 -0
  39. package/dist/presets.d.ts +43 -0
  40. package/dist/presets.js +70 -0
  41. package/dist/presets.js.map +1 -0
  42. package/dist/session-DFuy54C-.d.ts +31 -0
  43. package/dist/stats.d.ts +47 -0
  44. package/dist/stats.js +21 -0
  45. package/dist/stats.js.map +1 -0
  46. package/dist/storage.d.ts +82 -0
  47. package/dist/storage.js +246 -0
  48. package/dist/storage.js.map +1 -0
  49. package/dist/types-ZhV7TIQY.d.ts +76 -0
  50. package/dist/types.generated-CHGSbmLp.d.ts +67 -0
  51. package/dist/user.d.ts +377 -0
  52. package/dist/user.js +1225 -0
  53. package/dist/user.js.map +1 -0
  54. package/package.json +82 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * `@invisible-labs/sdk/storage` - storage adapters (spec section 7).
3
+ *
4
+ * The SDK persists recoverable secrets (Recovery Code, LP Position Code, LP
5
+ * Refill Key, withdrawal secret) only through a {@link StorageAdapter}. The
6
+ * `memory`, `browser`, and `extension` adapters are real. Browser and
7
+ * extension adapters persist the bytes provided by the caller; callers that need
8
+ * encrypted-at-rest storage can wrap/encrypt bytes before calling `put`.
9
+ */
10
+ /**
11
+ * A namespaced key/value store for the SDK's recoverable secrets. Values are
12
+ * raw bytes. Callers may store plaintext bytes, pre-wrapped bytes, or encrypted
13
+ * bytes depending on their host product's storage model.
14
+ */
15
+ interface StorageAdapter {
16
+ /** Which backing the adapter uses. */
17
+ readonly kind: "browser" | "extension" | "server-hkdf" | "server-custom" | "memory";
18
+ put(namespace: string, key: string, value: Uint8Array): Promise<void>;
19
+ get(namespace: string, key: string): Promise<Uint8Array | null>;
20
+ list(namespace: string): Promise<string[]>;
21
+ remove(namespace: string, key: string): Promise<void>;
22
+ /** `server-hkdf` only: derive a secret from a stable domain context. */
23
+ derive?(namespace: string, context: string): Promise<Uint8Array>;
24
+ }
25
+ interface BrowserStorageOptions {
26
+ /** Override for tests or custom host environments. Defaults to `globalThis.localStorage`. */
27
+ readonly storage?: StorageLike;
28
+ }
29
+ interface ExtensionStorageOptions {
30
+ /** Override for tests or custom extension hosts. Defaults to chrome/browser storage local. */
31
+ readonly storage?: ExtensionStorageArea;
32
+ /** Override for tests or custom extension hosts. Defaults to chrome/browser runtime. */
33
+ readonly runtime?: ExtensionRuntimeLike;
34
+ /**
35
+ * Chrome exposes storage.local to content scripts by default. Keep the default
36
+ * trusted-context restriction when the host API supports it.
37
+ */
38
+ readonly restrictAccessToTrustedContexts?: boolean;
39
+ }
40
+ interface StorageLike {
41
+ readonly length: number;
42
+ key(index: number): string | null;
43
+ getItem(key: string): string | null;
44
+ setItem(key: string, value: string): void;
45
+ removeItem(key: string): void;
46
+ }
47
+ interface ExtensionStorageArea {
48
+ get(keys?: string | string[] | Record<string, unknown> | null, callback?: (items: Record<string, unknown>) => void): Promise<Record<string, unknown>> | void;
49
+ set(items: Record<string, string>, callback?: () => void): Promise<void> | void;
50
+ remove(keys: string | string[], callback?: () => void): Promise<void> | void;
51
+ setAccessLevel?(details: {
52
+ accessLevel: string;
53
+ }, callback?: () => void): Promise<void> | void;
54
+ }
55
+ interface ExtensionRuntimeLike {
56
+ readonly lastError?: {
57
+ readonly message?: string;
58
+ } | null;
59
+ }
60
+ /**
61
+ * In-memory adapter. Fully functional, unencrypted, non-persistent - intended
62
+ * for tests and ephemeral flows, never for real secrets at rest.
63
+ */
64
+ declare function inMemoryStorage(): StorageAdapter;
65
+ /**
66
+ * Browser `localStorage` adapter. Values are stored as base64url-encoded bytes.
67
+ * Encrypt or wrap the bytes before `put` if your product requires encrypted
68
+ * local persistence.
69
+ *
70
+ * @throws StorageError `STORAGE_NOT_AVAILABLE` if `localStorage` is unavailable.
71
+ */
72
+ declare function browserStorage(options?: BrowserStorageOptions): StorageAdapter;
73
+ /**
74
+ * Browser-extension (`chrome.storage.local` / `browser.storage.local`) adapter.
75
+ * Values are stored as base64url-encoded bytes. Encrypt or wrap the bytes before
76
+ * `put` if your product requires encrypted local persistence.
77
+ *
78
+ * @throws StorageError `STORAGE_NOT_AVAILABLE` if extension storage is unavailable.
79
+ */
80
+ declare function extensionStorage(options?: ExtensionStorageOptions): StorageAdapter;
81
+
82
+ export { type BrowserStorageOptions, type ExtensionStorageOptions, type StorageAdapter, browserStorage, extensionStorage, inMemoryStorage };
@@ -0,0 +1,246 @@
1
+ import { StorageError } from './chunk-OHIM2YWU.js';
2
+ import './chunk-VR6T6OJS.js';
3
+
4
+ // src/storage/index.ts
5
+ var STORAGE_KEY_PREFIX = "invisible:sdk:storage:v1:";
6
+ var STORAGE_KEY_SEPARATOR = ":";
7
+ var BASE64URL_PAD = "=";
8
+ var BASE64URL_PLUS = "+";
9
+ var BASE64URL_SLASH = "/";
10
+ var BASE64URL_MINUS = "-";
11
+ var BASE64URL_UNDERSCORE = "_";
12
+ var BYTE_STRING_CHUNK_SIZE = 32768;
13
+ var EXTENSION_TRUSTED_CONTEXTS_ACCESS_LEVEL = "TRUSTED_CONTEXTS";
14
+ function inMemoryStorage() {
15
+ const namespaces = /* @__PURE__ */ new Map();
16
+ const bucket = (namespace) => {
17
+ let inner = namespaces.get(namespace);
18
+ if (!inner) {
19
+ inner = /* @__PURE__ */ new Map();
20
+ namespaces.set(namespace, inner);
21
+ }
22
+ return inner;
23
+ };
24
+ return {
25
+ kind: "memory",
26
+ async put(namespace, key, value) {
27
+ bucket(namespace).set(key, value);
28
+ },
29
+ async get(namespace, key) {
30
+ return namespaces.get(namespace)?.get(key) ?? null;
31
+ },
32
+ async list(namespace) {
33
+ return [...namespaces.get(namespace)?.keys() ?? []];
34
+ },
35
+ async remove(namespace, key) {
36
+ namespaces.get(namespace)?.delete(key);
37
+ }
38
+ };
39
+ }
40
+ function browserStorage(options = {}) {
41
+ const storage = options.storage ?? defaultBrowserStorage();
42
+ if (!storage) throw new StorageError("STORAGE_NOT_AVAILABLE", "localStorage is unavailable");
43
+ return {
44
+ kind: "browser",
45
+ async put(namespace, key, value) {
46
+ try {
47
+ storage.setItem(storageKey(namespace, key), bytesToBase64Url(value));
48
+ } catch (cause) {
49
+ throw browserOperationError(cause);
50
+ }
51
+ },
52
+ async get(namespace, key) {
53
+ try {
54
+ const value = storage.getItem(storageKey(namespace, key));
55
+ return value === null ? null : base64UrlToBytes(value);
56
+ } catch (cause) {
57
+ throw browserOperationError(cause);
58
+ }
59
+ },
60
+ async list(namespace) {
61
+ try {
62
+ const prefix = storageKeyPrefix(namespace);
63
+ const keys = [];
64
+ for (let index = 0; index < storage.length; index += 1) {
65
+ const storedKey = storage.key(index);
66
+ if (storedKey?.startsWith(prefix)) {
67
+ keys.push(decodeStorageSegment(storedKey.slice(prefix.length)));
68
+ }
69
+ }
70
+ return keys;
71
+ } catch (cause) {
72
+ throw browserOperationError(cause);
73
+ }
74
+ },
75
+ async remove(namespace, key) {
76
+ try {
77
+ storage.removeItem(storageKey(namespace, key));
78
+ } catch (cause) {
79
+ throw browserOperationError(cause);
80
+ }
81
+ }
82
+ };
83
+ }
84
+ function extensionStorage(options = {}) {
85
+ const storage = options.storage ?? defaultExtensionStorage();
86
+ if (!storage) {
87
+ throw new StorageError("STORAGE_NOT_AVAILABLE", "extension local storage is unavailable");
88
+ }
89
+ const runtime = options.runtime ?? defaultExtensionRuntime();
90
+ const trustedAccess = options.restrictAccessToTrustedContexts === false ? Promise.resolve() : extensionSetAccessLevel(storage, runtime);
91
+ return {
92
+ kind: "extension",
93
+ async put(namespace, key, value) {
94
+ await trustedAccess;
95
+ await extensionSet(storage, runtime, {
96
+ [storageKey(namespace, key)]: bytesToBase64Url(value)
97
+ });
98
+ },
99
+ async get(namespace, key) {
100
+ await trustedAccess;
101
+ const storedKey = storageKey(namespace, key);
102
+ const values = await extensionGet(storage, runtime, storedKey);
103
+ const value = values[storedKey];
104
+ return typeof value === "string" ? base64UrlToBytes(value) : null;
105
+ },
106
+ async list(namespace) {
107
+ await trustedAccess;
108
+ const prefix = storageKeyPrefix(namespace);
109
+ const values = await extensionGet(storage, runtime, null);
110
+ return Object.keys(values).filter((key) => key.startsWith(prefix)).map((key) => decodeStorageSegment(key.slice(prefix.length)));
111
+ },
112
+ async remove(namespace, key) {
113
+ await trustedAccess;
114
+ await extensionRemove(storage, runtime, storageKey(namespace, key));
115
+ }
116
+ };
117
+ }
118
+ function storageKey(namespace, key) {
119
+ return `${storageKeyPrefix(namespace)}${encodeStorageSegment(key)}`;
120
+ }
121
+ function storageKeyPrefix(namespace) {
122
+ return `${STORAGE_KEY_PREFIX}${encodeStorageSegment(namespace)}${STORAGE_KEY_SEPARATOR}`;
123
+ }
124
+ function encodeStorageSegment(value) {
125
+ return encodeURIComponent(value);
126
+ }
127
+ function decodeStorageSegment(value) {
128
+ return decodeURIComponent(value);
129
+ }
130
+ function bytesToBase64Url(value) {
131
+ let binary = "";
132
+ for (let index = 0; index < value.length; index += BYTE_STRING_CHUNK_SIZE) {
133
+ binary += String.fromCharCode(...value.slice(index, index + BYTE_STRING_CHUNK_SIZE));
134
+ }
135
+ return btoa(binary).split(BASE64URL_PLUS).join(BASE64URL_MINUS).split(BASE64URL_SLASH).join(BASE64URL_UNDERSCORE).split(BASE64URL_PAD).join("");
136
+ }
137
+ function base64UrlToBytes(value) {
138
+ try {
139
+ const base64 = value.split(BASE64URL_MINUS).join(BASE64URL_PLUS).split(BASE64URL_UNDERSCORE).join(BASE64URL_SLASH).padEnd(Math.ceil(value.length / 4) * 4, BASE64URL_PAD);
140
+ return Uint8Array.from(atob(base64), (char) => char.charCodeAt(0));
141
+ } catch (cause) {
142
+ throw new StorageError("STORAGE_DECRYPT_FAILED", "stored value is not valid base64url", {
143
+ cause
144
+ });
145
+ }
146
+ }
147
+ function defaultBrowserStorage() {
148
+ try {
149
+ return globalThis.localStorage;
150
+ } catch (cause) {
151
+ throw new StorageError("STORAGE_NOT_AVAILABLE", "localStorage is unavailable", { cause });
152
+ }
153
+ }
154
+ function browserOperationError(cause) {
155
+ if (cause instanceof StorageError) return cause;
156
+ return new StorageError(
157
+ "STORAGE_NOT_AVAILABLE",
158
+ storageErrorMessage(cause) ?? "localStorage operation failed",
159
+ { cause }
160
+ );
161
+ }
162
+ function defaultExtensionStorage() {
163
+ const global = globalThis;
164
+ return global.chrome?.storage?.local ?? global.browser?.storage?.local;
165
+ }
166
+ function defaultExtensionRuntime() {
167
+ const global = globalThis;
168
+ return global.chrome?.runtime ?? global.browser?.runtime;
169
+ }
170
+ function extensionGet(storage, runtime, keys) {
171
+ return new Promise((resolve, reject) => {
172
+ const maybePromise = storage.get(keys, (items) => {
173
+ const error = extensionLastError(runtime);
174
+ if (error) reject(extensionOperationError(error));
175
+ else resolve(items);
176
+ });
177
+ if (isPromise(maybePromise)) {
178
+ maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));
179
+ }
180
+ });
181
+ }
182
+ function extensionSet(storage, runtime, items) {
183
+ return new Promise((resolve, reject) => {
184
+ const maybePromise = storage.set(items, () => {
185
+ const error = extensionLastError(runtime);
186
+ if (error) reject(extensionOperationError(error));
187
+ else resolve();
188
+ });
189
+ if (isPromise(maybePromise))
190
+ maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));
191
+ });
192
+ }
193
+ function extensionRemove(storage, runtime, key) {
194
+ return new Promise((resolve, reject) => {
195
+ const maybePromise = storage.remove(key, () => {
196
+ const error = extensionLastError(runtime);
197
+ if (error) reject(extensionOperationError(error));
198
+ else resolve();
199
+ });
200
+ if (isPromise(maybePromise))
201
+ maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));
202
+ });
203
+ }
204
+ function extensionSetAccessLevel(storage, runtime) {
205
+ const setAccessLevel = storage.setAccessLevel;
206
+ if (!setAccessLevel) return Promise.resolve();
207
+ return new Promise((resolve, reject) => {
208
+ const maybePromise = setAccessLevel.call(
209
+ storage,
210
+ { accessLevel: EXTENSION_TRUSTED_CONTEXTS_ACCESS_LEVEL },
211
+ () => {
212
+ const error = extensionLastError(runtime);
213
+ if (error) reject(extensionOperationError(error));
214
+ else resolve();
215
+ }
216
+ );
217
+ if (isPromise(maybePromise))
218
+ maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));
219
+ });
220
+ }
221
+ function extensionLastError(runtime) {
222
+ return runtime?.lastError ?? null;
223
+ }
224
+ function extensionOperationError(error) {
225
+ if (error instanceof StorageError) return error;
226
+ return new StorageError(
227
+ "STORAGE_NOT_AVAILABLE",
228
+ storageErrorMessage(error) ?? "extension storage operation failed",
229
+ { cause: error }
230
+ );
231
+ }
232
+ function storageErrorMessage(error) {
233
+ if (error instanceof Error) return error.message;
234
+ if (typeof error === "object" && error !== null && "message" in error) {
235
+ const message = error.message;
236
+ if (typeof message === "string") return message;
237
+ }
238
+ return void 0;
239
+ }
240
+ function isPromise(value) {
241
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
242
+ }
243
+
244
+ export { browserStorage, extensionStorage, inMemoryStorage };
245
+ //# sourceMappingURL=storage.js.map
246
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/index.ts"],"names":[],"mappings":";;;;AAYA,IAAM,kBAAA,GAAqB,2BAAA;AAC3B,IAAM,qBAAA,GAAwB,GAAA;AAC9B,IAAM,aAAA,GAAgB,GAAA;AACtB,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,eAAA,GAAkB,GAAA;AACxB,IAAM,eAAA,GAAkB,GAAA;AACxB,IAAM,oBAAA,GAAuB,GAAA;AAC7B,IAAM,sBAAA,GAAyB,KAAA;AAC/B,IAAM,uCAAA,GAA0C,kBAAA;AA6DzC,SAAS,eAAA,GAAkC;AAIhD,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAqC;AAC5D,EAAA,MAAM,MAAA,GAAS,CAAC,SAAA,KAAsB;AACpC,IAAA,IAAI,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA;AACpC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,KAAA,uBAAY,GAAA,EAAwB;AACpC,MAAA,UAAA,CAAW,GAAA,CAAI,WAAW,KAAK,CAAA;AAAA,IACjC;AACA,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AACA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,MAAM,GAAA,CAAI,SAAA,EAAW,GAAA,EAAK,KAAA,EAAO;AAC/B,MAAA,MAAA,CAAO,SAAS,CAAA,CAAE,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,IAClC,CAAA;AAAA,IACA,MAAM,GAAA,CAAI,SAAA,EAAW,GAAA,EAAK;AACxB,MAAA,OAAO,WAAW,GAAA,CAAI,SAAS,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA;AAAA,IAChD,CAAA;AAAA,IACA,MAAM,KAAK,SAAA,EAAW;AACpB,MAAA,OAAO,CAAC,GAAI,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA,EAAG,IAAA,EAAK,IAAK,EAAG,CAAA;AAAA,IACtD,CAAA;AAAA,IACA,MAAM,MAAA,CAAO,SAAA,EAAW,GAAA,EAAK;AAC3B,MAAA,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA,EAAG,MAAA,CAAO,GAAG,CAAA;AAAA,IACvC;AAAA,GACF;AACF;AASO,SAAS,cAAA,CAAe,OAAA,GAAiC,EAAC,EAAmB;AAClF,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,qBAAA,EAAsB;AACzD,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,YAAA,CAAa,yBAAyB,6BAA6B,CAAA;AAC3F,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,MAAM,GAAA,CAAI,SAAA,EAAW,GAAA,EAAK,KAAA,EAAO;AAC/B,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,QAAQ,UAAA,CAAW,SAAA,EAAW,GAAG,CAAA,EAAG,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAAA,MACrE,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,sBAAsB,KAAK,CAAA;AAAA,MACnC;AAAA,IACF,CAAA;AAAA,IACA,MAAM,GAAA,CAAI,SAAA,EAAW,GAAA,EAAK;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,QAAQ,OAAA,CAAQ,OAAA,CAAQ,UAAA,CAAW,SAAA,EAAW,GAAG,CAAC,CAAA;AACxD,QAAA,OAAO,KAAA,KAAU,IAAA,GAAO,IAAA,GAAO,gBAAA,CAAiB,KAAK,CAAA;AAAA,MACvD,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,sBAAsB,KAAK,CAAA;AAAA,MACnC;AAAA,IACF,CAAA;AAAA,IACA,MAAM,KAAK,SAAA,EAAW;AACpB,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,iBAAiB,SAAS,CAAA;AACzC,QAAA,MAAM,OAAiB,EAAC;AACxB,QAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,CAAQ,MAAA,EAAQ,SAAS,CAAA,EAAG;AACtD,UAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA;AACnC,UAAA,IAAI,SAAA,EAAW,UAAA,CAAW,MAAM,CAAA,EAAG;AACjC,YAAA,IAAA,CAAK,KAAK,oBAAA,CAAqB,SAAA,CAAU,MAAM,MAAA,CAAO,MAAM,CAAC,CAAC,CAAA;AAAA,UAChE;AAAA,QACF;AACA,QAAA,OAAO,IAAA;AAAA,MACT,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,sBAAsB,KAAK,CAAA;AAAA,MACnC;AAAA,IACF,CAAA;AAAA,IACA,MAAM,MAAA,CAAO,SAAA,EAAW,GAAA,EAAK;AAC3B,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,UAAA,CAAW,UAAA,CAAW,SAAA,EAAW,GAAG,CAAC,CAAA;AAAA,MAC/C,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,sBAAsB,KAAK,CAAA;AAAA,MACnC;AAAA,IACF;AAAA,GACF;AACF;AASO,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAmB;AACtF,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,uBAAA,EAAwB;AAC3D,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,YAAA,CAAa,uBAAA,EAAyB,wCAAwC,CAAA;AAAA,EAC1F;AACA,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,uBAAA,EAAwB;AAC3D,EAAA,MAAM,aAAA,GACJ,QAAQ,+BAAA,KAAoC,KAAA,GACxC,QAAQ,OAAA,EAAQ,GAChB,uBAAA,CAAwB,OAAA,EAAS,OAAO,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,WAAA;AAAA,IACN,MAAM,GAAA,CAAI,SAAA,EAAW,GAAA,EAAK,KAAA,EAAO;AAC/B,MAAA,MAAM,aAAA;AACN,MAAA,MAAM,YAAA,CAAa,SAAS,OAAA,EAAS;AAAA,QACnC,CAAC,UAAA,CAAW,SAAA,EAAW,GAAG,CAAC,GAAG,iBAAiB,KAAK;AAAA,OACrD,CAAA;AAAA,IACH,CAAA;AAAA,IACA,MAAM,GAAA,CAAI,SAAA,EAAW,GAAA,EAAK;AACxB,MAAA,MAAM,aAAA;AACN,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,SAAA,EAAW,GAAG,CAAA;AAC3C,MAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,OAAA,EAAS,SAAS,SAAS,CAAA;AAC7D,MAAA,MAAM,KAAA,GAAQ,OAAO,SAAS,CAAA;AAC9B,MAAA,OAAO,OAAO,KAAA,KAAU,QAAA,GAAW,gBAAA,CAAiB,KAAK,CAAA,GAAI,IAAA;AAAA,IAC/D,CAAA;AAAA,IACA,MAAM,KAAK,SAAA,EAAW;AACpB,MAAA,MAAM,aAAA;AACN,MAAA,MAAM,MAAA,GAAS,iBAAiB,SAAS,CAAA;AACzC,MAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,OAAA,EAAS,SAAS,IAAI,CAAA;AACxD,MAAA,OAAO,MAAA,CAAO,KAAK,MAAM,CAAA,CACtB,OAAO,CAAC,GAAA,KAAQ,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA,CACtC,GAAA,CAAI,CAAC,GAAA,KAAQ,oBAAA,CAAqB,IAAI,KAAA,CAAM,MAAA,CAAO,MAAM,CAAC,CAAC,CAAA;AAAA,IAChE,CAAA;AAAA,IACA,MAAM,MAAA,CAAO,SAAA,EAAW,GAAA,EAAK;AAC3B,MAAA,MAAM,aAAA;AACN,MAAA,MAAM,gBAAgB,OAAA,EAAS,OAAA,EAAS,UAAA,CAAW,SAAA,EAAW,GAAG,CAAC,CAAA;AAAA,IACpE;AAAA,GACF;AACF;AAEA,SAAS,UAAA,CAAW,WAAmB,GAAA,EAAqB;AAC1D,EAAA,OAAO,GAAG,gBAAA,CAAiB,SAAS,CAAC,CAAA,EAAG,oBAAA,CAAqB,GAAG,CAAC,CAAA,CAAA;AACnE;AAEA,SAAS,iBAAiB,SAAA,EAA2B;AACnD,EAAA,OAAO,GAAG,kBAAkB,CAAA,EAAG,qBAAqB,SAAS,CAAC,GAAG,qBAAqB,CAAA,CAAA;AACxF;AAEA,SAAS,qBAAqB,KAAA,EAAuB;AACnD,EAAA,OAAO,mBAAmB,KAAK,CAAA;AACjC;AAEA,SAAS,qBAAqB,KAAA,EAAuB;AACnD,EAAA,OAAO,mBAAmB,KAAK,CAAA;AACjC;AAEA,SAAS,iBAAiB,KAAA,EAA2B;AACnD,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,KAAA,CAAM,MAAA,EAAQ,SAAS,sBAAA,EAAwB;AACzE,IAAA,MAAA,IAAU,MAAA,CAAO,aAAa,GAAG,KAAA,CAAM,MAAM,KAAA,EAAO,KAAA,GAAQ,sBAAsB,CAAC,CAAA;AAAA,EACrF;AACA,EAAA,OAAO,KAAK,MAAM,CAAA,CACf,MAAM,cAAc,CAAA,CACpB,KAAK,eAAe,CAAA,CACpB,MAAM,eAAe,CAAA,CACrB,KAAK,oBAAoB,CAAA,CACzB,MAAM,aAAa,CAAA,CACnB,KAAK,EAAE,CAAA;AACZ;AAEA,SAAS,iBAAiB,KAAA,EAA2B;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MACZ,KAAA,CAAM,eAAe,EACrB,IAAA,CAAK,cAAc,CAAA,CACnB,KAAA,CAAM,oBAAoB,CAAA,CAC1B,KAAK,eAAe,CAAA,CACpB,OAAO,IAAA,CAAK,IAAA,CAAK,MAAM,MAAA,GAAS,CAAC,CAAA,GAAI,CAAA,EAAG,aAAa,CAAA;AACxD,IAAA,OAAO,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA,EAAG,CAAC,IAAA,KAAS,IAAA,CAAK,UAAA,CAAW,CAAC,CAAC,CAAA;AAAA,EACnE,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,YAAA,CAAa,wBAAA,EAA0B,qCAAA,EAAuC;AAAA,MACtF;AAAA,KACD,CAAA;AAAA,EACH;AACF;AAEA,SAAS,qBAAA,GAAiD;AACxD,EAAA,IAAI;AACF,IAAA,OAAO,UAAA,CAAW,YAAA;AAAA,EACpB,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,YAAA,CAAa,uBAAA,EAAyB,6BAAA,EAA+B,EAAE,OAAO,CAAA;AAAA,EAC1F;AACF;AAEA,SAAS,sBAAsB,KAAA,EAA8B;AAC3D,EAAA,IAAI,KAAA,YAAiB,cAAc,OAAO,KAAA;AAC1C,EAAA,OAAO,IAAI,YAAA;AAAA,IACT,uBAAA;AAAA,IACA,mBAAA,CAAoB,KAAK,CAAA,IAAK,+BAAA;AAAA,IAC9B,EAAE,KAAA;AAAM,GACV;AACF;AAEA,SAAS,uBAAA,GAA4D;AACnE,EAAA,MAAM,MAAA,GAAS,UAAA;AAIf,EAAA,OAAO,OAAO,MAAA,EAAQ,OAAA,EAAS,KAAA,IAAS,MAAA,CAAO,SAAS,OAAA,EAAS,KAAA;AACnE;AAEA,SAAS,uBAAA,GAA4D;AACnE,EAAA,MAAM,MAAA,GAAS,UAAA;AAIf,EAAA,OAAO,MAAA,CAAO,MAAA,EAAQ,OAAA,IAAW,MAAA,CAAO,OAAA,EAAS,OAAA;AACnD;AAEA,SAAS,YAAA,CACP,OAAA,EACA,OAAA,EACA,IAAA,EACkC;AAClC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,CAAC,KAAA,KAAU;AAChD,MAAA,MAAM,KAAA,GAAQ,mBAAmB,OAAO,CAAA;AACxC,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,uBAAA,CAAwB,KAAK,CAAC,CAAA;AAAA,mBACnC,KAAK,CAAA;AAAA,IACpB,CAAC,CAAA;AACD,IAAA,IAAI,SAAA,CAAmC,YAAY,CAAA,EAAG;AACpD,MAAA,YAAA,CAAa,IAAA,CAAK,SAAS,CAAC,KAAA,KAAU,OAAO,uBAAA,CAAwB,KAAK,CAAC,CAAC,CAAA;AAAA,IAC9E;AAAA,EACF,CAAC,CAAA;AACH;AAEA,SAAS,YAAA,CACP,OAAA,EACA,OAAA,EACA,KAAA,EACe;AACf,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,MAAM;AAC5C,MAAA,MAAM,KAAA,GAAQ,mBAAmB,OAAO,CAAA;AACxC,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,uBAAA,CAAwB,KAAK,CAAC,CAAA;AAAA,WAC3C,OAAA,EAAQ;AAAA,IACf,CAAC,CAAA;AACD,IAAA,IAAI,UAAgB,YAAY,CAAA;AAC9B,MAAA,YAAA,CAAa,IAAA,CAAK,SAAS,CAAC,KAAA,KAAU,OAAO,uBAAA,CAAwB,KAAK,CAAC,CAAC,CAAA;AAAA,EAChF,CAAC,CAAA;AACH;AAEA,SAAS,eAAA,CACP,OAAA,EACA,OAAA,EACA,GAAA,EACe;AACf,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,MAAA,CAAO,GAAA,EAAK,MAAM;AAC7C,MAAA,MAAM,KAAA,GAAQ,mBAAmB,OAAO,CAAA;AACxC,MAAA,IAAI,KAAA,EAAO,MAAA,CAAO,uBAAA,CAAwB,KAAK,CAAC,CAAA;AAAA,WAC3C,OAAA,EAAQ;AAAA,IACf,CAAC,CAAA;AACD,IAAA,IAAI,UAAgB,YAAY,CAAA;AAC9B,MAAA,YAAA,CAAa,IAAA,CAAK,SAAS,CAAC,KAAA,KAAU,OAAO,uBAAA,CAAwB,KAAK,CAAC,CAAC,CAAA;AAAA,EAChF,CAAC,CAAA;AACH;AAEA,SAAS,uBAAA,CACP,SACA,OAAA,EACe;AACf,EAAA,MAAM,iBAAiB,OAAA,CAAQ,cAAA;AAC/B,EAAA,IAAI,CAAC,cAAA,EAAgB,OAAO,OAAA,CAAQ,OAAA,EAAQ;AAC5C,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,eAAe,cAAA,CAAe,IAAA;AAAA,MAClC,OAAA;AAAA,MACA,EAAE,aAAa,uCAAA,EAAwC;AAAA,MACvD,MAAM;AACJ,QAAA,MAAM,KAAA,GAAQ,mBAAmB,OAAO,CAAA;AACxC,QAAA,IAAI,KAAA,EAAO,MAAA,CAAO,uBAAA,CAAwB,KAAK,CAAC,CAAA;AAAA,aAC3C,OAAA,EAAQ;AAAA,MACf;AAAA,KACF;AACA,IAAA,IAAI,UAAgB,YAAY,CAAA;AAC9B,MAAA,YAAA,CAAa,IAAA,CAAK,SAAS,CAAC,KAAA,KAAU,OAAO,uBAAA,CAAwB,KAAK,CAAC,CAAC,CAAA;AAAA,EAChF,CAAC,CAAA;AACH;AAEA,SAAS,mBACP,OAAA,EACsC;AACtC,EAAA,OAAO,SAAS,SAAA,IAAa,IAAA;AAC/B;AAEA,SAAS,wBAAwB,KAAA,EAA8B;AAC7D,EAAA,IAAI,KAAA,YAAiB,cAAc,OAAO,KAAA;AAC1C,EAAA,OAAO,IAAI,YAAA;AAAA,IACT,uBAAA;AAAA,IACA,mBAAA,CAAoB,KAAK,CAAA,IAAK,oCAAA;AAAA,IAC9B,EAAE,OAAO,KAAA;AAAM,GACjB;AACF;AAEA,SAAS,oBAAoB,KAAA,EAAoC;AAC/D,EAAA,IAAI,KAAA,YAAiB,KAAA,EAAO,OAAO,KAAA,CAAM,OAAA;AACzC,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,aAAa,KAAA,EAAO;AACrE,IAAA,MAAM,UAAW,KAAA,CAAgC,OAAA;AACjD,IAAA,IAAI,OAAO,OAAA,KAAY,QAAA,EAAU,OAAO,OAAA;AAAA,EAC1C;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,UAAa,KAAA,EAAqC;AACzD,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,MAAA,IAAU,KAAA,IACV,OAAQ,KAAA,CAA4B,IAAA,KAAS,UAAA;AAEjD","file":"storage.js","sourcesContent":["/**\n * `@invisible-labs/sdk/storage` - storage adapters (spec section 7).\n *\n * The SDK persists recoverable secrets (Recovery Code, LP Position Code, LP\n * Refill Key, withdrawal secret) only through a {@link StorageAdapter}. The\n * `memory`, `browser`, and `extension` adapters are real. Browser and\n * extension adapters persist the bytes provided by the caller; callers that need\n * encrypted-at-rest storage can wrap/encrypt bytes before calling `put`.\n */\n\nimport { StorageError } from \"../core/errors.js\";\n\nconst STORAGE_KEY_PREFIX = \"invisible:sdk:storage:v1:\";\nconst STORAGE_KEY_SEPARATOR = \":\";\nconst BASE64URL_PAD = \"=\";\nconst BASE64URL_PLUS = \"+\";\nconst BASE64URL_SLASH = \"/\";\nconst BASE64URL_MINUS = \"-\";\nconst BASE64URL_UNDERSCORE = \"_\";\nconst BYTE_STRING_CHUNK_SIZE = 0x8000;\nconst EXTENSION_TRUSTED_CONTEXTS_ACCESS_LEVEL = \"TRUSTED_CONTEXTS\";\n\n/**\n * A namespaced key/value store for the SDK's recoverable secrets. Values are\n * raw bytes. Callers may store plaintext bytes, pre-wrapped bytes, or encrypted\n * bytes depending on their host product's storage model.\n */\nexport interface StorageAdapter {\n /** Which backing the adapter uses. */\n readonly kind: \"browser\" | \"extension\" | \"server-hkdf\" | \"server-custom\" | \"memory\";\n put(namespace: string, key: string, value: Uint8Array): Promise<void>;\n get(namespace: string, key: string): Promise<Uint8Array | null>;\n list(namespace: string): Promise<string[]>;\n remove(namespace: string, key: string): Promise<void>;\n /** `server-hkdf` only: derive a secret from a stable domain context. */\n derive?(namespace: string, context: string): Promise<Uint8Array>;\n}\n\nexport interface BrowserStorageOptions {\n /** Override for tests or custom host environments. Defaults to `globalThis.localStorage`. */\n readonly storage?: StorageLike;\n}\n\nexport interface ExtensionStorageOptions {\n /** Override for tests or custom extension hosts. Defaults to chrome/browser storage local. */\n readonly storage?: ExtensionStorageArea;\n /** Override for tests or custom extension hosts. Defaults to chrome/browser runtime. */\n readonly runtime?: ExtensionRuntimeLike;\n /**\n * Chrome exposes storage.local to content scripts by default. Keep the default\n * trusted-context restriction when the host API supports it.\n */\n readonly restrictAccessToTrustedContexts?: boolean;\n}\n\ninterface StorageLike {\n readonly length: number;\n key(index: number): string | null;\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\ninterface ExtensionStorageArea {\n get(\n keys?: string | string[] | Record<string, unknown> | null,\n callback?: (items: Record<string, unknown>) => void,\n ): Promise<Record<string, unknown>> | void;\n set(items: Record<string, string>, callback?: () => void): Promise<void> | void;\n remove(keys: string | string[], callback?: () => void): Promise<void> | void;\n setAccessLevel?(details: { accessLevel: string }, callback?: () => void): Promise<void> | void;\n}\n\ninterface ExtensionRuntimeLike {\n readonly lastError?: { readonly message?: string } | null;\n}\n\n/**\n * In-memory adapter. Fully functional, unencrypted, non-persistent - intended\n * for tests and ephemeral flows, never for real secrets at rest.\n */\nexport function inMemoryStorage(): StorageAdapter {\n // Each namespace is a separate inner map rather than a flattened composite\n // key, so a namespace or key containing any character (including a separator)\n // can never collide across namespaces.\n const namespaces = new Map<string, Map<string, Uint8Array>>();\n const bucket = (namespace: string) => {\n let inner = namespaces.get(namespace);\n if (!inner) {\n inner = new Map<string, Uint8Array>();\n namespaces.set(namespace, inner);\n }\n return inner;\n };\n return {\n kind: \"memory\",\n async put(namespace, key, value) {\n bucket(namespace).set(key, value);\n },\n async get(namespace, key) {\n return namespaces.get(namespace)?.get(key) ?? null;\n },\n async list(namespace) {\n return [...(namespaces.get(namespace)?.keys() ?? [])];\n },\n async remove(namespace, key) {\n namespaces.get(namespace)?.delete(key);\n },\n };\n}\n\n/**\n * Browser `localStorage` adapter. Values are stored as base64url-encoded bytes.\n * Encrypt or wrap the bytes before `put` if your product requires encrypted\n * local persistence.\n *\n * @throws StorageError `STORAGE_NOT_AVAILABLE` if `localStorage` is unavailable.\n */\nexport function browserStorage(options: BrowserStorageOptions = {}): StorageAdapter {\n const storage = options.storage ?? defaultBrowserStorage();\n if (!storage) throw new StorageError(\"STORAGE_NOT_AVAILABLE\", \"localStorage is unavailable\");\n return {\n kind: \"browser\",\n async put(namespace, key, value) {\n try {\n storage.setItem(storageKey(namespace, key), bytesToBase64Url(value));\n } catch (cause) {\n throw browserOperationError(cause);\n }\n },\n async get(namespace, key) {\n try {\n const value = storage.getItem(storageKey(namespace, key));\n return value === null ? null : base64UrlToBytes(value);\n } catch (cause) {\n throw browserOperationError(cause);\n }\n },\n async list(namespace) {\n try {\n const prefix = storageKeyPrefix(namespace);\n const keys: string[] = [];\n for (let index = 0; index < storage.length; index += 1) {\n const storedKey = storage.key(index);\n if (storedKey?.startsWith(prefix)) {\n keys.push(decodeStorageSegment(storedKey.slice(prefix.length)));\n }\n }\n return keys;\n } catch (cause) {\n throw browserOperationError(cause);\n }\n },\n async remove(namespace, key) {\n try {\n storage.removeItem(storageKey(namespace, key));\n } catch (cause) {\n throw browserOperationError(cause);\n }\n },\n };\n}\n\n/**\n * Browser-extension (`chrome.storage.local` / `browser.storage.local`) adapter.\n * Values are stored as base64url-encoded bytes. Encrypt or wrap the bytes before\n * `put` if your product requires encrypted local persistence.\n *\n * @throws StorageError `STORAGE_NOT_AVAILABLE` if extension storage is unavailable.\n */\nexport function extensionStorage(options: ExtensionStorageOptions = {}): StorageAdapter {\n const storage = options.storage ?? defaultExtensionStorage();\n if (!storage) {\n throw new StorageError(\"STORAGE_NOT_AVAILABLE\", \"extension local storage is unavailable\");\n }\n const runtime = options.runtime ?? defaultExtensionRuntime();\n const trustedAccess =\n options.restrictAccessToTrustedContexts === false\n ? Promise.resolve()\n : extensionSetAccessLevel(storage, runtime);\n return {\n kind: \"extension\",\n async put(namespace, key, value) {\n await trustedAccess;\n await extensionSet(storage, runtime, {\n [storageKey(namespace, key)]: bytesToBase64Url(value),\n });\n },\n async get(namespace, key) {\n await trustedAccess;\n const storedKey = storageKey(namespace, key);\n const values = await extensionGet(storage, runtime, storedKey);\n const value = values[storedKey];\n return typeof value === \"string\" ? base64UrlToBytes(value) : null;\n },\n async list(namespace) {\n await trustedAccess;\n const prefix = storageKeyPrefix(namespace);\n const values = await extensionGet(storage, runtime, null);\n return Object.keys(values)\n .filter((key) => key.startsWith(prefix))\n .map((key) => decodeStorageSegment(key.slice(prefix.length)));\n },\n async remove(namespace, key) {\n await trustedAccess;\n await extensionRemove(storage, runtime, storageKey(namespace, key));\n },\n };\n}\n\nfunction storageKey(namespace: string, key: string): string {\n return `${storageKeyPrefix(namespace)}${encodeStorageSegment(key)}`;\n}\n\nfunction storageKeyPrefix(namespace: string): string {\n return `${STORAGE_KEY_PREFIX}${encodeStorageSegment(namespace)}${STORAGE_KEY_SEPARATOR}`;\n}\n\nfunction encodeStorageSegment(value: string): string {\n return encodeURIComponent(value);\n}\n\nfunction decodeStorageSegment(value: string): string {\n return decodeURIComponent(value);\n}\n\nfunction bytesToBase64Url(value: Uint8Array): string {\n let binary = \"\";\n for (let index = 0; index < value.length; index += BYTE_STRING_CHUNK_SIZE) {\n binary += String.fromCharCode(...value.slice(index, index + BYTE_STRING_CHUNK_SIZE));\n }\n return btoa(binary)\n .split(BASE64URL_PLUS)\n .join(BASE64URL_MINUS)\n .split(BASE64URL_SLASH)\n .join(BASE64URL_UNDERSCORE)\n .split(BASE64URL_PAD)\n .join(\"\");\n}\n\nfunction base64UrlToBytes(value: string): Uint8Array {\n try {\n const base64 = value\n .split(BASE64URL_MINUS)\n .join(BASE64URL_PLUS)\n .split(BASE64URL_UNDERSCORE)\n .join(BASE64URL_SLASH)\n .padEnd(Math.ceil(value.length / 4) * 4, BASE64URL_PAD);\n return Uint8Array.from(atob(base64), (char) => char.charCodeAt(0));\n } catch (cause) {\n throw new StorageError(\"STORAGE_DECRYPT_FAILED\", \"stored value is not valid base64url\", {\n cause,\n });\n }\n}\n\nfunction defaultBrowserStorage(): StorageLike | undefined {\n try {\n return globalThis.localStorage;\n } catch (cause) {\n throw new StorageError(\"STORAGE_NOT_AVAILABLE\", \"localStorage is unavailable\", { cause });\n }\n}\n\nfunction browserOperationError(cause: unknown): StorageError {\n if (cause instanceof StorageError) return cause;\n return new StorageError(\n \"STORAGE_NOT_AVAILABLE\",\n storageErrorMessage(cause) ?? \"localStorage operation failed\",\n { cause },\n );\n}\n\nfunction defaultExtensionStorage(): ExtensionStorageArea | undefined {\n const global = globalThis as {\n chrome?: { storage?: { local?: ExtensionStorageArea } };\n browser?: { storage?: { local?: ExtensionStorageArea } };\n };\n return global.chrome?.storage?.local ?? global.browser?.storage?.local;\n}\n\nfunction defaultExtensionRuntime(): ExtensionRuntimeLike | undefined {\n const global = globalThis as {\n chrome?: { runtime?: ExtensionRuntimeLike };\n browser?: { runtime?: ExtensionRuntimeLike };\n };\n return global.chrome?.runtime ?? global.browser?.runtime;\n}\n\nfunction extensionGet(\n storage: ExtensionStorageArea,\n runtime: ExtensionRuntimeLike | undefined,\n keys: string | string[] | Record<string, unknown> | null,\n): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const maybePromise = storage.get(keys, (items) => {\n const error = extensionLastError(runtime);\n if (error) reject(extensionOperationError(error));\n else resolve(items);\n });\n if (isPromise<Record<string, unknown>>(maybePromise)) {\n maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));\n }\n });\n}\n\nfunction extensionSet(\n storage: ExtensionStorageArea,\n runtime: ExtensionRuntimeLike | undefined,\n items: Record<string, string>,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const maybePromise = storage.set(items, () => {\n const error = extensionLastError(runtime);\n if (error) reject(extensionOperationError(error));\n else resolve();\n });\n if (isPromise<void>(maybePromise))\n maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));\n });\n}\n\nfunction extensionRemove(\n storage: ExtensionStorageArea,\n runtime: ExtensionRuntimeLike | undefined,\n key: string,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const maybePromise = storage.remove(key, () => {\n const error = extensionLastError(runtime);\n if (error) reject(extensionOperationError(error));\n else resolve();\n });\n if (isPromise<void>(maybePromise))\n maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));\n });\n}\n\nfunction extensionSetAccessLevel(\n storage: ExtensionStorageArea,\n runtime: ExtensionRuntimeLike | undefined,\n): Promise<void> {\n const setAccessLevel = storage.setAccessLevel;\n if (!setAccessLevel) return Promise.resolve();\n return new Promise((resolve, reject) => {\n const maybePromise = setAccessLevel.call(\n storage,\n { accessLevel: EXTENSION_TRUSTED_CONTEXTS_ACCESS_LEVEL },\n () => {\n const error = extensionLastError(runtime);\n if (error) reject(extensionOperationError(error));\n else resolve();\n },\n );\n if (isPromise<void>(maybePromise))\n maybePromise.then(resolve, (cause) => reject(extensionOperationError(cause)));\n });\n}\n\nfunction extensionLastError(\n runtime: ExtensionRuntimeLike | undefined,\n): { readonly message?: string } | null {\n return runtime?.lastError ?? null;\n}\n\nfunction extensionOperationError(error: unknown): StorageError {\n if (error instanceof StorageError) return error;\n return new StorageError(\n \"STORAGE_NOT_AVAILABLE\",\n storageErrorMessage(error) ?? \"extension storage operation failed\",\n { cause: error },\n );\n}\n\nfunction storageErrorMessage(error: unknown): string | undefined {\n if (error instanceof Error) return error.message;\n if (typeof error === \"object\" && error !== null && \"message\" in error) {\n const message = (error as { message?: unknown }).message;\n if (typeof message === \"string\") return message;\n }\n return undefined;\n}\n\nfunction isPromise<T>(value: unknown): value is Promise<T> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof (value as { then: unknown }).then === \"function\"\n );\n}\n"]}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Transport abstraction.
3
+ *
4
+ * A `Transport` is the raw, ordered byte channel between the client and one
5
+ * coordinator process. It knows how to open, carry frames, and close - nothing
6
+ * about Noise or attestation, which are session-level concerns layered on top.
7
+ * This separation lets the same session logic run over a real WebSocket in
8
+ * production and over an in-memory channel in tests.
9
+ */
10
+ /** Lifecycle of a transport connection. */
11
+ type ConnectionState = "idle" | "connecting" | "open" | "closing" | "closed";
12
+ /** Unsubscribe a previously-registered listener. */
13
+ type Unsubscribe = () => void;
14
+ /**
15
+ * The byte channel a session runs over. Implementations are created by a
16
+ * factory (`inMemoryTransport`, `noiseWebSocketTransport`); consumers never
17
+ * construct one directly.
18
+ */
19
+ interface Transport {
20
+ /**
21
+ * Open the channel. Resolves once the underlying connection is established
22
+ * (for the WebSocket transport, once the socket is open). Rejects with a
23
+ * `TransportError` on failure or abort.
24
+ *
25
+ * @param signal optional `AbortSignal`; aborting mid-connect closes the
26
+ * socket and rejects.
27
+ */
28
+ connect(signal?: AbortSignal): Promise<void>;
29
+ /** The current lifecycle state. */
30
+ state(): ConnectionState;
31
+ /** Subscribe to state transitions. Returns an unsubscribe function. */
32
+ onStateChange(listener: (state: ConnectionState) => void): Unsubscribe;
33
+ /** Subscribe to inbound frames. Returns an unsubscribe function. */
34
+ onMessage(listener: (frame: Uint8Array) => void): Unsubscribe;
35
+ /**
36
+ * Send one frame. Frame construction (Noise encryption, length framing) is
37
+ * not implemented in the skeleton, so this throws `NotImplementedError`.
38
+ */
39
+ send(frame: Uint8Array): void;
40
+ /** Close the channel. Idempotent. */
41
+ close(): void;
42
+ }
43
+ /**
44
+ * Minimal browser-`WebSocket`-shaped surface the WebSocket transport depends on.
45
+ * Node 22's global `WebSocket` and the `ws` package's client both satisfy it,
46
+ * so tests can inject a stub without a real network.
47
+ */
48
+ interface WebSocketLike {
49
+ binaryType: string;
50
+ readonly readyState: number;
51
+ send(data: ArrayBufferView | ArrayBuffer): void;
52
+ close(code?: number, reason?: string): void;
53
+ onopen: ((event: unknown) => void) | null;
54
+ onclose: ((event: unknown) => void) | null;
55
+ onerror: ((event: unknown) => void) | null;
56
+ onmessage: ((event: {
57
+ data: unknown;
58
+ }) => void) | null;
59
+ }
60
+ /** Constructs a {@link WebSocketLike} for a URL. Injected for testability. */
61
+ type WebSocketFactory = (url: string) => WebSocketLike;
62
+ /** Options for {@link noiseWebSocketTransport}. */
63
+ interface NoiseWebSocketTransportOptions {
64
+ /** The coordinator URL, e.g. `wss://<host>/ws-noise`. */
65
+ readonly wsUrl: string;
66
+ /**
67
+ * WebSocket constructor. Defaults to the platform global `WebSocket`
68
+ * (present in browsers and Node 22+). Inject a stub or the `ws` client in
69
+ * environments without one.
70
+ */
71
+ readonly webSocketFactory?: WebSocketFactory;
72
+ /** Milliseconds to wait for the socket to open before failing. Default 30000. */
73
+ readonly connectTimeoutMs?: number;
74
+ }
75
+
76
+ export type { ConnectionState as C, NoiseWebSocketTransportOptions as N, Transport as T, Unsubscribe as U, WebSocketFactory as W, WebSocketLike as a };
@@ -0,0 +1,67 @@
1
+ type CoordinatorEndpoint = {
2
+ readonly wsUrl: string;
3
+ readonly expectedHostname: string;
4
+ readonly releasePin: CoordinatorReleasePin;
5
+ readonly requiredMode: "prod" | "dev" | "auto";
6
+ readonly allowLocalAttestation?: boolean;
7
+ readonly roleHint?: "leader" | "watcher";
8
+ readonly weight?: number;
9
+ };
10
+ type CoordinatorReleasePin = {
11
+ readonly mrtd: string;
12
+ readonly binaryHash?: string;
13
+ readonly intelRootFingerprint?: string;
14
+ readonly allowMissingDcapCollateral?: boolean;
15
+ readonly azureMaa?: AzureMaaPin;
16
+ };
17
+ type AzureMaaPin = {
18
+ readonly issuer: string;
19
+ readonly jwksUrl: string;
20
+ readonly policyHash: string;
21
+ };
22
+ type CoordinatorPoolConfig = {
23
+ readonly endpoints: readonly CoordinatorEndpoint[];
24
+ readonly reattestEveryMs?: number;
25
+ readonly failoverDebounceMs?: number;
26
+ readonly maxReconnectAttempts?: number;
27
+ readonly noiseTransportTimeoutMs?: number;
28
+ readonly preferLeader?: boolean;
29
+ readonly allowedRoles?: readonly ("leader" | "watcher")[];
30
+ };
31
+ type LpPositionView = {
32
+ readonly id: string;
33
+ readonly status: "dkg_pending" | "active" | "withdrawing" | "closed";
34
+ readonly targetShardCount: number;
35
+ readonly authPublicKey: string;
36
+ readonly refillPublicKey: string;
37
+ readonly withdrawalCommitment: string;
38
+ readonly committedLamports: number;
39
+ readonly earnedLamports: number;
40
+ readonly refillThreshold: number;
41
+ readonly shards: readonly {
42
+ readonly [key: string]: unknown;
43
+ }[];
44
+ readonly createdAt: number;
45
+ };
46
+ type PayoutDestination = {
47
+ readonly address: string;
48
+ readonly sharePercent: number;
49
+ readonly minDelayMs?: number;
50
+ readonly maxDelayMs?: number;
51
+ readonly minLamports?: number;
52
+ };
53
+ type PayoutPolicy = {
54
+ readonly destinations: readonly PayoutDestination[];
55
+ readonly totalDeadlineMs?: number;
56
+ readonly batchExclusionId?: string;
57
+ };
58
+ type StorageEnvelope = {
59
+ readonly namespace: string;
60
+ readonly key: string;
61
+ readonly alg: "AES-GCM" | "none";
62
+ readonly ciphertext: string;
63
+ readonly iv?: string;
64
+ readonly createdAtMs: number;
65
+ };
66
+
67
+ export type { AzureMaaPin as A, CoordinatorEndpoint as C, LpPositionView as L, PayoutPolicy as P, StorageEnvelope as S, CoordinatorPoolConfig as a, CoordinatorReleasePin as b, PayoutDestination as c };