@glyphteck/veyl 0.64.0 → 0.65.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.
package/dist/account.js CHANGED
@@ -39793,10 +39793,24 @@ function openAccount(options = {}) {
39793
39793
  finishOperation();
39794
39794
  }
39795
39795
  }
39796
- async function changeVaultPassword({ currentPassword, newPassword } = {}) {
39796
+ function vaultPasswordOperationContext() {
39797
39797
  if (state.lockState !== "unlocked" || !state.session) {
39798
39798
  throw vaultPasswordChangeError("locked", "unlocked vault required");
39799
39799
  }
39800
+ const uid = profileUid();
39801
+ const session = state.session;
39802
+ const observedVault = state.vault;
39803
+ if (!observedVault)
39804
+ throw vaultPasswordChangeError("vault-required", "vault not ready");
39805
+ return {
39806
+ uid,
39807
+ session,
39808
+ observedVault,
39809
+ isCurrent: () => !closed && !operationBarrier.blocksOperations && state.uid === uid && state.session === session && state.vault === observedVault && !session.closed && cloud.auth.user?.uid === uid
39810
+ };
39811
+ }
39812
+ async function changeVaultPassword({ currentPassword, newPassword } = {}) {
39813
+ const { uid, session, observedVault, isCurrent } = vaultPasswordOperationContext();
39800
39814
  const finishOperation = operationBarrier.begin("vault password", {
39801
39815
  busyError: () => vaultPasswordChangeError("busy", "vault password change already in progress")
39802
39816
  });
@@ -39816,12 +39830,6 @@ function openAccount(options = {}) {
39816
39830
  if (!isPasswordStrengthAcceptable(getPasswordStrength(next, [state.user?.username]))) {
39817
39831
  throw vaultPasswordChangeError("weak", "new password is too weak");
39818
39832
  }
39819
- const uid = profileUid();
39820
- const session = state.session;
39821
- const observedVault = state.vault;
39822
- if (!observedVault)
39823
- throw vaultPasswordChangeError("vault-required", "vault not ready");
39824
- const isCurrent = () => !closed && !operationBarrier.blocksOperations && state.uid === uid && state.session === session && !session.closed && cloud.auth.user?.uid === uid;
39825
39833
  const prepared = await vaultCrypto.rewrapVaultPassword(observedVault, current, next, {
39826
39834
  expectedVaultPK: session.vaultPK
39827
39835
  });
@@ -39839,6 +39847,33 @@ function openAccount(options = {}) {
39839
39847
  finishOperation();
39840
39848
  }
39841
39849
  }
39850
+ async function verifyVaultPasswordForChange(currentPassword) {
39851
+ const { observedVault, isCurrent } = vaultPasswordOperationContext();
39852
+ const finishOperation = operationBarrier.begin("vault password verification", {
39853
+ busyError: () => vaultPasswordChangeError("busy", "vault password operation already in progress")
39854
+ });
39855
+ try {
39856
+ if (typeof vaultCrypto.verifyVaultPassword !== "function") {
39857
+ throw vaultPasswordChangeError("unsupported", "vault password verification unavailable");
39858
+ }
39859
+ const current = normalizePassword(currentPassword);
39860
+ if (!current)
39861
+ throw vaultPasswordChangeError("current-required", "current password required");
39862
+ let verified = false;
39863
+ try {
39864
+ verified = await vaultCrypto.verifyVaultPassword(observedVault, current);
39865
+ } catch (cause) {
39866
+ throw vaultPasswordChangeError("incorrect-current", "incorrect current password", cause);
39867
+ }
39868
+ if (!verified)
39869
+ throw vaultPasswordChangeError("incorrect-current", "incorrect current password");
39870
+ if (!isCurrent())
39871
+ throw vaultPasswordChangeError("account-changed", "account changed during password verification");
39872
+ return { verified: true };
39873
+ } finally {
39874
+ finishOperation();
39875
+ }
39876
+ }
39842
39877
  function setAgreementContract(value) {
39843
39878
  nextAgreement = agreementContract(value);
39844
39879
  return nextAgreement;
@@ -40000,6 +40035,7 @@ function openAccount(options = {}) {
40000
40035
  unlock,
40001
40036
  acceptAgreement,
40002
40037
  createVault,
40038
+ verifyVaultPasswordForChange,
40003
40039
  changeVaultPassword,
40004
40040
  delete: deleteAccount,
40005
40041
  lock,
package/dist/cli.js CHANGED
@@ -43779,10 +43779,24 @@ function openAccount(options = {}) {
43779
43779
  finishOperation();
43780
43780
  }
43781
43781
  }
43782
- async function changeVaultPassword({ currentPassword, newPassword } = {}) {
43782
+ function vaultPasswordOperationContext() {
43783
43783
  if (state.lockState !== "unlocked" || !state.session) {
43784
43784
  throw vaultPasswordChangeError("locked", "unlocked vault required");
43785
43785
  }
43786
+ const uid = profileUid();
43787
+ const session = state.session;
43788
+ const observedVault = state.vault;
43789
+ if (!observedVault)
43790
+ throw vaultPasswordChangeError("vault-required", "vault not ready");
43791
+ return {
43792
+ uid,
43793
+ session,
43794
+ observedVault,
43795
+ isCurrent: () => !closed && !operationBarrier.blocksOperations && state.uid === uid && state.session === session && state.vault === observedVault && !session.closed && cloud.auth.user?.uid === uid
43796
+ };
43797
+ }
43798
+ async function changeVaultPassword({ currentPassword, newPassword } = {}) {
43799
+ const { uid, session, observedVault, isCurrent } = vaultPasswordOperationContext();
43786
43800
  const finishOperation = operationBarrier.begin("vault password", {
43787
43801
  busyError: () => vaultPasswordChangeError("busy", "vault password change already in progress")
43788
43802
  });
@@ -43802,12 +43816,6 @@ function openAccount(options = {}) {
43802
43816
  if (!isPasswordStrengthAcceptable(getPasswordStrength(next, [state.user?.username]))) {
43803
43817
  throw vaultPasswordChangeError("weak", "new password is too weak");
43804
43818
  }
43805
- const uid = profileUid();
43806
- const session = state.session;
43807
- const observedVault = state.vault;
43808
- if (!observedVault)
43809
- throw vaultPasswordChangeError("vault-required", "vault not ready");
43810
- const isCurrent = () => !closed && !operationBarrier.blocksOperations && state.uid === uid && state.session === session && !session.closed && cloud.auth.user?.uid === uid;
43811
43819
  const prepared = await vaultCrypto.rewrapVaultPassword(observedVault, current, next, {
43812
43820
  expectedVaultPK: session.vaultPK
43813
43821
  });
@@ -43825,6 +43833,33 @@ function openAccount(options = {}) {
43825
43833
  finishOperation();
43826
43834
  }
43827
43835
  }
43836
+ async function verifyVaultPasswordForChange(currentPassword) {
43837
+ const { observedVault, isCurrent } = vaultPasswordOperationContext();
43838
+ const finishOperation = operationBarrier.begin("vault password verification", {
43839
+ busyError: () => vaultPasswordChangeError("busy", "vault password operation already in progress")
43840
+ });
43841
+ try {
43842
+ if (typeof vaultCrypto.verifyVaultPassword !== "function") {
43843
+ throw vaultPasswordChangeError("unsupported", "vault password verification unavailable");
43844
+ }
43845
+ const current = normalizePassword(currentPassword);
43846
+ if (!current)
43847
+ throw vaultPasswordChangeError("current-required", "current password required");
43848
+ let verified = false;
43849
+ try {
43850
+ verified = await vaultCrypto.verifyVaultPassword(observedVault, current);
43851
+ } catch (cause) {
43852
+ throw vaultPasswordChangeError("incorrect-current", "incorrect current password", cause);
43853
+ }
43854
+ if (!verified)
43855
+ throw vaultPasswordChangeError("incorrect-current", "incorrect current password");
43856
+ if (!isCurrent())
43857
+ throw vaultPasswordChangeError("account-changed", "account changed during password verification");
43858
+ return { verified: true };
43859
+ } finally {
43860
+ finishOperation();
43861
+ }
43862
+ }
43828
43863
  function setAgreementContract(value) {
43829
43864
  nextAgreement = agreementContract(value);
43830
43865
  return nextAgreement;
@@ -43986,6 +44021,7 @@ function openAccount(options = {}) {
43986
44021
  unlock,
43987
44022
  acceptAgreement,
43988
44023
  createVault,
44024
+ verifyVaultPasswordForChange,
43989
44025
  changeVaultPassword,
43990
44026
  delete: deleteAccount,
43991
44027
  lock,
@@ -54026,7 +54062,7 @@ var package_default;
54026
54062
  var init_package2 = __esm(() => {
54027
54063
  package_default = {
54028
54064
  name: "veyl",
54029
- version: "0.64.0",
54065
+ version: "0.65.1",
54030
54066
  packageManager: "bun@1.4.0",
54031
54067
  private: true,
54032
54068
  license: "UNLICENSED",
package/dist/index.js CHANGED
@@ -43778,10 +43778,24 @@ function openAccount(options = {}) {
43778
43778
  finishOperation();
43779
43779
  }
43780
43780
  }
43781
- async function changeVaultPassword({ currentPassword, newPassword } = {}) {
43781
+ function vaultPasswordOperationContext() {
43782
43782
  if (state.lockState !== "unlocked" || !state.session) {
43783
43783
  throw vaultPasswordChangeError("locked", "unlocked vault required");
43784
43784
  }
43785
+ const uid = profileUid();
43786
+ const session = state.session;
43787
+ const observedVault = state.vault;
43788
+ if (!observedVault)
43789
+ throw vaultPasswordChangeError("vault-required", "vault not ready");
43790
+ return {
43791
+ uid,
43792
+ session,
43793
+ observedVault,
43794
+ isCurrent: () => !closed && !operationBarrier.blocksOperations && state.uid === uid && state.session === session && state.vault === observedVault && !session.closed && cloud.auth.user?.uid === uid
43795
+ };
43796
+ }
43797
+ async function changeVaultPassword({ currentPassword, newPassword } = {}) {
43798
+ const { uid, session, observedVault, isCurrent } = vaultPasswordOperationContext();
43785
43799
  const finishOperation = operationBarrier.begin("vault password", {
43786
43800
  busyError: () => vaultPasswordChangeError("busy", "vault password change already in progress")
43787
43801
  });
@@ -43801,12 +43815,6 @@ function openAccount(options = {}) {
43801
43815
  if (!isPasswordStrengthAcceptable(getPasswordStrength(next, [state.user?.username]))) {
43802
43816
  throw vaultPasswordChangeError("weak", "new password is too weak");
43803
43817
  }
43804
- const uid = profileUid();
43805
- const session = state.session;
43806
- const observedVault = state.vault;
43807
- if (!observedVault)
43808
- throw vaultPasswordChangeError("vault-required", "vault not ready");
43809
- const isCurrent = () => !closed && !operationBarrier.blocksOperations && state.uid === uid && state.session === session && !session.closed && cloud.auth.user?.uid === uid;
43810
43818
  const prepared = await vaultCrypto.rewrapVaultPassword(observedVault, current, next, {
43811
43819
  expectedVaultPK: session.vaultPK
43812
43820
  });
@@ -43824,6 +43832,33 @@ function openAccount(options = {}) {
43824
43832
  finishOperation();
43825
43833
  }
43826
43834
  }
43835
+ async function verifyVaultPasswordForChange(currentPassword) {
43836
+ const { observedVault, isCurrent } = vaultPasswordOperationContext();
43837
+ const finishOperation = operationBarrier.begin("vault password verification", {
43838
+ busyError: () => vaultPasswordChangeError("busy", "vault password operation already in progress")
43839
+ });
43840
+ try {
43841
+ if (typeof vaultCrypto.verifyVaultPassword !== "function") {
43842
+ throw vaultPasswordChangeError("unsupported", "vault password verification unavailable");
43843
+ }
43844
+ const current = normalizePassword(currentPassword);
43845
+ if (!current)
43846
+ throw vaultPasswordChangeError("current-required", "current password required");
43847
+ let verified = false;
43848
+ try {
43849
+ verified = await vaultCrypto.verifyVaultPassword(observedVault, current);
43850
+ } catch (cause) {
43851
+ throw vaultPasswordChangeError("incorrect-current", "incorrect current password", cause);
43852
+ }
43853
+ if (!verified)
43854
+ throw vaultPasswordChangeError("incorrect-current", "incorrect current password");
43855
+ if (!isCurrent())
43856
+ throw vaultPasswordChangeError("account-changed", "account changed during password verification");
43857
+ return { verified: true };
43858
+ } finally {
43859
+ finishOperation();
43860
+ }
43861
+ }
43827
43862
  function setAgreementContract(value) {
43828
43863
  nextAgreement = agreementContract(value);
43829
43864
  return nextAgreement;
@@ -43985,6 +44020,7 @@ function openAccount(options = {}) {
43985
44020
  unlock,
43986
44021
  acceptAgreement,
43987
44022
  createVault,
44023
+ verifyVaultPasswordForChange,
43988
44024
  changeVaultPassword,
43989
44025
  delete: deleteAccount,
43990
44026
  lock,
@@ -54025,7 +54061,7 @@ var package_default;
54025
54061
  var init_package2 = __esm(() => {
54026
54062
  package_default = {
54027
54063
  name: "veyl",
54028
- version: "0.64.0",
54064
+ version: "0.65.1",
54029
54065
  packageManager: "bun@1.4.0",
54030
54066
  private: true,
54031
54067
  license: "UNLICENSED",
package/docs/api.md CHANGED
@@ -109,6 +109,8 @@ await account.profile.setAvatar(preparedWebpBytes);
109
109
 
110
110
  await account.createVault(password);
111
111
  const session = await account.unlock(password);
112
+ await account.verifyVaultPasswordForChange(currentPassword);
113
+ await account.changeVaultPassword({ currentPassword, newPassword });
112
114
  const unsubscribeChat = account.chat.subscribe(() => {
113
115
  console.log(account.chat.getSnapshot().chats);
114
116
  });
@@ -152,7 +154,7 @@ unsubscribe();
152
154
  await account.close();
153
155
  ```
154
156
 
155
- `openAccount()` owns authenticated user observation, username and avatar publication, vault observation and creation, vault unlock/lock, encrypted settings/network selection, presence, late wallet readiness, public Bitcoin data, support/report commands, chat and peer/profile composition, account switching, and secret-bearing session teardown. Focused-chat presence is separately owned by the chat session's encrypted ephemeral live transport. The account snapshot exposes `user`, `vault`, `vaultReady`, `vaultError`, `session`, `wallet`, `walletError`, `network`, and `lockState`; stable domain owners such as `bitcoin` and `support` live directly on the returned account owner.
157
+ `openAccount()` owns authenticated user observation, username and avatar publication, vault observation and creation, vault unlock/lock, encrypted settings/network selection, presence, late wallet readiness, public Bitcoin data, support/report commands, chat and peer/profile composition, account switching, and secret-bearing session teardown. Focused-chat presence is separately owned by the chat session's encrypted ephemeral live transport. The account snapshot exposes `user`, `vault`, `vaultReady`, `vaultError`, `session`, `wallet`, `walletError`, `network`, and `lockState`; stable domain owners such as `bitcoin` and `support` live directly on the returned account owner. Graphical password-change flows call `verifyVaultPasswordForChange(currentPassword)` before revealing the new-password step, then call the atomic `changeVaultPassword({ currentPassword, newPassword })` command. Both are account-bound local decryptions; the first immediately clears its temporary seed, while the second preserves and verifies the existing Vault Signature identity before replacing the authoritative ciphertext.
156
158
 
157
159
  `account.profile` owns the server mutation after a platform has prepared avatar bytes or collected a username. Browser canvas work and native image manipulation remain platform-local; both then call the same `setAvatar`, `clearAvatar`, or `setUsername` command. Successful avatar commands update the shared user owner before returning.
158
160
 
package/package.json CHANGED
@@ -42,5 +42,5 @@
42
42
  "start": "node src/cli.js",
43
43
  "lint": "eslint src --quiet"
44
44
  },
45
- "version": "0.64.0"
45
+ "version": "0.65.1"
46
46
  }