1# Account and access API23## Recoverable accounts45The root `@nzip/lofi` export owns principal replacement and runtime cleanup:67| API | Purpose |8| -------------------------------------------- | ------------------------------------------------------------------------------------- |9| `readAccountSession()` | Opens the runtime and returns the stable `user_id` and account state. |10| `createRecoverablePasskeyBackup()` | Backs up the active Jazz secret to a resident, user-verifying passkey. |11| `restoreFromPasskey(options)` | Restores that secret, saves it for the app ID, replaces the runtime, and elects sync. |12| `revealRecoveryPhrase()` | Returns the portable bearer-secret fallback. Do not persist or log it. |13| `restoreFromRecoveryPhrase(phrase, options)` | Performs the same replacement lifecycle from the phrase. |1415Both restore APIs require `confirmLocalReplacement: true` when a different local-only account would16be discarded. `RecoverablePasskeyError` maps unsupported browsers, cancellation, missing17credentials, RP-ID mismatch, and verification failure to non-secret, actionable messages.1819`createBackupPasskey()` and `confirmPhraseAccess()` are retained compatibility APIs for a local20phrase-reveal guard. That credential cannot restore an account.2122## Access templates2324Import from `@nzip/lofi/access`:2526- Schema helpers: `sharedGrantTable`, `groupMembershipTable`.27- Policy templates: `privateAccess`, `sharedAccess`, `groupAccess`, `defineAccessPolicies`.28- Identities: `sharingIdentity`, `encodeSharingIdentity`, `decodeSharingIdentity`.29- Operations: `createSharingOperations`, `createGroupOperations`.30- Fixed roles: `reader`, `contributor`, `writer`, `admin`.3132Sharing operations provide `share`, `revoke`, `listShares`, and `sharedWithMe`. Group operations33provide `createGroup`, `addMember`, `changeRole`, `removeMember`, `leaveGroup`, and `listMembers`.34Collaboration operations reject local-only use with `AccessError.code === "sync-required"`.3536In pinned Jazz alpha.53, the permission authority does not expose a group inserted earlier in the37same transaction to the first membership's `allowedTo.update("groupId")` check. `createGroup`38therefore serializes the creator-owned group write and first-admin membership write, and attempts a39compensating group delete if the membership is rejected. The compensating delete is authorized by40the creator's direct delete authority on their own group rows, so a failed bootstrap does not strand41an orphan group. This is secure, but it is not database-transaction atomic. Do not describe it as42atomic until Jazz can validate that relationship against staged transaction rows.4344The group creator additionally holds a permanent superseat — see45[Permission templates](../permissions.md#fixed-group-roles) and46[the decision record](../decisions/group-creator-authority-alpha53.md).4748The templates compile ordinary Jazz policies and accept a final raw-policy callback. They do not49replace `s.table`, `s.defineApp`, or raw `s.definePermissions`; use those directly when the fixed50models do not fit.