@oxy.so/core 7.30.0 → 7.32.0

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 (40) hide show
  1. package/dist/cjs/api/identity.js +146 -23
  2. package/dist/cjs/crypto/identityMarker.js +15 -0
  3. package/dist/cjs/crypto/index.js +7 -2
  4. package/dist/cjs/crypto/keyManager.js +7 -10
  5. package/dist/cjs/crypto/keychainGroupMigration.js +327 -160
  6. package/dist/cjs/crypto/organizationKeys.js +33 -5
  7. package/dist/cjs/crypto/retiredKeys.js +80 -18
  8. package/dist/cjs/session/authStateStore.js +13 -0
  9. package/dist/cjs/session/index.js +5 -2
  10. package/dist/cjs/utils/keychainAccessGroups.js +208 -51
  11. package/dist/esm/api/identity.js +146 -23
  12. package/dist/esm/crypto/identityMarker.js +14 -0
  13. package/dist/esm/crypto/index.js +3 -3
  14. package/dist/esm/crypto/keyManager.js +9 -12
  15. package/dist/esm/crypto/keychainGroupMigration.js +327 -162
  16. package/dist/esm/crypto/organizationKeys.js +34 -6
  17. package/dist/esm/crypto/retiredKeys.js +76 -17
  18. package/dist/esm/session/authStateStore.js +12 -0
  19. package/dist/esm/session/index.js +1 -1
  20. package/dist/esm/utils/keychainAccessGroups.js +205 -51
  21. package/dist/types/api/identity.d.ts +36 -0
  22. package/dist/types/crypto/identityMarker.d.ts +8 -0
  23. package/dist/types/crypto/index.d.ts +4 -4
  24. package/dist/types/crypto/keychainGroupMigration.d.ts +28 -6
  25. package/dist/types/crypto/organizationKeys.d.ts +4 -2
  26. package/dist/types/crypto/retiredKeys.d.ts +30 -4
  27. package/dist/types/session/authStateStore.d.ts +9 -0
  28. package/dist/types/session/index.d.ts +2 -2
  29. package/dist/types/utils/keychainAccessGroups.d.ts +108 -26
  30. package/package.json +2 -2
  31. package/src/api/identity.ts +185 -40
  32. package/src/crypto/identityMarker.ts +15 -0
  33. package/src/crypto/index.ts +10 -1
  34. package/src/crypto/keyManager.ts +9 -15
  35. package/src/crypto/keychainGroupMigration.ts +396 -186
  36. package/src/crypto/organizationKeys.ts +38 -6
  37. package/src/crypto/retiredKeys.ts +87 -17
  38. package/src/session/authStateStore.ts +14 -0
  39. package/src/session/index.ts +8 -1
  40. package/src/utils/keychainAccessGroups.ts +276 -52
@@ -46,6 +46,7 @@ const keychainAccessGroups_1 = require("../utils/keychainAccessGroups");
46
46
  const platform_1 = require("../utils/platform");
47
47
  const identitySigner_1 = require("./identitySigner");
48
48
  const keychainGroupMigration_1 = require("./keychainGroupMigration");
49
+ const retiredKeys_1 = require("./retiredKeys");
49
50
  const keychainItems_1 = require("./keychainItems");
50
51
  Object.defineProperty(exports, "isOrganizationAccountId", { enumerable: true, get: function () { return keychainItems_1.isOrganizationAccountId; } });
51
52
  const ORGANIZATION_PHRASE_WORDS = 24;
@@ -115,9 +116,7 @@ async function organizationKeyFromPhrase(phrase) {
115
116
  async function secureStore(item) {
116
117
  const raw = await (0, protocol_1.loadSecureStore)();
117
118
  const access = await (0, keychainAccessGroups_1.resolveKeychainAccess)();
118
- if (access.mode === 'grouped' && access.role === 'holder') {
119
- await (0, keychainGroupMigration_1.ensureKeychainGroupsMigrated)();
120
- }
119
+ await (0, keychainGroupMigration_1.prepareKeychainAccess)(access);
121
120
  return (0, keychainAccessGroups_1.groupedKeychainStore)(raw, access, item);
122
121
  }
123
122
  const pairStore = () => secureStore('spending-key');
@@ -208,8 +207,10 @@ async function readLocalPair(accountId) {
208
207
  * it; on iOS only Commons holds the groups it writes (any other app throws).
209
208
  *
210
209
  * Refuses a pair whose public key does not derive from its private key, and a
211
- * phrase that does not derive the pair. Overwrites whatever this device held for
212
- * the organization (a replaced key is the caller's decision, ADR 0061 D7).
210
+ * phrase that does not derive the pair. A DIFFERENT key this device already
211
+ * held for the organization is first kept in the organization's retired ring
212
+ * (ADR 0061 D7 as amended; R4-12): coins under it still need it. When that
213
+ * cannot be confirmed nothing is overwritten and this throws.
213
214
  */
214
215
  async function storeOrganizationKey(accountId, key) {
215
216
  assertAccountId(accountId);
@@ -231,6 +232,18 @@ async function storeOrganizationKey(accountId, key) {
231
232
  throw new Error('On Android only Commons holds organization keys; this app has no identity signer store for them.');
232
233
  }
233
234
  const store = await pairStore();
235
+ const previous = await heldPrivateKey(store, accountId);
236
+ if (previous) {
237
+ const previousPublic = (0, secp256k1_1.deriveSecp256k1PublicKey)(previous);
238
+ if (previousPublic !== publicKey) {
239
+ try {
240
+ await (0, retiredKeys_1.retireIdentityKey)({ privateKey: previous, publicKey: previousPublic }, { accountId });
241
+ }
242
+ catch (error) {
243
+ throw new Error(`organization key: the key this device held could not be kept as a previous key, so it was not replaced (${error instanceof Error ? error.message : 'unknown'})`);
244
+ }
245
+ }
246
+ }
234
247
  await store.setItemAsync((0, keychainItems_1.organizationPrivateKeyName)(accountId), privateKey, pairOptions(store, true));
235
248
  await store.setItemAsync((0, keychainItems_1.organizationPublicKeyName)(accountId), publicKey, pairOptions(store, false));
236
249
  if (signer?.writeOrganization &&
@@ -311,6 +324,21 @@ async function listOrganizationKeys() {
311
324
  return [];
312
325
  return readIndex(await indexStore());
313
326
  }
327
+ /**
328
+ * The private key this device holds for `accountId`, whatever its public half
329
+ * says (an unhealthy pair is still a key coins may sit under): the slot, then
330
+ * on Android the signer store's copy. `null` when there is none.
331
+ */
332
+ async function heldPrivateKey(store, accountId) {
333
+ const local = await store.getItemAsync((0, keychainItems_1.organizationPrivateKeyName)(accountId), pairOptions(store, false));
334
+ if (local && (0, secp256k1_1.isValidSecp256k1PrivateKey)(local))
335
+ return (0, secp256k1_1.normalizeSecp256k1PrivateKey)(local);
336
+ const signer = (0, platform_1.isAndroid)() ? (0, identitySigner_1.registeredIdentitySignerStore)() : null;
337
+ const mirrored = (await signer?.readOrganization?.(accountId)) ?? null;
338
+ return mirrored && (0, secp256k1_1.isValidSecp256k1PrivateKey)(mirrored.privateKey)
339
+ ? (0, secp256k1_1.normalizeSecp256k1PrivateKey)(mirrored.privateKey)
340
+ : null;
341
+ }
314
342
  /** Forget an organization key on this device: its pair, its phrase, its signer copy and its index entry. */
315
343
  async function deleteOrganizationKey(accountId) {
316
344
  assertAccountId(accountId);
@@ -45,11 +45,14 @@
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
46
  exports.retiredKeyScope = retiredKeyScope;
47
47
  exports.retireIdentityKey = retireIdentityKey;
48
+ exports.retireIdentityKeyDuringMigration = retireIdentityKeyDuringMigration;
48
49
  exports.listRetiredIdentityKeys = listRetiredIdentityKeys;
49
50
  exports.getRetiredPrivateKey = getRetiredPrivateKey;
50
51
  exports.forgetRetiredIdentityKey = forgetRetiredIdentityKey;
51
52
  exports.forgetRetiredIdentityKeys = forgetRetiredIdentityKeys;
52
53
  exports.syncRetiredKeys = syncRetiredKeys;
54
+ exports.exportRetiredIdentityKeys = exportRetiredIdentityKeys;
55
+ exports.retiredKeyFromPrivateKey = retiredKeyFromPrivateKey;
53
56
  exports.retiredKeyFromPhrase = retiredKeyFromPhrase;
54
57
  const bip39_1 = require("@scure/bip39");
55
58
  const english_js_1 = require("@scure/bip39/wordlists/english.js");
@@ -59,8 +62,8 @@ const logger_1 = require("../logger");
59
62
  const keychainAccessGroups_1 = require("../utils/keychainAccessGroups");
60
63
  const platform_1 = require("../utils/platform");
61
64
  const identitySigner_1 = require("./identitySigner");
65
+ const keychainItems_1 = require("./keychainItems");
62
66
  const keychainGroupMigration_1 = require("./keychainGroupMigration");
63
- const organizationKeys_1 = require("./organizationKeys");
64
67
  const PERSONAL_SCOPE = 'personal';
65
68
  /** Android, Commons-local: its own Keystore-backed slot, shared with no other key. */
66
69
  const ANDROID_KEYCHAIN_SERVICE = 'oxy_retired_identity';
@@ -71,15 +74,15 @@ const PUBLIC_KEY = /^04[0-9a-f]{128}$/;
71
74
  * The secure store for the ring. On iOS every item is a `spending-key`
72
75
  * (ADR 0062): the private keys AND the index live in the wallet group, which
73
76
  * only Commons and the Peable wallet can read, never the shared one. In
74
- * Commons every access first awaits the access-group migration. On Android
75
- * the grouping is a no-op and Commons' own services below apply.
77
+ * Commons every access first awaits the access-group migration (`gate: false`
78
+ * is the migration itself, keeping a pre-split copy). On Android the grouping
79
+ * is a no-op and Commons' own services below apply.
76
80
  */
77
- async function ringStore() {
81
+ async function ringStore(gate = true) {
78
82
  const raw = await (0, protocol_1.loadSecureStore)();
79
83
  const access = await (0, keychainAccessGroups_1.resolveKeychainAccess)();
80
- if (access.mode === 'grouped' && access.role === 'holder') {
81
- await (0, keychainGroupMigration_1.ensureKeychainGroupsMigrated)();
82
- }
84
+ if (gate)
85
+ await (0, keychainGroupMigration_1.prepareKeychainAccess)(access);
83
86
  return (0, keychainAccessGroups_1.groupedKeychainStore)(raw, access, 'spending-key');
84
87
  }
85
88
  /** The ring a selector names: `personal`, or the organization's account id. */
@@ -87,7 +90,7 @@ function retiredKeyScope(selector) {
87
90
  const accountId = selector?.accountId;
88
91
  if (accountId === undefined)
89
92
  return PERSONAL_SCOPE;
90
- return (0, organizationKeys_1.isOrganizationAccountId)(accountId) ? accountId : null;
93
+ return (0, keychainItems_1.isOrganizationAccountId)(accountId) ? accountId : null;
91
94
  }
92
95
  function canonicalPublicKey(publicKey) {
93
96
  try {
@@ -134,7 +137,7 @@ function isIndexEntry(value) {
134
137
  return false;
135
138
  const entry = value;
136
139
  return (typeof entry.scope === 'string' &&
137
- (entry.scope === PERSONAL_SCOPE || (0, organizationKeys_1.isOrganizationAccountId)(entry.scope)) &&
140
+ (entry.scope === PERSONAL_SCOPE || (0, keychainItems_1.isOrganizationAccountId)(entry.scope)) &&
138
141
  typeof entry.publicKey === 'string' &&
139
142
  PUBLIC_KEY.test(entry.publicKey) &&
140
143
  typeof entry.retiredAt === 'number' &&
@@ -171,13 +174,24 @@ function toListed(entry) {
171
174
  ? { publicKey: entry.publicKey, retiredAt: entry.retiredAt }
172
175
  : { publicKey: entry.publicKey, accountId: entry.scope, retiredAt: entry.retiredAt };
173
176
  }
174
- /** Whether this app writes the ring: Commons (Android: the signer store it registers; iOS: native). */
175
- function assertMayWrite() {
177
+ /**
178
+ * Whether this app writes the ring: Commons only (Android: the signer store it
179
+ * registers; iOS: the keychain role `holder`). The Peable wallet holds the
180
+ * wallet group too, but only reads, derives and signs: a key the wallet could
181
+ * add to the ring is a key it could choose (R4-14).
182
+ */
183
+ async function assertMayWrite() {
176
184
  if ((0, platform_1.isWeb)())
177
185
  throw new Error('retired key: only a native device holds one');
178
186
  if ((0, platform_1.isAndroid)() && !(0, identitySigner_1.registeredIdentitySignerStore)()?.writeRetired) {
179
187
  throw new Error('On Android only Commons holds retired keys; this app has no identity signer store for them.');
180
188
  }
189
+ if ((0, platform_1.isIOS)()) {
190
+ const access = await (0, keychainAccessGroups_1.resolveKeychainAccess)();
191
+ if (access.mode === 'grouped' && access.role !== 'holder') {
192
+ throw new Error('On iOS only Commons writes retired keys; this app may only read them.');
193
+ }
194
+ }
181
195
  }
182
196
  /**
183
197
  * Keep `key` in the ring of `selector`'s account. Commons only. Idempotent: a
@@ -187,16 +201,27 @@ function assertMayWrite() {
187
201
  * caller about to replace the key can stop before anything is lost.
188
202
  */
189
203
  async function retireIdentityKey(key, selector) {
204
+ await keepRetired(key, selector, true);
205
+ }
206
+ /**
207
+ * {@link retireIdentityKey} from inside the iOS access-group migration, which
208
+ * keeps a replaced pre-split copy before deleting it from the shared group and
209
+ * cannot await itself. @internal
210
+ */
211
+ async function retireIdentityKeyDuringMigration(key, selector) {
212
+ await keepRetired(key, selector, false);
213
+ }
214
+ async function keepRetired(key, selector, gate) {
190
215
  const scope = retiredKeyScope(selector);
191
216
  if (!scope)
192
217
  throw new Error('retired key: accountId must be a 24-hex or uuid account id');
193
- assertMayWrite();
218
+ await assertMayWrite();
194
219
  if (!isHealthyPair(key.privateKey, key.publicKey)) {
195
220
  throw new Error('retired key: the public key does not derive from the private key');
196
221
  }
197
222
  const privateKey = (0, secp256k1_1.normalizeSecp256k1PrivateKey)(key.privateKey);
198
223
  const publicKey = (0, secp256k1_1.normalizeSecp256k1PublicKey)(key.publicKey);
199
- const store = await ringStore();
224
+ const store = await ringStore(gate);
200
225
  await store.setItemAsync(privateKeyName(scope, publicKey), privateKey, privateOptions(store, true));
201
226
  const readBack = await store.getItemAsync(privateKeyName(scope, publicKey), privateOptions(store, false));
202
227
  if (readBack !== privateKey) {
@@ -294,7 +319,7 @@ async function forgetRetiredIdentityKey(publicKey, selector) {
294
319
  const canonical = canonicalPublicKey(publicKey);
295
320
  if (!scope || !canonical)
296
321
  throw new Error('retired key: invalid selector or public key');
297
- assertMayWrite();
322
+ await assertMayWrite();
298
323
  const store = await ringStore();
299
324
  await store.deleteItemAsync(privateKeyName(scope, canonical), privateOptions(store, false));
300
325
  const signer = (0, platform_1.isAndroid)() ? (0, identitySigner_1.registeredIdentitySignerStore)() : null;
@@ -302,10 +327,12 @@ async function forgetRetiredIdentityKey(publicKey, selector) {
302
327
  await writeIndex(store, (await readIndex(store)).filter((entry) => !(entry.scope === scope && entry.publicKey === canonical)));
303
328
  }
304
329
  /**
305
- * Forget every retired key of one ring (the person's, or an organization's):
306
- * called when the identity itself is deleted from this device, so a phone
307
- * handed on keeps none of the person's old keys. Commons only. Resolves how
308
- * many it removed.
330
+ * Forget every retired key of one ring (the person's, or an organization's).
331
+ * Commons only, and only when the person deletes their Oxy ACCOUNT (Commons'
332
+ * delete-account flow), which tells them the coins go with it. Deleting the
333
+ * identity from this device — "Start over", a forced delete — never calls it:
334
+ * the ring is money, and the same person restoring their identity later must
335
+ * find it (R4-4). Resolves how many it removed.
309
336
  */
310
337
  async function forgetRetiredIdentityKeys(selector) {
311
338
  const scope = retiredKeyScope(selector);
@@ -352,6 +379,41 @@ async function syncRetiredKeys() {
352
379
  }
353
380
  return mirrored;
354
381
  }
382
+ /**
383
+ * Every retired key of `selector`'s ring WITH its private half, for the
384
+ * encrypted identity backup (`oxy.identity.backup.create`), which carries them
385
+ * under the CURRENT phrase so a lost phone costs no more than the current
386
+ * phrase does (R4-4). Commons only; an entry whose private half is missing or
387
+ * does not derive its public key is left out. Never log or transmit the result
388
+ * except inside that encrypted envelope.
389
+ */
390
+ async function exportRetiredIdentityKeys(selector) {
391
+ const scope = retiredKeyScope(selector);
392
+ if (!scope || (0, platform_1.isWeb)())
393
+ return [];
394
+ await assertMayWrite();
395
+ const out = [];
396
+ for (const entry of await listRetiredIdentityKeys(selector)) {
397
+ const privateKey = await getRetiredPrivateKey(entry.publicKey, selector);
398
+ if (privateKey)
399
+ out.push({ privateKey, publicKey: entry.publicKey, retiredAt: entry.retiredAt });
400
+ }
401
+ return out;
402
+ }
403
+ /**
404
+ * The pair a previous key's raw PRIVATE KEY gives (64 hex, an optional `0x`),
405
+ * for a person whose old identity was imported as a private key and so has no
406
+ * phrase to re-enter. Stores nothing: the caller checks the public key against
407
+ * the account's key history and only then calls {@link retireIdentityKey}.
408
+ */
409
+ function retiredKeyFromPrivateKey(privateKeyHex) {
410
+ const trimmed = privateKeyHex.trim().toLowerCase().replace(/^0x/, '');
411
+ if (!/^[0-9a-f]{64}$/.test(trimmed) || !(0, secp256k1_1.isValidSecp256k1PrivateKey)(trimmed)) {
412
+ throw new Error('retired key: not a valid private key');
413
+ }
414
+ const privateKey = (0, secp256k1_1.normalizeSecp256k1PrivateKey)(trimmed);
415
+ return { privateKey, publicKey: publicKeyOf(privateKey) };
416
+ }
355
417
  /**
356
418
  * The pair a previous recovery phrase derives (`seed[0:32]`, the personal-root
357
419
  * and organization-key derivation; 12–24 words). Stores nothing: the caller
@@ -20,6 +20,7 @@
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.AUTH_STATE_TOKEN_STORAGE_KEY = exports.AUTOMATIC_IDENTITY_SIGNIN_SUPPRESSED_KEY = exports.AUTH_STATE_STORAGE_KEY = void 0;
22
22
  exports.matchesAuthState = matchesAuthState;
23
+ exports.nativeSessionItemNames = nativeSessionItemNames;
23
24
  exports.createMemoryAuthStateStore = createMemoryAuthStateStore;
24
25
  exports.createWebAuthStateStore = createWebAuthStateStore;
25
26
  exports.createNativeAuthStateStore = createNativeAuthStateStore;
@@ -53,6 +54,18 @@ function matchesAuthState(actual, expected) {
53
54
  */
54
55
  exports.AUTH_STATE_STORAGE_KEY = 'oxy.auth.v1';
55
56
  exports.AUTOMATIC_IDENTITY_SIGNIN_SUPPRESSED_KEY = 'oxy.auth.automatic-identity-signin-suppressed.v1';
57
+ /**
58
+ * What `ownKeychainItemPlan` (ADR 0062 D6) must know about a key a native
59
+ * session store keeps — this module's three and the identity pin: every Oxy app
60
+ * writes it under the same name, so on iOS a copy in the shared group may be
61
+ * another app's session and is never read as this app's. The sign-out marker
62
+ * can only withhold, so a shared copy of it still counts.
63
+ */
64
+ function nativeSessionItemNames(key) {
65
+ return key === exports.AUTOMATIC_IDENTITY_SIGNIN_SUPPRESSED_KEY
66
+ ? 'every-oxy-app-withholding'
67
+ : 'every-oxy-app';
68
+ }
56
69
  /**
57
70
  * Versioned BEST-EFFORT warm-token storage key. Holds the short-lived
58
71
  * `{ accessToken, expiresAt }` pair only. Its write is genuinely non-fatal — a
@@ -8,8 +8,8 @@
8
8
  * the API with a token it already has never needs it.
9
9
  */
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.establishIdentitySession = exports.resolveIdentityPin = exports.IDENTITY_PIN_STORAGE_KEY = exports.identityPinMatches = exports.createMemoryIdentityPinStore = exports.createNativeIdentityPinStore = exports.createWebIdentityPinStore = exports.resolveKeychainAccess = exports.deleteThroughPlan = exports.readThroughPlan = exports.ownKeychainItemPlan = exports.keychainAccessGroupValue = exports.KeychainAccessUnavailableError = exports.readLocalDeviceCredential = exports.publishProvenDeviceCredential = exports.normalizeSharedDeviceSessionRead = exports.decideSharedDevicePublish = exports.decideSharedDeviceJoin = exports.createSharedMirroringAuthStateStore = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.resolveAccountDelegationAccess = exports.canSwitchIntoAccount = exports.isSwitchTargetAccount = exports.deviceComparisonCode = exports.showsPrincipalHeaders = exports.buildSwitcherRows = exports.resolveDeviceContext = exports.resolveActiveContext = exports.projectDevicePrincipals = exports.directoryHandle = exports.directoryDisplayName = exports.canActivateContext = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.DeviceManager = void 0;
12
- exports.runColdBoot = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = void 0;
11
+ exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.establishIdentitySession = exports.resolveIdentityPin = exports.IDENTITY_PIN_STORAGE_KEY = exports.identityPinMatches = exports.createMemoryIdentityPinStore = exports.createNativeIdentityPinStore = exports.createWebIdentityPinStore = exports.resolveKeychainAccess = exports.deleteThroughPlan = exports.readThroughPlan = exports.ownKeychainItemPlan = exports.keychainAccessGroupValue = exports.KeychainAccessUnavailableError = exports.readLocalDeviceCredential = exports.publishProvenDeviceCredential = exports.normalizeSharedDeviceSessionRead = exports.decideSharedDevicePublish = exports.decideSharedDeviceJoin = exports.createSharedMirroringAuthStateStore = exports.AUTOMATIC_IDENTITY_SIGNIN_SUPPRESSED_KEY = exports.AUTH_STATE_TOKEN_STORAGE_KEY = exports.AUTH_STATE_STORAGE_KEY = exports.nativeSessionItemNames = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.resolveAccountDelegationAccess = exports.canSwitchIntoAccount = exports.isSwitchTargetAccount = exports.deviceComparisonCode = exports.showsPrincipalHeaders = exports.buildSwitcherRows = exports.resolveDeviceContext = exports.resolveActiveContext = exports.projectDevicePrincipals = exports.directoryHandle = exports.directoryDisplayName = exports.canActivateContext = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.DeviceManager = void 0;
12
+ exports.runColdBoot = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = void 0;
13
13
  // Session code reaches the identity key (identity-bound sessions), so the
14
14
  // crypto shim goes first — see `../crypto/polyfill`.
15
15
  require("../crypto/polyfill");
@@ -95,7 +95,10 @@ var authStateStore_1 = require("./authStateStore");
95
95
  Object.defineProperty(exports, "createWebAuthStateStore", { enumerable: true, get: function () { return authStateStore_1.createWebAuthStateStore; } });
96
96
  Object.defineProperty(exports, "createNativeAuthStateStore", { enumerable: true, get: function () { return authStateStore_1.createNativeAuthStateStore; } });
97
97
  Object.defineProperty(exports, "createMemoryAuthStateStore", { enumerable: true, get: function () { return authStateStore_1.createMemoryAuthStateStore; } });
98
+ Object.defineProperty(exports, "nativeSessionItemNames", { enumerable: true, get: function () { return authStateStore_1.nativeSessionItemNames; } });
98
99
  Object.defineProperty(exports, "AUTH_STATE_STORAGE_KEY", { enumerable: true, get: function () { return authStateStore_1.AUTH_STATE_STORAGE_KEY; } });
100
+ Object.defineProperty(exports, "AUTH_STATE_TOKEN_STORAGE_KEY", { enumerable: true, get: function () { return authStateStore_1.AUTH_STATE_TOKEN_STORAGE_KEY; } });
101
+ Object.defineProperty(exports, "AUTOMATIC_IDENTITY_SIGNIN_SUPPRESSED_KEY", { enumerable: true, get: function () { return authStateStore_1.AUTOMATIC_IDENTITY_SIGNIN_SUPPRESSED_KEY; } });
99
102
  // The shared NATIVE DeviceSession credential — how several official apps on one
100
103
  // device end up on ONE `DeviceSession` and therefore one active context. It is an
101
104
  // ordinary revocable `deviceId` + `deviceSecret`, deliberately NOT the