@glyphteck/veyl 0.29.2 → 0.30.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 (3) hide show
  1. package/dist/cli.js +195 -130
  2. package/dist/index.js +195 -130
  3. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -61224,11 +61224,13 @@ function deriveKey(input, label, parts = [], size = 32) {
61224
61224
  "use client";
61225
61225
  var VAULT_SIGNATURE_PROTOCOL = "veyl-vault-signature-v1";
61226
61226
  var VAULT_SIGNING_KEY_SCOPE = "vault-signing-key-v1";
61227
- var VAULT_LEASE_PURPOSE = "vault-lease";
61228
61227
  var VAULT_SIGNATURE_PURPOSES = Object.freeze({
61228
+ CREATE_PASSKEY_LINK: "create-passkey-link",
61229
61229
  DELETE_ACCOUNT: "delete-account",
61230
+ DELETE_PASSKEY: "delete-passkey",
61230
61231
  LOGOUT_ALL_DEVICES: "logout-all-devices",
61231
61232
  SET_CHAT_IDENTITY: "set-chat-identity",
61233
+ SET_SETTINGS: "set-settings",
61232
61234
  SET_WALLET_IDENTITY: "set-wallet-identity"
61233
61235
  });
61234
61236
  var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
@@ -61271,12 +61273,12 @@ function cleanGeneration(value) {
61271
61273
  }
61272
61274
  return generation;
61273
61275
  }
61274
- function cleanClientSessionId(value) {
61275
- const clientSessionId = typeof value === "string" ? value.trim() : "";
61276
- if (!/^[A-Za-z0-9_-]{24,80}$/u.test(clientSessionId)) {
61277
- throw signatureError("invalid-client-session", "client session required");
61276
+ function cleanSessionId(value) {
61277
+ const sessionId = typeof value === "string" ? value.trim() : "";
61278
+ if (!/^[A-Za-z0-9_-]{24,80}$/u.test(sessionId)) {
61279
+ throw signatureError("invalid-session", "session required");
61278
61280
  }
61279
- return clientSessionId;
61281
+ return sessionId;
61280
61282
  }
61281
61283
  function vaultSigningPublicKey(masterSeed) {
61282
61284
  const secret = deriveKey(toBytes(masterSeed, "master seed"), VAULT_SIGNING_KEY_SCOPE);
@@ -61323,7 +61325,7 @@ function createVaultSignature(signer, claims, purpose, payload = null, now = Dat
61323
61325
  VAULT_SIGNATURE_PROTOCOL,
61324
61326
  uid,
61325
61327
  cleanGeneration(claims?.sessionGeneration),
61326
- cleanClientSessionId(claims?.clientSessionId),
61328
+ cleanSessionId(claims?.sessionId),
61327
61329
  cleanPurpose(purpose),
61328
61330
  now,
61329
61331
  base64url2(randomBytes3(24)),
@@ -61582,12 +61584,12 @@ async function encryptSeedWithPassword(seed, pwd, options = {}) {
61582
61584
  const params = normalizeVaultKdf(options.params);
61583
61585
  const deriveKey2 = getVaultDeriveKey(options);
61584
61586
  const registry = normalizeSecretRegistry(options.registry || createSecretRegistry());
61585
- const vaultSigningPK = vaultSigningPublicKey(seed);
61587
+ const vaultPK = vaultSigningPublicKey(seed);
61586
61588
  const sealedRegistry = await sealSecretRegistry(seed, registry);
61587
61589
  const key = await deriveKey2(pwd, salt, params);
61588
61590
  try {
61589
61591
  const { iv, ct } = await sealAes(key, seed);
61590
- return { crypto: options.crypto || VAULT_CRYPTO, kdf: params, ciphertext: ct, salt, iv, registry: sealedRegistry, vaultSigningPK };
61592
+ return { crypto: options.crypto || VAULT_CRYPTO, kdf: params, ciphertext: ct, salt, iv, registry: sealedRegistry, vaultPK };
61591
61593
  } finally {
61592
61594
  key.fill(0);
61593
61595
  }
@@ -63378,7 +63380,7 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
63378
63380
  network,
63379
63381
  vaultSigner,
63380
63382
  vaultAccess,
63381
- vaultSigningPK: vaultSigner.publicKey
63383
+ vaultPK: vaultSigner.publicKey
63382
63384
  });
63383
63385
  } catch (error) {
63384
63386
  closeSessionResources({ wallet, chatPrivateKey, vaultAccess, vaultSigner });
@@ -152230,6 +152232,15 @@ function authSessionGeneration(value) {
152230
152232
  const generation = Number(value);
152231
152233
  return Number.isSafeInteger(generation) && generation > 0 ? generation : null;
152232
152234
  }
152235
+ function authCredentialFromClaims(claims) {
152236
+ const kind = typeof claims?.credentialKind === "string" ? claims.credentialKind.trim() : "";
152237
+ const id = typeof claims?.credentialId === "string" ? claims.credentialId.trim() : "";
152238
+ return /^(machine|passkey)$/u.test(kind) && /^[A-Za-z0-9_-]{1,1500}$/u.test(id) ? { kind, id } : null;
152239
+ }
152240
+ function authCredentialDoc(db, credential) {
152241
+ const collectionName = credential?.kind === "passkey" ? "passkeys" : credential?.kind === "machine" ? "machineCredentials" : "";
152242
+ return collectionName ? doc(db, collectionName, credential.id) : null;
152243
+ }
152233
152244
  function vaultSignatureError(code, message) {
152234
152245
  const error = new Error(message);
152235
152246
  error.code = `vault-signature/${code}`;
@@ -152312,9 +152323,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152312
152323
  throw new Error("createFirebaseCloud requires db");
152313
152324
  }
152314
152325
  let activeVaultSigner = null;
152315
- let vaultLeaseExpiresAt = 0;
152316
- let vaultLeaseRequest = null;
152317
- let vaultOpenRequest = null;
152318
152326
  function pageTs(value) {
152319
152327
  if (value instanceof Timestamp2) {
152320
152328
  return value;
@@ -152475,11 +152483,12 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152475
152483
  requireUid(uid);
152476
152484
  const user = requireAuth().currentUser;
152477
152485
  let active = true;
152478
- let unsubscribe = () => {};
152486
+ let unsubscribeSession = () => {};
152487
+ let unsubscribeCredential = () => {};
152479
152488
  if (!user || user.uid !== uid) {
152480
152489
  Promise.resolve().then(() => {
152481
152490
  if (active)
152482
- onUpdate?.({ active: false, generation: null, currentGeneration: null });
152491
+ onUpdate?.({ active: false, generation: null, currentGeneration: null, authCredential: null });
152483
152492
  });
152484
152493
  return () => {
152485
152494
  active = false;
@@ -152489,19 +152498,43 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152489
152498
  if (!active)
152490
152499
  return;
152491
152500
  const generation = authSessionGeneration(result?.claims?.sessionGeneration);
152492
- if (!generation) {
152493
- onUpdate?.({ active: false, generation: null, currentGeneration: null });
152501
+ const sessionId = typeof result?.claims?.sessionId === "string" ? result.claims.sessionId : "";
152502
+ const authCredential = authCredentialFromClaims(result?.claims);
152503
+ const credentialRef = authCredentialDoc(db, authCredential);
152504
+ if (!generation || !sessionId || !authCredential || !credentialRef) {
152505
+ onUpdate?.({ active: false, generation: null, currentGeneration: null, authCredential: null });
152494
152506
  return;
152495
152507
  }
152496
- unsubscribe = onSnapshot(doc(db, "auth_sessions", uid), (snap) => {
152497
- if (!active)
152508
+ let sessionReady = false;
152509
+ let credentialReady = false;
152510
+ let currentGeneration = null;
152511
+ let credentialActive = false;
152512
+ const emit = () => {
152513
+ if (!active || !sessionReady || !credentialReady)
152498
152514
  return;
152499
- const currentGeneration = authSessionGeneration(snap.data()?.generation);
152500
152515
  onUpdate?.({
152501
- active: currentGeneration === generation,
152516
+ active: currentGeneration === generation && credentialActive,
152502
152517
  generation,
152503
- currentGeneration
152518
+ currentGeneration,
152519
+ authCredential
152504
152520
  });
152521
+ };
152522
+ unsubscribeSession = onSnapshot(doc(db, "users", uid, "auth", "session"), (snap) => {
152523
+ if (!active)
152524
+ return;
152525
+ sessionReady = true;
152526
+ currentGeneration = authSessionGeneration(snap.data()?.generation);
152527
+ emit();
152528
+ }, (error) => {
152529
+ if (active)
152530
+ onError?.(error);
152531
+ });
152532
+ unsubscribeCredential = onSnapshot(credentialRef, (snap) => {
152533
+ if (!active)
152534
+ return;
152535
+ credentialReady = true;
152536
+ credentialActive = snap.exists() && snap.data()?.uid === uid;
152537
+ emit();
152505
152538
  }, (error) => {
152506
152539
  if (active)
152507
152540
  onError?.(error);
@@ -152512,9 +152545,43 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152512
152545
  });
152513
152546
  return () => {
152514
152547
  active = false;
152515
- unsubscribe();
152548
+ unsubscribeSession();
152549
+ unsubscribeCredential();
152516
152550
  };
152517
152551
  }
152552
+ function watchPasskeyLinks(uid, onUpdate, onError) {
152553
+ requireUid(uid);
152554
+ return onSnapshot(query(collection(db, "passkeyLinks"), where("uid", "==", uid)), (snapshot) => {
152555
+ const links2 = snapshot.docs.map((snap) => {
152556
+ const data = snap.data() || {};
152557
+ if (data.status !== "pending")
152558
+ return null;
152559
+ return {
152560
+ id: snap.id,
152561
+ type: "pending",
152562
+ status: "pending",
152563
+ createdAt: timestampMs(data.createdAt, null)
152564
+ };
152565
+ }).filter(Boolean).sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
152566
+ onUpdate?.(links2);
152567
+ }, onError);
152568
+ }
152569
+ function watchPasskeys(uid, onUpdate, onError) {
152570
+ requireUid(uid);
152571
+ return onSnapshot(query(collection(db, "passkeys"), where("uid", "==", uid)), (snapshot) => {
152572
+ const passkeys = snapshot.docs.map((snap) => {
152573
+ const data = snap.data() || {};
152574
+ const label = typeof data.label === "string" ? data.label.trim() : "";
152575
+ return {
152576
+ id: snap.id,
152577
+ type: "passkey",
152578
+ label: label || "unnamed passkey",
152579
+ createdAt: timestampMs(data.createdAt, null)
152580
+ };
152581
+ }).filter(Boolean).sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
152582
+ onUpdate?.(passkeys);
152583
+ }, onError);
152584
+ }
152518
152585
  async function logout() {
152519
152586
  await signOut(requireAuth());
152520
152587
  return true;
@@ -152523,25 +152590,25 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152523
152590
  await callVaultFunction("logoutDevices", VAULT_SIGNATURE_PURPOSES.LOGOUT_ALL_DEVICES);
152524
152591
  return true;
152525
152592
  }
152526
- async function clientSessionClaims() {
152593
+ async function sessionClaims() {
152527
152594
  const user = requireAuth().currentUser;
152528
152595
  if (!user?.uid) {
152529
152596
  throw new Error("signed in user required");
152530
152597
  }
152531
152598
  const token = await user.getIdTokenResult();
152532
152599
  const sessionGeneration = authSessionGeneration(token?.claims?.sessionGeneration);
152533
- const clientSessionId = token?.claims?.clientSessionId;
152534
- if (!sessionGeneration || typeof clientSessionId !== "string" || !clientSessionId) {
152535
- throw new Error("invalid client session");
152600
+ const sessionId = token?.claims?.sessionId;
152601
+ if (!sessionGeneration || typeof sessionId !== "string" || !sessionId) {
152602
+ throw new Error("invalid session");
152536
152603
  }
152537
152604
  return {
152538
152605
  uid: user.uid,
152539
152606
  sessionGeneration,
152540
- clientSessionId
152607
+ sessionId
152541
152608
  };
152542
152609
  }
152543
152610
  function vaultSignatureClaims() {
152544
- return clientSessionClaims();
152611
+ return sessionClaims();
152545
152612
  }
152546
152613
  async function signVaultRequest(purpose, payload = null, signer = activeVaultSigner) {
152547
152614
  if (!signer) {
@@ -152551,71 +152618,22 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152551
152618
  return createVaultSignature(signer, await vaultSignatureClaims(), purpose, payload);
152552
152619
  } catch (error) {
152553
152620
  if (!error?.code) {
152554
- error.code = "vault-signature/proof-construction";
152621
+ error.code = "vault-signature/construction";
152555
152622
  }
152556
152623
  throw error;
152557
152624
  }
152558
152625
  }
152559
- async function grantVaultLease(signer = activeVaultSigner, force = false) {
152560
- if (!signer || signer !== activeVaultSigner) {
152561
- throw new Error("unlocked vault required");
152562
- }
152563
- if (!force && vaultLeaseExpiresAt - Date.now() > 15000) {
152564
- return { expiresAt: vaultLeaseExpiresAt };
152565
- }
152566
- if (vaultLeaseRequest?.signer === signer) {
152567
- return vaultLeaseRequest.promise;
152568
- }
152569
- const promise = (async () => {
152570
- const result = await callFunction("grantVaultLease", {
152571
- vaultSignature: await signVaultRequest(VAULT_LEASE_PURPOSE, null, signer)
152572
- });
152573
- if (signer !== activeVaultSigner) {
152574
- throw new Error("vault locked during authorization");
152575
- }
152576
- const expiresAt = Number(result?.expiresAt);
152577
- if (!Number.isFinite(expiresAt) || expiresAt <= Date.now()) {
152578
- throw new Error("invalid vault lease");
152579
- }
152580
- vaultLeaseExpiresAt = expiresAt;
152581
- return { expiresAt };
152582
- })().finally(() => {
152583
- if (vaultLeaseRequest?.promise === promise) {
152584
- vaultLeaseRequest = null;
152585
- }
152586
- });
152587
- vaultLeaseRequest = { signer, promise };
152588
- return promise;
152589
- }
152590
152626
  async function openVaultSignature(signer) {
152591
152627
  if (!signer?.publicKey || typeof signer?.sign !== "function") {
152592
152628
  throw vaultSignatureError("invalid-signer", "vault signer required");
152593
152629
  }
152594
152630
  if (activeVaultSigner?.closed) {
152595
152631
  activeVaultSigner = null;
152596
- vaultLeaseExpiresAt = 0;
152597
- vaultLeaseRequest = null;
152598
- vaultOpenRequest = null;
152599
152632
  }
152600
152633
  if (activeVaultSigner && activeVaultSigner !== signer) {
152601
152634
  throw vaultSignatureError("already-open", "vault signature already open");
152602
152635
  }
152603
152636
  activeVaultSigner = signer;
152604
- const openPromise = grantVaultLease(signer, true);
152605
- vaultOpenRequest = { signer, promise: openPromise };
152606
- try {
152607
- await openPromise;
152608
- } catch (error) {
152609
- if (activeVaultSigner === signer) {
152610
- activeVaultSigner = null;
152611
- vaultLeaseExpiresAt = 0;
152612
- }
152613
- throw error;
152614
- } finally {
152615
- if (vaultOpenRequest?.promise === openPromise) {
152616
- vaultOpenRequest = null;
152617
- }
152618
- }
152619
152637
  let closed = false;
152620
152638
  return {
152621
152639
  close() {
@@ -152625,8 +152643,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152625
152643
  if (activeVaultSigner !== signer)
152626
152644
  return;
152627
152645
  activeVaultSigner = null;
152628
- vaultLeaseExpiresAt = 0;
152629
- callFunction("dropVaultLease").catch(() => {});
152630
152646
  }
152631
152647
  };
152632
152648
  }
@@ -152634,9 +152650,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152634
152650
  const signer = activeVaultSigner;
152635
152651
  if (!signer)
152636
152652
  throw new Error("unlocked vault required");
152637
- if (vaultOpenRequest?.signer === signer) {
152638
- await vaultOpenRequest.promise;
152639
- }
152640
152653
  if (signer !== activeVaultSigner) {
152641
152654
  throw vaultSignatureError("locked", "unlocked vault required");
152642
152655
  }
@@ -152666,10 +152679,10 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152666
152679
  const snap = await getDoc(doc(db, "seeds", uid));
152667
152680
  return snap.exists();
152668
152681
  }
152669
- async function writeVault(uid, vault, { vaultSigningPK } = {}) {
152682
+ async function writeVault(uid, vault, { vaultPK } = {}) {
152670
152683
  requireUid(uid);
152671
- if (!vault || !vaultSigningPK) {
152672
- throw new Error("vault enrollment required");
152684
+ if (!vault || !vaultPK) {
152685
+ throw new Error("vault and public key required");
152673
152686
  }
152674
152687
  const user = requireAuth().currentUser;
152675
152688
  if (user?.uid !== uid) {
@@ -152677,7 +152690,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152677
152690
  }
152678
152691
  await callFunction("createVault", {
152679
152692
  vault: cloudBytesBase64(vault, "vault bytes"),
152680
- vaultSigningPK
152693
+ vaultPK
152681
152694
  });
152682
152695
  return true;
152683
152696
  }
@@ -152779,10 +152792,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152779
152792
  return openSettings(key, uid, readCloudBytes(saved, "settings body"));
152780
152793
  }
152781
152794
  const settings = normalizeSettings(defaultSettings);
152782
- await grantVaultLease(activeVaultSigner);
152783
- await setDoc(doc(db, "users", uid), {
152784
- settings: writeCloudBytes(await sealSettings(key, uid, settings), "settings body")
152785
- }, { merge: true });
152795
+ await callVaultFunction("setSettings", VAULT_SIGNATURE_PURPOSES.SET_SETTINGS, { settings: bytesBase64(await sealSettings(key, uid, settings)) });
152786
152796
  return settings;
152787
152797
  }
152788
152798
  async function writeSettings(uid, settings, { currentSettings, key } = {}) {
@@ -152793,10 +152803,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152793
152803
  const base = currentSettings || await readSettings(uid, key);
152794
152804
  const nextSettings = normalizeSettings(settings, base);
152795
152805
  const body = await sealSettings(key, uid, nextSettings);
152796
- await grantVaultLease(activeVaultSigner);
152797
- await setDoc(doc(db, "users", uid), {
152798
- settings: writeCloudBytes(body, "settings body")
152799
- }, { merge: true });
152806
+ await callVaultFunction("setSettings", VAULT_SIGNATURE_PURPOSES.SET_SETTINGS, { settings: bytesBase64(body) });
152800
152807
  return nextSettings;
152801
152808
  }
152802
152809
  async function writeUserActive(uid, active) {
@@ -152853,7 +152860,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152853
152860
  }
152854
152861
  async function readPeer(uid) {
152855
152862
  requireUid(uid);
152856
- const snap = await getDoc(doc(db, "profiles", uid));
152863
+ const snap = await getDocFromServer(doc(db, "profiles", uid));
152857
152864
  return peerRecordFromDoc(snap);
152858
152865
  }
152859
152866
  async function readPeerActive(uid) {
@@ -153120,7 +153127,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
153120
153127
  },
153121
153128
  vaultSignature: {
153122
153129
  open: openVaultSignature,
153123
- ensure: () => grantVaultLease(activeVaultSigner),
153124
153130
  sign: signVaultRequest,
153125
153131
  call: callVaultFunction
153126
153132
  },
@@ -153135,6 +153141,19 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
153135
153141
  start: (payload) => callFunction("passkeyRegisterOptions", payload),
153136
153142
  token: (payload) => callFunction("passkeyRegisterVerify", payload),
153137
153143
  finish: (payload) => finishAuth("passkeyRegisterVerify", payload)
153144
+ },
153145
+ passkeys: {
153146
+ watch: watchPasskeys,
153147
+ deleteOptions: (payload) => callFunction("passkeyDeleteOptions", payload),
153148
+ delete: (id, assertion = null) => callVaultFunction("deletePasskey", VAULT_SIGNATURE_PURPOSES.DELETE_PASSKEY, assertion ? { id, assertion } : { id })
153149
+ },
153150
+ passkeyLinks: {
153151
+ info: (payload) => callFunction("passkeyLinkInfo", payload),
153152
+ start: (payload) => callFunction("passkeyLinkOptions", payload),
153153
+ use: (payload) => callFunction("usePasskeyLink", payload),
153154
+ activate: (token) => signInWithCustomToken(requireAuth(), token),
153155
+ create: () => callVaultFunction("createPasskeyLink", VAULT_SIGNATURE_PURPOSES.CREATE_PASSKEY_LINK),
153156
+ watch: watchPasskeyLinks
153138
153157
  }
153139
153158
  };
153140
153159
  function userChatsQuery(uid, count, afterChat) {
@@ -155518,41 +155537,87 @@ function cliHelpLines(kind) {
155518
155537
  const field2 = kind === "structured" ? "structuredUsage" : "shortUsage";
155519
155538
  return HEADLESS_COMMANDS.map((item) => item[field2]).filter(Boolean);
155520
155539
  }
155521
- // package.json
155540
+ // ../../package.json
155522
155541
  var package_default = {
155523
- name: "@glyphteck/veyl",
155524
- version: "0.29.2",
155542
+ name: "veyl",
155543
+ version: "0.30.1",
155544
+ private: true,
155525
155545
  license: "Apache-2.0",
155526
- type: "module",
155527
- description: "Programmable Node.js client for Veyl accounts, vaults, chat, and wallet payments.",
155528
- repository: {
155529
- type: "git",
155530
- url: "https://github.com/glyphteck/veyl.git",
155531
- directory: "clients/headless"
155532
- },
155533
- exports: {
155534
- ".": "./dist/index.js"
155535
- },
155536
- bin: {
155537
- veyl: "dist/cli.js"
155538
- },
155539
- files: [
155540
- "dist",
155541
- "docs",
155542
- "README.md",
155543
- "package.json"
155544
- ],
155545
- engines: {
155546
- node: ">=22.0.0"
155547
- },
155548
- publishConfig: {
155549
- access: "public"
155546
+ workspaces: {
155547
+ packages: [
155548
+ "clients/*",
155549
+ "adapters/*",
155550
+ "bots",
155551
+ "shared"
155552
+ ],
155553
+ catalog: {
155554
+ "@buildonspark/spark-sdk": "^0.8.8",
155555
+ "@noble/ciphers": "^2.2.0",
155556
+ "@noble/curves": "^2.2.0",
155557
+ "@noble/hashes": "^2.2.0",
155558
+ "@scure/bip39": "^2.2.0",
155559
+ "@tailwindcss/postcss": "^4.3.2",
155560
+ bech32: "^2.0.0",
155561
+ firebase: "^12.16.0",
155562
+ "lucide-react": "^1.24.0",
155563
+ next: "16.3.0-preview.6",
155564
+ "next-themes": "^0.4.6",
155565
+ postcss: "^8.5.19",
155566
+ react: "19.2.7",
155567
+ "react-dom": "19.2.7",
155568
+ tailwindcss: "^4.3.2",
155569
+ "tw-animate-css": "^1.4.0"
155570
+ }
155550
155571
  },
155551
155572
  scripts: {
155552
- build: "bun build src/index.js src/cli.js --target=node --outdir dist",
155553
- prepack: "bun run build",
155554
- start: "node src/cli.js",
155555
- lint: "eslint src --quiet"
155573
+ admin: "bun scripts/admin/index.mjs",
155574
+ bot: "bun scripts/admin/bot.mjs",
155575
+ passkey: "bun scripts/admin/passkey.mjs",
155576
+ push: "bun scripts/repo.mjs push",
155577
+ merge: "bun scripts/repo.mjs merge",
155578
+ dev: "bun scripts/dev.mjs",
155579
+ make: "bun scripts/make.mjs",
155580
+ map: "bun scripts/map.mjs",
155581
+ dirty: "bun scripts/dirty.mjs",
155582
+ "check:paths": "bun scripts/check-paths.mjs",
155583
+ ban: "bun scripts/admin/ban.mjs",
155584
+ nuke: "bun scripts/admin/nuke.mjs",
155585
+ free: "bun scripts/admin/free.mjs",
155586
+ lint: "eslint . --quiet",
155587
+ "lint:warn": "eslint .",
155588
+ "lint:quality": 'eslint . --rule "react-hooks/exhaustive-deps: warn" --rule "react-hooks/purity: warn" --rule "complexity: [warn, 20]" --rule "max-depth: [warn, 4]" --rule "max-lines-per-function: [warn, {max: 200, skipBlankLines: true, skipComments: true}]" --rule "max-params: [warn, 6]"',
155589
+ "lint:fix": "eslint . --fix",
155590
+ "install:clean": "bun scripts/deps.mjs clean-install",
155591
+ update: "bun scripts/deps.mjs update",
155592
+ "sync:frameworks": "bun scripts/sync-frameworks.mjs",
155593
+ "check:frameworks": "bun scripts/sync-frameworks.mjs --check"
155594
+ },
155595
+ dependencies: {
155596
+ "@buildonspark/spark-sdk": "^0.8.8",
155597
+ "@noble/ciphers": "^2.2.0",
155598
+ "@noble/curves": "^2.2.0",
155599
+ "@noble/hashes": "^2.2.0",
155600
+ "@scure/bip39": "^2.2.0",
155601
+ "@veyl/shared": "workspace:*",
155602
+ bech32: "^2.0.0",
155603
+ firebase: "^12.16.0"
155604
+ },
155605
+ overrides: {
155606
+ firebase: "catalog:",
155607
+ next: "catalog:",
155608
+ "react-native-quick-base64": "3.0.1"
155609
+ },
155610
+ patchedDependencies: {
155611
+ "@noble/hashes@1.8.0": "patches/@noble__hashes@1.8.0.patch",
155612
+ "react-native-keyboard-controller@1.22.0": "patches/react-native-keyboard-controller@1.22.0.patch",
155613
+ "react-native-reanimated@4.5.0": "patches/react-native-reanimated@4.5.0.patch"
155614
+ },
155615
+ devDependencies: {
155616
+ "@eslint/js": "^10.0.1",
155617
+ "babel-plugin-react-compiler": "^1.0.0",
155618
+ eslint: "^10.7.0",
155619
+ "eslint-plugin-react-hooks": "^7.1.1",
155620
+ globals: "^17.7.0"
155556
155621
  }
155557
155622
  };
155558
155623
 
@@ -156007,7 +156072,7 @@ class VeylHeadlessClient {
156007
156072
  registry: registrySource
156008
156073
  });
156009
156074
  const vault = packSeedData(encrypted);
156010
- await this.cloud.user.vault.write(profile.uid, vault, { vaultSigningPK: encrypted.vaultSigningPK });
156075
+ await this.cloud.user.vault.write(profile.uid, vault, { vaultPK: encrypted.vaultPK });
156011
156076
  const session = await this.bootSession(masterSeed, encrypted.registry, profile);
156012
156077
  await this.cloud.user.profile.walletpk.write(session.walletPK, { network: profile.network || this.network });
156013
156078
  await this.cloud.user.profile.chatpk.write(session.chatPK);
package/dist/index.js CHANGED
@@ -61223,11 +61223,13 @@ function deriveKey(input, label, parts = [], size = 32) {
61223
61223
  "use client";
61224
61224
  var VAULT_SIGNATURE_PROTOCOL = "veyl-vault-signature-v1";
61225
61225
  var VAULT_SIGNING_KEY_SCOPE = "vault-signing-key-v1";
61226
- var VAULT_LEASE_PURPOSE = "vault-lease";
61227
61226
  var VAULT_SIGNATURE_PURPOSES = Object.freeze({
61227
+ CREATE_PASSKEY_LINK: "create-passkey-link",
61228
61228
  DELETE_ACCOUNT: "delete-account",
61229
+ DELETE_PASSKEY: "delete-passkey",
61229
61230
  LOGOUT_ALL_DEVICES: "logout-all-devices",
61230
61231
  SET_CHAT_IDENTITY: "set-chat-identity",
61232
+ SET_SETTINGS: "set-settings",
61231
61233
  SET_WALLET_IDENTITY: "set-wallet-identity"
61232
61234
  });
61233
61235
  var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
@@ -61270,12 +61272,12 @@ function cleanGeneration(value) {
61270
61272
  }
61271
61273
  return generation;
61272
61274
  }
61273
- function cleanClientSessionId(value) {
61274
- const clientSessionId = typeof value === "string" ? value.trim() : "";
61275
- if (!/^[A-Za-z0-9_-]{24,80}$/u.test(clientSessionId)) {
61276
- throw signatureError("invalid-client-session", "client session required");
61275
+ function cleanSessionId(value) {
61276
+ const sessionId = typeof value === "string" ? value.trim() : "";
61277
+ if (!/^[A-Za-z0-9_-]{24,80}$/u.test(sessionId)) {
61278
+ throw signatureError("invalid-session", "session required");
61277
61279
  }
61278
- return clientSessionId;
61280
+ return sessionId;
61279
61281
  }
61280
61282
  function vaultSigningPublicKey(masterSeed) {
61281
61283
  const secret = deriveKey(toBytes(masterSeed, "master seed"), VAULT_SIGNING_KEY_SCOPE);
@@ -61322,7 +61324,7 @@ function createVaultSignature(signer, claims, purpose, payload = null, now = Dat
61322
61324
  VAULT_SIGNATURE_PROTOCOL,
61323
61325
  uid,
61324
61326
  cleanGeneration(claims?.sessionGeneration),
61325
- cleanClientSessionId(claims?.clientSessionId),
61327
+ cleanSessionId(claims?.sessionId),
61326
61328
  cleanPurpose(purpose),
61327
61329
  now,
61328
61330
  base64url2(randomBytes3(24)),
@@ -61581,12 +61583,12 @@ async function encryptSeedWithPassword(seed, pwd, options = {}) {
61581
61583
  const params = normalizeVaultKdf(options.params);
61582
61584
  const deriveKey2 = getVaultDeriveKey(options);
61583
61585
  const registry = normalizeSecretRegistry(options.registry || createSecretRegistry());
61584
- const vaultSigningPK = vaultSigningPublicKey(seed);
61586
+ const vaultPK = vaultSigningPublicKey(seed);
61585
61587
  const sealedRegistry = await sealSecretRegistry(seed, registry);
61586
61588
  const key = await deriveKey2(pwd, salt, params);
61587
61589
  try {
61588
61590
  const { iv, ct } = await sealAes(key, seed);
61589
- return { crypto: options.crypto || VAULT_CRYPTO, kdf: params, ciphertext: ct, salt, iv, registry: sealedRegistry, vaultSigningPK };
61591
+ return { crypto: options.crypto || VAULT_CRYPTO, kdf: params, ciphertext: ct, salt, iv, registry: sealedRegistry, vaultPK };
61590
61592
  } finally {
61591
61593
  key.fill(0);
61592
61594
  }
@@ -63377,7 +63379,7 @@ async function openAccountSessionFromSecrets(walletEntropy, chatSeed, masterSeed
63377
63379
  network,
63378
63380
  vaultSigner,
63379
63381
  vaultAccess,
63380
- vaultSigningPK: vaultSigner.publicKey
63382
+ vaultPK: vaultSigner.publicKey
63381
63383
  });
63382
63384
  } catch (error) {
63383
63385
  closeSessionResources({ wallet, chatPrivateKey, vaultAccess, vaultSigner });
@@ -152229,6 +152231,15 @@ function authSessionGeneration(value) {
152229
152231
  const generation = Number(value);
152230
152232
  return Number.isSafeInteger(generation) && generation > 0 ? generation : null;
152231
152233
  }
152234
+ function authCredentialFromClaims(claims) {
152235
+ const kind = typeof claims?.credentialKind === "string" ? claims.credentialKind.trim() : "";
152236
+ const id = typeof claims?.credentialId === "string" ? claims.credentialId.trim() : "";
152237
+ return /^(machine|passkey)$/u.test(kind) && /^[A-Za-z0-9_-]{1,1500}$/u.test(id) ? { kind, id } : null;
152238
+ }
152239
+ function authCredentialDoc(db, credential) {
152240
+ const collectionName = credential?.kind === "passkey" ? "passkeys" : credential?.kind === "machine" ? "machineCredentials" : "";
152241
+ return collectionName ? doc(db, collectionName, credential.id) : null;
152242
+ }
152232
152243
  function vaultSignatureError(code, message) {
152233
152244
  const error = new Error(message);
152234
152245
  error.code = `vault-signature/${code}`;
@@ -152311,9 +152322,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152311
152322
  throw new Error("createFirebaseCloud requires db");
152312
152323
  }
152313
152324
  let activeVaultSigner = null;
152314
- let vaultLeaseExpiresAt = 0;
152315
- let vaultLeaseRequest = null;
152316
- let vaultOpenRequest = null;
152317
152325
  function pageTs(value) {
152318
152326
  if (value instanceof Timestamp2) {
152319
152327
  return value;
@@ -152474,11 +152482,12 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152474
152482
  requireUid(uid);
152475
152483
  const user = requireAuth().currentUser;
152476
152484
  let active = true;
152477
- let unsubscribe = () => {};
152485
+ let unsubscribeSession = () => {};
152486
+ let unsubscribeCredential = () => {};
152478
152487
  if (!user || user.uid !== uid) {
152479
152488
  Promise.resolve().then(() => {
152480
152489
  if (active)
152481
- onUpdate?.({ active: false, generation: null, currentGeneration: null });
152490
+ onUpdate?.({ active: false, generation: null, currentGeneration: null, authCredential: null });
152482
152491
  });
152483
152492
  return () => {
152484
152493
  active = false;
@@ -152488,19 +152497,43 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152488
152497
  if (!active)
152489
152498
  return;
152490
152499
  const generation = authSessionGeneration(result?.claims?.sessionGeneration);
152491
- if (!generation) {
152492
- onUpdate?.({ active: false, generation: null, currentGeneration: null });
152500
+ const sessionId = typeof result?.claims?.sessionId === "string" ? result.claims.sessionId : "";
152501
+ const authCredential = authCredentialFromClaims(result?.claims);
152502
+ const credentialRef = authCredentialDoc(db, authCredential);
152503
+ if (!generation || !sessionId || !authCredential || !credentialRef) {
152504
+ onUpdate?.({ active: false, generation: null, currentGeneration: null, authCredential: null });
152493
152505
  return;
152494
152506
  }
152495
- unsubscribe = onSnapshot(doc(db, "auth_sessions", uid), (snap) => {
152496
- if (!active)
152507
+ let sessionReady = false;
152508
+ let credentialReady = false;
152509
+ let currentGeneration = null;
152510
+ let credentialActive = false;
152511
+ const emit = () => {
152512
+ if (!active || !sessionReady || !credentialReady)
152497
152513
  return;
152498
- const currentGeneration = authSessionGeneration(snap.data()?.generation);
152499
152514
  onUpdate?.({
152500
- active: currentGeneration === generation,
152515
+ active: currentGeneration === generation && credentialActive,
152501
152516
  generation,
152502
- currentGeneration
152517
+ currentGeneration,
152518
+ authCredential
152503
152519
  });
152520
+ };
152521
+ unsubscribeSession = onSnapshot(doc(db, "users", uid, "auth", "session"), (snap) => {
152522
+ if (!active)
152523
+ return;
152524
+ sessionReady = true;
152525
+ currentGeneration = authSessionGeneration(snap.data()?.generation);
152526
+ emit();
152527
+ }, (error) => {
152528
+ if (active)
152529
+ onError?.(error);
152530
+ });
152531
+ unsubscribeCredential = onSnapshot(credentialRef, (snap) => {
152532
+ if (!active)
152533
+ return;
152534
+ credentialReady = true;
152535
+ credentialActive = snap.exists() && snap.data()?.uid === uid;
152536
+ emit();
152504
152537
  }, (error) => {
152505
152538
  if (active)
152506
152539
  onError?.(error);
@@ -152511,9 +152544,43 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152511
152544
  });
152512
152545
  return () => {
152513
152546
  active = false;
152514
- unsubscribe();
152547
+ unsubscribeSession();
152548
+ unsubscribeCredential();
152515
152549
  };
152516
152550
  }
152551
+ function watchPasskeyLinks(uid, onUpdate, onError) {
152552
+ requireUid(uid);
152553
+ return onSnapshot(query(collection(db, "passkeyLinks"), where("uid", "==", uid)), (snapshot) => {
152554
+ const links2 = snapshot.docs.map((snap) => {
152555
+ const data = snap.data() || {};
152556
+ if (data.status !== "pending")
152557
+ return null;
152558
+ return {
152559
+ id: snap.id,
152560
+ type: "pending",
152561
+ status: "pending",
152562
+ createdAt: timestampMs(data.createdAt, null)
152563
+ };
152564
+ }).filter(Boolean).sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
152565
+ onUpdate?.(links2);
152566
+ }, onError);
152567
+ }
152568
+ function watchPasskeys(uid, onUpdate, onError) {
152569
+ requireUid(uid);
152570
+ return onSnapshot(query(collection(db, "passkeys"), where("uid", "==", uid)), (snapshot) => {
152571
+ const passkeys = snapshot.docs.map((snap) => {
152572
+ const data = snap.data() || {};
152573
+ const label = typeof data.label === "string" ? data.label.trim() : "";
152574
+ return {
152575
+ id: snap.id,
152576
+ type: "passkey",
152577
+ label: label || "unnamed passkey",
152578
+ createdAt: timestampMs(data.createdAt, null)
152579
+ };
152580
+ }).filter(Boolean).sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
152581
+ onUpdate?.(passkeys);
152582
+ }, onError);
152583
+ }
152517
152584
  async function logout() {
152518
152585
  await signOut(requireAuth());
152519
152586
  return true;
@@ -152522,25 +152589,25 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152522
152589
  await callVaultFunction("logoutDevices", VAULT_SIGNATURE_PURPOSES.LOGOUT_ALL_DEVICES);
152523
152590
  return true;
152524
152591
  }
152525
- async function clientSessionClaims() {
152592
+ async function sessionClaims() {
152526
152593
  const user = requireAuth().currentUser;
152527
152594
  if (!user?.uid) {
152528
152595
  throw new Error("signed in user required");
152529
152596
  }
152530
152597
  const token = await user.getIdTokenResult();
152531
152598
  const sessionGeneration = authSessionGeneration(token?.claims?.sessionGeneration);
152532
- const clientSessionId = token?.claims?.clientSessionId;
152533
- if (!sessionGeneration || typeof clientSessionId !== "string" || !clientSessionId) {
152534
- throw new Error("invalid client session");
152599
+ const sessionId = token?.claims?.sessionId;
152600
+ if (!sessionGeneration || typeof sessionId !== "string" || !sessionId) {
152601
+ throw new Error("invalid session");
152535
152602
  }
152536
152603
  return {
152537
152604
  uid: user.uid,
152538
152605
  sessionGeneration,
152539
- clientSessionId
152606
+ sessionId
152540
152607
  };
152541
152608
  }
152542
152609
  function vaultSignatureClaims() {
152543
- return clientSessionClaims();
152610
+ return sessionClaims();
152544
152611
  }
152545
152612
  async function signVaultRequest(purpose, payload = null, signer = activeVaultSigner) {
152546
152613
  if (!signer) {
@@ -152550,71 +152617,22 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152550
152617
  return createVaultSignature(signer, await vaultSignatureClaims(), purpose, payload);
152551
152618
  } catch (error) {
152552
152619
  if (!error?.code) {
152553
- error.code = "vault-signature/proof-construction";
152620
+ error.code = "vault-signature/construction";
152554
152621
  }
152555
152622
  throw error;
152556
152623
  }
152557
152624
  }
152558
- async function grantVaultLease(signer = activeVaultSigner, force = false) {
152559
- if (!signer || signer !== activeVaultSigner) {
152560
- throw new Error("unlocked vault required");
152561
- }
152562
- if (!force && vaultLeaseExpiresAt - Date.now() > 15000) {
152563
- return { expiresAt: vaultLeaseExpiresAt };
152564
- }
152565
- if (vaultLeaseRequest?.signer === signer) {
152566
- return vaultLeaseRequest.promise;
152567
- }
152568
- const promise = (async () => {
152569
- const result = await callFunction("grantVaultLease", {
152570
- vaultSignature: await signVaultRequest(VAULT_LEASE_PURPOSE, null, signer)
152571
- });
152572
- if (signer !== activeVaultSigner) {
152573
- throw new Error("vault locked during authorization");
152574
- }
152575
- const expiresAt = Number(result?.expiresAt);
152576
- if (!Number.isFinite(expiresAt) || expiresAt <= Date.now()) {
152577
- throw new Error("invalid vault lease");
152578
- }
152579
- vaultLeaseExpiresAt = expiresAt;
152580
- return { expiresAt };
152581
- })().finally(() => {
152582
- if (vaultLeaseRequest?.promise === promise) {
152583
- vaultLeaseRequest = null;
152584
- }
152585
- });
152586
- vaultLeaseRequest = { signer, promise };
152587
- return promise;
152588
- }
152589
152625
  async function openVaultSignature(signer) {
152590
152626
  if (!signer?.publicKey || typeof signer?.sign !== "function") {
152591
152627
  throw vaultSignatureError("invalid-signer", "vault signer required");
152592
152628
  }
152593
152629
  if (activeVaultSigner?.closed) {
152594
152630
  activeVaultSigner = null;
152595
- vaultLeaseExpiresAt = 0;
152596
- vaultLeaseRequest = null;
152597
- vaultOpenRequest = null;
152598
152631
  }
152599
152632
  if (activeVaultSigner && activeVaultSigner !== signer) {
152600
152633
  throw vaultSignatureError("already-open", "vault signature already open");
152601
152634
  }
152602
152635
  activeVaultSigner = signer;
152603
- const openPromise = grantVaultLease(signer, true);
152604
- vaultOpenRequest = { signer, promise: openPromise };
152605
- try {
152606
- await openPromise;
152607
- } catch (error) {
152608
- if (activeVaultSigner === signer) {
152609
- activeVaultSigner = null;
152610
- vaultLeaseExpiresAt = 0;
152611
- }
152612
- throw error;
152613
- } finally {
152614
- if (vaultOpenRequest?.promise === openPromise) {
152615
- vaultOpenRequest = null;
152616
- }
152617
- }
152618
152636
  let closed = false;
152619
152637
  return {
152620
152638
  close() {
@@ -152624,8 +152642,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152624
152642
  if (activeVaultSigner !== signer)
152625
152643
  return;
152626
152644
  activeVaultSigner = null;
152627
- vaultLeaseExpiresAt = 0;
152628
- callFunction("dropVaultLease").catch(() => {});
152629
152645
  }
152630
152646
  };
152631
152647
  }
@@ -152633,9 +152649,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152633
152649
  const signer = activeVaultSigner;
152634
152650
  if (!signer)
152635
152651
  throw new Error("unlocked vault required");
152636
- if (vaultOpenRequest?.signer === signer) {
152637
- await vaultOpenRequest.promise;
152638
- }
152639
152652
  if (signer !== activeVaultSigner) {
152640
152653
  throw vaultSignatureError("locked", "unlocked vault required");
152641
152654
  }
@@ -152665,10 +152678,10 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152665
152678
  const snap = await getDoc(doc(db, "seeds", uid));
152666
152679
  return snap.exists();
152667
152680
  }
152668
- async function writeVault(uid, vault, { vaultSigningPK } = {}) {
152681
+ async function writeVault(uid, vault, { vaultPK } = {}) {
152669
152682
  requireUid(uid);
152670
- if (!vault || !vaultSigningPK) {
152671
- throw new Error("vault enrollment required");
152683
+ if (!vault || !vaultPK) {
152684
+ throw new Error("vault and public key required");
152672
152685
  }
152673
152686
  const user = requireAuth().currentUser;
152674
152687
  if (user?.uid !== uid) {
@@ -152676,7 +152689,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152676
152689
  }
152677
152690
  await callFunction("createVault", {
152678
152691
  vault: cloudBytesBase64(vault, "vault bytes"),
152679
- vaultSigningPK
152692
+ vaultPK
152680
152693
  });
152681
152694
  return true;
152682
152695
  }
@@ -152778,10 +152791,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152778
152791
  return openSettings(key, uid, readCloudBytes(saved, "settings body"));
152779
152792
  }
152780
152793
  const settings = normalizeSettings(defaultSettings);
152781
- await grantVaultLease(activeVaultSigner);
152782
- await setDoc(doc(db, "users", uid), {
152783
- settings: writeCloudBytes(await sealSettings(key, uid, settings), "settings body")
152784
- }, { merge: true });
152794
+ await callVaultFunction("setSettings", VAULT_SIGNATURE_PURPOSES.SET_SETTINGS, { settings: bytesBase64(await sealSettings(key, uid, settings)) });
152785
152795
  return settings;
152786
152796
  }
152787
152797
  async function writeSettings(uid, settings, { currentSettings, key } = {}) {
@@ -152792,10 +152802,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152792
152802
  const base = currentSettings || await readSettings(uid, key);
152793
152803
  const nextSettings = normalizeSettings(settings, base);
152794
152804
  const body = await sealSettings(key, uid, nextSettings);
152795
- await grantVaultLease(activeVaultSigner);
152796
- await setDoc(doc(db, "users", uid), {
152797
- settings: writeCloudBytes(body, "settings body")
152798
- }, { merge: true });
152805
+ await callVaultFunction("setSettings", VAULT_SIGNATURE_PURPOSES.SET_SETTINGS, { settings: bytesBase64(body) });
152799
152806
  return nextSettings;
152800
152807
  }
152801
152808
  async function writeUserActive(uid, active) {
@@ -152852,7 +152859,7 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
152852
152859
  }
152853
152860
  async function readPeer(uid) {
152854
152861
  requireUid(uid);
152855
- const snap = await getDoc(doc(db, "profiles", uid));
152862
+ const snap = await getDocFromServer(doc(db, "profiles", uid));
152856
152863
  return peerRecordFromDoc(snap);
152857
152864
  }
152858
152865
  async function readPeerActive(uid) {
@@ -153119,7 +153126,6 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
153119
153126
  },
153120
153127
  vaultSignature: {
153121
153128
  open: openVaultSignature,
153122
- ensure: () => grantVaultLease(activeVaultSigner),
153123
153129
  sign: signVaultRequest,
153124
153130
  call: callVaultFunction
153125
153131
  },
@@ -153134,6 +153140,19 @@ function createFirebaseCloud({ db, auth: auth2, getAuth: getAuth2, functions: fu
153134
153140
  start: (payload) => callFunction("passkeyRegisterOptions", payload),
153135
153141
  token: (payload) => callFunction("passkeyRegisterVerify", payload),
153136
153142
  finish: (payload) => finishAuth("passkeyRegisterVerify", payload)
153143
+ },
153144
+ passkeys: {
153145
+ watch: watchPasskeys,
153146
+ deleteOptions: (payload) => callFunction("passkeyDeleteOptions", payload),
153147
+ delete: (id, assertion = null) => callVaultFunction("deletePasskey", VAULT_SIGNATURE_PURPOSES.DELETE_PASSKEY, assertion ? { id, assertion } : { id })
153148
+ },
153149
+ passkeyLinks: {
153150
+ info: (payload) => callFunction("passkeyLinkInfo", payload),
153151
+ start: (payload) => callFunction("passkeyLinkOptions", payload),
153152
+ use: (payload) => callFunction("usePasskeyLink", payload),
153153
+ activate: (token) => signInWithCustomToken(requireAuth(), token),
153154
+ create: () => callVaultFunction("createPasskeyLink", VAULT_SIGNATURE_PURPOSES.CREATE_PASSKEY_LINK),
153155
+ watch: watchPasskeyLinks
153137
153156
  }
153138
153157
  };
153139
153158
  function userChatsQuery(uid, count, afterChat) {
@@ -155517,41 +155536,87 @@ function cliHelpLines(kind) {
155517
155536
  const field2 = kind === "structured" ? "structuredUsage" : "shortUsage";
155518
155537
  return HEADLESS_COMMANDS.map((item) => item[field2]).filter(Boolean);
155519
155538
  }
155520
- // package.json
155539
+ // ../../package.json
155521
155540
  var package_default = {
155522
- name: "@glyphteck/veyl",
155523
- version: "0.29.2",
155541
+ name: "veyl",
155542
+ version: "0.30.1",
155543
+ private: true,
155524
155544
  license: "Apache-2.0",
155525
- type: "module",
155526
- description: "Programmable Node.js client for Veyl accounts, vaults, chat, and wallet payments.",
155527
- repository: {
155528
- type: "git",
155529
- url: "https://github.com/glyphteck/veyl.git",
155530
- directory: "clients/headless"
155531
- },
155532
- exports: {
155533
- ".": "./dist/index.js"
155534
- },
155535
- bin: {
155536
- veyl: "dist/cli.js"
155537
- },
155538
- files: [
155539
- "dist",
155540
- "docs",
155541
- "README.md",
155542
- "package.json"
155543
- ],
155544
- engines: {
155545
- node: ">=22.0.0"
155546
- },
155547
- publishConfig: {
155548
- access: "public"
155545
+ workspaces: {
155546
+ packages: [
155547
+ "clients/*",
155548
+ "adapters/*",
155549
+ "bots",
155550
+ "shared"
155551
+ ],
155552
+ catalog: {
155553
+ "@buildonspark/spark-sdk": "^0.8.8",
155554
+ "@noble/ciphers": "^2.2.0",
155555
+ "@noble/curves": "^2.2.0",
155556
+ "@noble/hashes": "^2.2.0",
155557
+ "@scure/bip39": "^2.2.0",
155558
+ "@tailwindcss/postcss": "^4.3.2",
155559
+ bech32: "^2.0.0",
155560
+ firebase: "^12.16.0",
155561
+ "lucide-react": "^1.24.0",
155562
+ next: "16.3.0-preview.6",
155563
+ "next-themes": "^0.4.6",
155564
+ postcss: "^8.5.19",
155565
+ react: "19.2.7",
155566
+ "react-dom": "19.2.7",
155567
+ tailwindcss: "^4.3.2",
155568
+ "tw-animate-css": "^1.4.0"
155569
+ }
155549
155570
  },
155550
155571
  scripts: {
155551
- build: "bun build src/index.js src/cli.js --target=node --outdir dist",
155552
- prepack: "bun run build",
155553
- start: "node src/cli.js",
155554
- lint: "eslint src --quiet"
155572
+ admin: "bun scripts/admin/index.mjs",
155573
+ bot: "bun scripts/admin/bot.mjs",
155574
+ passkey: "bun scripts/admin/passkey.mjs",
155575
+ push: "bun scripts/repo.mjs push",
155576
+ merge: "bun scripts/repo.mjs merge",
155577
+ dev: "bun scripts/dev.mjs",
155578
+ make: "bun scripts/make.mjs",
155579
+ map: "bun scripts/map.mjs",
155580
+ dirty: "bun scripts/dirty.mjs",
155581
+ "check:paths": "bun scripts/check-paths.mjs",
155582
+ ban: "bun scripts/admin/ban.mjs",
155583
+ nuke: "bun scripts/admin/nuke.mjs",
155584
+ free: "bun scripts/admin/free.mjs",
155585
+ lint: "eslint . --quiet",
155586
+ "lint:warn": "eslint .",
155587
+ "lint:quality": 'eslint . --rule "react-hooks/exhaustive-deps: warn" --rule "react-hooks/purity: warn" --rule "complexity: [warn, 20]" --rule "max-depth: [warn, 4]" --rule "max-lines-per-function: [warn, {max: 200, skipBlankLines: true, skipComments: true}]" --rule "max-params: [warn, 6]"',
155588
+ "lint:fix": "eslint . --fix",
155589
+ "install:clean": "bun scripts/deps.mjs clean-install",
155590
+ update: "bun scripts/deps.mjs update",
155591
+ "sync:frameworks": "bun scripts/sync-frameworks.mjs",
155592
+ "check:frameworks": "bun scripts/sync-frameworks.mjs --check"
155593
+ },
155594
+ dependencies: {
155595
+ "@buildonspark/spark-sdk": "^0.8.8",
155596
+ "@noble/ciphers": "^2.2.0",
155597
+ "@noble/curves": "^2.2.0",
155598
+ "@noble/hashes": "^2.2.0",
155599
+ "@scure/bip39": "^2.2.0",
155600
+ "@veyl/shared": "workspace:*",
155601
+ bech32: "^2.0.0",
155602
+ firebase: "^12.16.0"
155603
+ },
155604
+ overrides: {
155605
+ firebase: "catalog:",
155606
+ next: "catalog:",
155607
+ "react-native-quick-base64": "3.0.1"
155608
+ },
155609
+ patchedDependencies: {
155610
+ "@noble/hashes@1.8.0": "patches/@noble__hashes@1.8.0.patch",
155611
+ "react-native-keyboard-controller@1.22.0": "patches/react-native-keyboard-controller@1.22.0.patch",
155612
+ "react-native-reanimated@4.5.0": "patches/react-native-reanimated@4.5.0.patch"
155613
+ },
155614
+ devDependencies: {
155615
+ "@eslint/js": "^10.0.1",
155616
+ "babel-plugin-react-compiler": "^1.0.0",
155617
+ eslint: "^10.7.0",
155618
+ "eslint-plugin-react-hooks": "^7.1.1",
155619
+ globals: "^17.7.0"
155555
155620
  }
155556
155621
  };
155557
155622
 
@@ -156006,7 +156071,7 @@ class VeylHeadlessClient {
156006
156071
  registry: registrySource
156007
156072
  });
156008
156073
  const vault = packSeedData(encrypted);
156009
- await this.cloud.user.vault.write(profile.uid, vault, { vaultSigningPK: encrypted.vaultSigningPK });
156074
+ await this.cloud.user.vault.write(profile.uid, vault, { vaultPK: encrypted.vaultPK });
156010
156075
  const session = await this.bootSession(masterSeed, encrypted.registry, profile);
156011
156076
  await this.cloud.user.profile.walletpk.write(session.walletPK, { network: profile.network || this.network });
156012
156077
  await this.cloud.user.profile.chatpk.write(session.chatPK);
package/package.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "name": "@glyphteck/veyl",
3
- "version": "0.29.2",
4
3
  "license": "Apache-2.0",
5
4
  "type": "module",
6
5
  "description": "Programmable Node.js client for Veyl accounts, vaults, chat, and wallet payments.",
@@ -32,5 +31,6 @@
32
31
  "prepack": "bun run build",
33
32
  "start": "node src/cli.js",
34
33
  "lint": "eslint src --quiet"
35
- }
34
+ },
35
+ "version": "0.30.1"
36
36
  }