Skip to main content

Account and access API

Recoverable accounts

The root @nzip/lofi export owns principal replacement and runtime cleanup:

APIPurpose
readAccountSession()Opens the runtime and returns the stable user_id and account state.
createRecoverablePasskeyBackup()Backs up the active Jazz secret to a resident, user-verifying passkey.
restoreFromPasskey(options)Restores that secret, saves it for the app ID, replaces the runtime, and elects sync.
revealRecoveryPhrase()Returns the portable bearer-secret fallback. Do not persist or log it.
restoreFromRecoveryPhrase(phrase, options)Performs the same replacement lifecycle from the phrase.

Both restore APIs require confirmLocalReplacement: true when a different local-only account would be discarded. RecoverablePasskeyError maps unsupported browsers, cancellation, missing credentials, RP-ID mismatch, and verification failure to non-secret, actionable messages.

createBackupPasskey() and confirmPhraseAccess() are retained compatibility APIs for a local phrase-reveal guard. That credential cannot restore an account.

Access templates

Import from @nzip/lofi/access:

  • Schema helpers: sharedGrantTable, groupMembershipTable.
  • Policy templates: privateAccess, sharedAccess, groupAccess, defineAccessPolicies.
  • Identities: sharingIdentity, encodeSharingIdentity, decodeSharingIdentity.
  • Operations: createSharingOperations, createGroupOperations.
  • Fixed roles: reader, contributor, writer, admin.

Sharing operations provide share, revoke, listShares, and sharedWithMe. Group operations provide createGroup, addMember, changeRole, removeMember, leaveGroup, and listMembers. Collaboration operations reject local-only use with AccessError.code === "sync-required".

In pinned Jazz alpha.53, the permission authority does not expose a group inserted earlier in the same transaction to the first membership's allowedTo.update("groupId") check. createGroup therefore serializes the creator-owned group write and first-admin membership write, and attempts a compensating group delete if the membership is rejected. The compensating delete is authorized by the creator's direct delete authority on their own group rows, so a failed bootstrap does not strand an orphan group. This is secure, but it is not database-transaction atomic. Do not describe it as atomic until Jazz can validate that relationship against staged transaction rows.

The group creator additionally holds a permanent superseat — see Permission templates and the decision record.

The templates compile ordinary Jazz policies and accept a final raw-policy callback. They do not replace s.table, s.defineApp, or raw s.definePermissions; use those directly when the fixed models do not fit.