@glyphteck/veyl 0.69.0 → 0.71.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.
package/docs/api.md CHANGED
@@ -27,12 +27,14 @@ Most product methods ensure login and vault unlock when saved account and vault
27
27
 
28
28
  ### Local access and connectivity
29
29
 
30
- The shared account owner separates `localReady`, `online`, and `connection` in its snapshot. `localReady` means the exact locally signed-in account has enough encrypted bootstrap data for vault unlock; it is not server authorization. Unlock opens encrypted cached chats and wallet history without waiting for cloud services. Cached balance is display-only and must be labeled last known. `online` becomes true after cloud reads and online proof succeed; reconnect attaches services to the same unlocked session. Chat writes fail with `unavailable` while offline, and live wallet readiness remains mandatory for payments. There is no offline mutation queue.
30
+ The shared account owner separates `localReady`, `online`, and `connection` in its snapshot. `localReady` means the exact locally signed-in account has enough encrypted bootstrap data for vault unlock; it is not server authorization. Unlock opens encrypted cached chats and wallet history without waiting for cloud services. Cached balance is display-only and must be labeled last known. `online` becomes true after cloud reads and online proof succeed; reconnect attaches services to the same unlocked session. Text sends wait up to 30 seconds for connectivity, then remain encrypted on-device as failed attempts for manual retry; reactions expire without a retry row. Avatar changes wait only for the current session, as described below. These are domain-owned pending operations, not a general cloud mutation queue. Live wallet readiness remains mandatory for payments.
31
31
 
32
32
  Custom platform hosts may provide `bootstrapStorage.read(uid)`, `write(uid, snapshot)`, and `remove(uid)` to `openAccount`, and call `setInternetAvailable(false | true | null)` with platform reachability. Encrypt bootstrap data under the account/environment-bound install key; never put decrypted private content there. Standard web, iOS and Node adapters supply encrypted storage. Logout or observed revocation removes it.
33
33
 
34
34
  Node authentication is currently process-local: a fresh SDK/CLI process still needs the network to authenticate, even with saved credentials. Cached access supports an already-authenticated long-running SDK process; saved username/profile metadata cannot establish an offline session. Web and iOS can restore their platform-persisted signed-in auth slots.
35
35
 
36
+ `connection.unavailable` is the shared offline-display signal, separate from account readiness in `connection.status`. Ordinary startup, local service initialization, and brief cache refreshes do not mean offline. Explicit device/cloud blocking and network errors report unavailability immediately; silent required server reads use the existing 15-second deadline. The cloud transport's `availability` port reports `false` when explicitly blocked and `null` when unknown, never treating an allowed test phase as proof of a server connection.
37
+
36
38
  ## Graphical auth owner
37
39
 
38
40
  ```js
@@ -166,7 +168,9 @@ await account.close();
166
168
 
167
169
  `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`; `vaultReady` becomes true only after the backend authorizes and confirms the current vault snapshot, while a cached snapshot may warm `vault` without authorizing a guarded route. 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.
168
170
 
169
- `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.
171
+ `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. Avatar selection/removal previews immediately through the shared user snapshot, waits while offline, and publishes once authenticated profile reads recover. Only the latest selection is retained, in memory for this session; lock/close discards unsent work and rejects its promise with `cancelled`. The promise resolves after server acknowledgment and the confirmed bytes/version enter the ordinary avatar cache. No pending avatar is persisted or compared through extra server reads. Username changes still require connectivity.
172
+
173
+ `account.bitcoin` restores the last observed public USD price from `bitcoinPriceStorage` (`read()` / `write({ price, updatedAt })`). The platform port is shared across accounts within the same installation and realm. The snapshot exposes `priceUpdatedAt` and `priceFromCache`; a null observation time means the configured $80,000 default, never a fetched rate. Cache hydration restores price only, not fee estimates or server/wallet readiness. The existing cloud listener refreshes the saved rate without additional requests. Confirmed self/peer avatar bytes similarly hydrate from their exact cached version independently of cloud readiness.
170
174
 
171
175
  `account.peers` is the shared peer-directory owner used by Node, web, and iOS. `openAccount()` supplies its chat, wallet, blocked-user, and encrypted-cache sources directly, including missing-profile chat cleanup. Graphical adapters only subscribe to the same snapshot and profile selectors already defined by core. `openSearch('profiles')` creates profile-only search; web may also use `openSearch('mainmenu')` for its combined local-action and remote-profile menu. Active searches track peer and blocked-user changes and release those subscriptions when cleared or closed.
172
176
 
@@ -250,6 +254,9 @@ Vault creation returns the vault key directly. That key unlocks the vault and ev
250
254
 
251
255
  ```js
252
256
  await veyl.profile.show();
257
+ await veyl.profile.getPresence({ timeoutMs: 15_000 });
258
+ await veyl.profile.setPresenceVisibility('private'); // appear offline on every account device
259
+ await veyl.profile.setPresenceVisibility('public'); // share online status and last active
253
260
  await veyl.profile.uploadAvatar(webpBytes);
254
261
  await veyl.profile.deleteAvatar();
255
262
  await veyl.profile.setChatAdmission({
@@ -269,6 +276,8 @@ await veyl.cache.clear();
269
276
 
270
277
  Settings use the shared normalization and encrypted settings document. Changing `walletNetwork` locks the current vault so the next unlock boots the selected network. Cache methods operate on the same vault-encrypted display and media cache as the other clients.
271
278
 
279
+ Presence visibility is an independent account-wide relay policy, not an encrypted settings field. `getPresence` waits for the acknowledged policy and returns `{ visibility, pending, error, availability, status, lastActiveAt }`. `setPresenceVisibility` accepts only `public` or `private` and resolves after the shared presence owner confirms the revisioned change; connection, conflict, and timeout errors reject explicitly. An unloaded policy never implies public visibility. The matching CLI commands are `veyl profile presence` and `veyl profile presence-set <public|private>`.
280
+
272
281
  ## Peers
273
282
 
274
283
  ```js
@@ -282,6 +291,8 @@ await veyl.peers.unblock('@alice');
282
291
 
283
292
  Peer resolution accepts `@username`, username, chat public key, or wallet public key when the operation supports it. Blocking self is rejected. A block independently submits a narrow user report, retires every private chat route containing that peer, and returns `reported` separately from `blocked`; report failure never prevents the block. Peer/profile results are public projections and do not expose local cache internals. `peers.show` authoritatively refreshes a cached identity; a confirmed missing profile evicts it and deletes loaded chats through the shared missing-peer owner. Normal chat/wallet actions keep the shared cached fast path, while their server-side operations still validate the authoritative route they mutate.
284
293
 
294
+ Profile and peer results include `presence: { availability, status, lastActiveAt }`; `active` is derived only from `availability === 'online'`, never from a stored profile flag. Availability is `unknown`, `online`, or `offline`; unknown/private/unobserved peers must not be presented as confirmed offline. Last-active timestamps are coarse buckets, not exact interaction times. Presence reflects the current bounded observation set; `@active` / `@online` search filters observed local peers rather than querying a global directory of online users.
295
+
285
296
  ## Chat
286
297
 
287
298
  ```js
package/package.json CHANGED
@@ -53,5 +53,5 @@
53
53
  "start": "node src/cli.js",
54
54
  "lint": "eslint src --quiet"
55
55
  },
56
- "version": "0.69.0"
56
+ "version": "0.71.0"
57
57
  }