@voltro/plugin-auth 0.86.0 → 0.87.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
@@ -20,6 +20,21 @@ Installation, guides, the full API reference, and examples all live in the
20
20
  **[Voltro documentation](https://docs.voltro.dev/docs/intro/getting-started)** — the single source of truth. This README is
21
21
  deliberately short so there is nothing here to drift out of date.
22
22
 
23
+ The opt-in `auth.guest` extension adds durable guest device credentials and
24
+ registered sessions. Its current status is **built**; see [Guest
25
+ identities](https://docs.voltro.dev/docs/authentication/guests) for the storage
26
+ contract, trusted transaction-bound account upgrade and remaining validation
27
+ limits.
28
+
29
+ `@voltro/plugin-auth/guest` provides the same guest client and pure credential
30
+ parser without React or server imports. Possession remains a server SQL check.
31
+
32
+ `@voltro/plugin-auth/native` also exports `nativeGuestStore`: adapt a supplied
33
+ durable native store and host-wide lock without a memory fallback. Create and
34
+ Resume responses bind the guest subject to the device proof before exposing
35
+ the session or persisting a new proof. Real OS-keystore verification remains
36
+ separate from the port contract.
37
+
23
38
  ## Registered device sessions
24
39
 
25
40
  `rotateRegisteredSession` replaces a credential atomically and retains inactive
@@ -30,7 +45,75 @@ upgraded auth replicas. See the bilingual
30
45
  [session guide](https://docs.voltro.dev/docs/authentication/sessions) for authority
31
46
  checks, device families and revocation cache limits.
32
47
 
48
+ `lockRegisteredSession(store, userId, sessionId)` reads an owned, unrotated
49
+ credential under the device-family fence. Supply the store of an existing
50
+ transaction, after the application's account/tenant fences, and keep that
51
+ transaction through the protected write. The helper does not validate a signed
52
+ token, expiry or application permissions. Root and presented-row locking reads
53
+ also serve rotation, touch and family revocation; ordinary reads and zero cache
54
+ TTL are not a substitute for native transaction semantics.
55
+
33
56
  ## License
34
57
 
35
58
  Proprietary. © 2026 Voltro UG. Your use is governed by the
36
59
  [Terms of Service](https://voltro.cloud/legal/terms). See the bundled `LICENSE`.
60
+
61
+
62
+ ### Complete device-family root discovery
63
+
64
+ Account-wide DataStore registry revocation locks actual user-owned family roots
65
+ in stable order before descendant rows. It never enumerates roots through an
66
+ ordinary older snapshot or rediscoveries after the current-root query. Revoke-other-
67
+ devices resolves its preserved lineage after acquiring the root roster, including
68
+ an owned rotation alias; unknown/foreign keep IDs retain no unverified family.
69
+
70
+ For an existing transaction, real owner/account fences must precede the registry's
71
+ family fences. New-root issuance must change the same actual owner's persisted
72
+ revision atomically with registration when an older repeatable-read snapshot is
73
+ possible. PostgreSQL row locking alone does not refresh that snapshot. Applications
74
+ owe whole-transaction retry/abort, not a cache workaround or fabricated owner.
75
+ Cloud implements this with private users.sessionFamilyRevision and its existing
76
+ account lifecycle fence. Other custom registries/issuers owe their equivalent
77
+ native contract. Native dialect/rollback/concurrency/replica/restart proof remains
78
+ required. Stop old issuers and apply declared schema before coordinated cutover.
79
+
80
+
81
+ ### Session reads require the owned canonical family root
82
+
83
+ `findSession` and `listSessions` return only unrotated credentials whose canonical
84
+ family root exists and has the same `userId`. A rotated root is still a valid
85
+ anchor; its tenant and expiry do not replace those of the current credential.
86
+ Missing, foreign or chained roots are refused without reconstructing any row.
87
+ Custom `SessionStore` implementations must enforce this read contract too.
88
+ Registry and Memory reads reject ambiguous duplicate IDs. PostgreSQL uses a
89
+ single self-join on the actual sessions table for each lookup/enumeration.
90
+ Memory insert/read results copy stored dates rather than exposing mutable
91
+ references. These reads are point-in-time eligibility checks, not a replacement
92
+ for locked current-session validation inside a protected write transaction.
93
+ Positive revocation-cache entries still obey the configured TTL; choose the
94
+ required revocation window explicitly.
95
+
96
+
97
+ ### Bind a revocation check to the signed user
98
+
99
+ `makeSessionRevocationChecker(store, options).isLiveFor(sessionId, userId)`
100
+ requires the verified signed user's ID. A live credential owned by another
101
+ user is refused. The cached entry retains the actual row owner; checking a
102
+ wrong user neither authorizes that user nor poisons the owner's verdict.
103
+ `invalidate(sessionId)` clears that credential regardless of requested user.
104
+ Positive freshness is capped by both TTL and observed row expiry.
105
+
106
+ `SessionRevocationChecker` implementers must provide `isLiveFor`, `invalidate`
107
+ and a finite nonnegative `ttlMs`. The ownerless `isLive` method is removed;
108
+ unsupported objects fail construction rather than becoming cache options.
109
+ Options accept only finite nonnegative `ttlMs`, nonnegative safe-integer
110
+ `maxEntries` and a `now` clock function. Zero `maxEntries` disables caching.
111
+ Normal HTTP auth, carried strategies and Cloud reauthorization/renewal pass
112
+ the verified subject ID. Native root ownership, current account authorization
113
+ and protected write fences remain separate requirements. Existing signed
114
+ payloads and session schemas do not change. Run `voltro update` to receive the
115
+ manual migration instructions for custom checker calls and implementations.
116
+
117
+ With `requireSessionId: true`, a missing checker fails authentication even if
118
+ the signed payload carries an ID. Wire a store, registry or conforming checker;
119
+ the flag alone does not prove a persisted session.