@synonymdev/pubky 0.14.0 → 0.15.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/README.md CHANGED
@@ -219,6 +219,18 @@ like a bearer token. Delegated browser grant sessions should use
219
219
  > applications should use grant auth plus `browserSessionStore` or
220
220
  > `exportLocalSecret()`.
221
221
 
222
+ **Multiple browser tabs**
223
+
224
+ `browserSessionStore.restore(id)` shares one bearer per grant across tabs on the
225
+ same origin, including after reloads. It uses the existing single-session protocol.
226
+ Browser persistence requires IndexedDB and Web Locks in a secure context.
227
+
228
+ Signout revokes the grant for every tab. Separate applications should obtain
229
+ their own grants: restoring the same exported grant outside browser coordination
230
+ replaces its current bearer.
231
+ See [grant session lifecycle](../../../../docs/grant-session-lifecycle.md)
232
+ for compatibility and expiry behavior.
233
+
222
234
  **Approve a pubkyauth request URL**
223
235
 
224
236
  ```js
@@ -406,8 +418,23 @@ await s.list("/pub/example.com/", null, false, 100, false);
406
418
 
407
419
  // Delete
408
420
  await s.delete("/pub/example.com/data.json");
421
+
422
+ // Locked writes (WebDAV LOCK/UNLOCK)
423
+ const lock = await s.lock("/pub/example.com/state.json", 30); // seconds
424
+ lock.path; // -> "/pub/example.com/state.json"
425
+ lock.token; // -> "opaquelocktoken:<uuid>"
426
+ lock.timeoutSeconds; // -> what the homeserver granted (it caps the lifetime)
427
+ await s.putTextLocked(lock, JSON.stringify({ count: 1 })); // only the holder can write; no putJsonLocked
428
+ await s.putBytesLocked(lock, new Uint8Array([1, 2, 3]));
429
+ await s.deleteLocked(lock);
430
+ await s.refreshLock(lock, 30); // restart the lifetime
431
+ await s.unlock(lock);
409
432
  ```
410
433
 
434
+ While a lock lives, a plain `putJson`/`putText`/`putBytes`/`delete` on that path rejects with `423 Locked`, and so does a second `lock()`. Once the lock is gone, the old value is refused with `412` (write, delete, refresh) and `409` on `unlock()`; take a new lock and read the file again. A homeserver without lock support answers `405`.
435
+
436
+ `timeoutSeconds` is rounded down to whole seconds, with a minimum of 1. If `lock()` rejects without a status code (a lost connection, say), the homeserver may still have granted the lock; nothing can release it, so the path answers `423` until it times out.
437
+
411
438
  `get()` exposes the underlying `Response`, which is handy for streaming bodies or inspecting headers before consuming content.
412
439
 
413
440
  Path rules: