Zero Accessby Railmandocs

Vault guide

Create a vault, unlock daily, and recover without making the recovery phrase the everyday path.

Vault guide

Product vault UX lives in @railman/zero-vault. The Better Auth plugin only stores wraps you already produced.

Composition

Wire the full stack with Vault composition. This page is the create / unlock / recover ceremony.

Live demo: Vault lab

Create

import { createVaultClient } from "@railman/zero-vault";

const vault = createVaultClient({ userId: session.user.id });

const created = await vault.createVault({
  password: vaultPassword, // optional daily method
  // prfSecret + encryptionCredentialId after WebAuthn get
  accountRecovery: false, // set true for Mode B account+vault
});

// Force export before continuing
created.init.exportRecoveryPhrase();

// Persist:
// POST created.mekBody → /zero-access/mek
// POST each created.dailySlots → /zero-access/wrap-slots

What you just did:

  1. Generated a MEK client-side
  2. Wrapped it under a recovery KEK (BIP-39)
  3. Optionally wrapped it under password and/or PRF
  4. Asked the user to export the phrase
  5. Sent only ciphertext to the server

Daily unlock

const slots = await fetchWrapSlots(); // GET /zero-access/wrap-slots

const result = await vault.unlockDaily({
  slots,
  prfSecret, // from extractPrfSecret after WebAuthn
  password, // vault password, never sent to server
});

if (!result.ok) {
  // not_provisioned | no_daily_method | password_required | ...
}

Order of attempts: PRF slots first, then password slots. Recovery slots are ignored here on purpose.

Recovery reset

const unlocked = await vault.resetWithRecoveryPhrase({
  slots,
  mnemonic,
});

// Immediately re-enroll daily methods so the user is not phrase-dependent
const newDaily = await vault.reenrollDailyMethods({
  slots,
  mnemonic,
  prfSecret,
  password,
});
// POST new wraps; revoke lost PRF slots if needed

reenrollDailyMethods re-unlocks a short-lived grant MEK (session MEK cannot plant wraps). Pass fresh slots + secrets — do not reuse the session unlocked from resetWithRecoveryPhrase.

Idle lock

MEK session stores support idle timeout (default on the order of 15 minutes). When idle expires, require unlock again — elevate status is unrelated.

UI checklist

MomentProduct should
CreateForce phrase export + confirm storage
DailyPrefer passkey; fall back to vault password
Missing daily methodsPrompt re-enroll after recovery, not “paste phrase every day”
PRF unsupportedClear toast; password path if provisioned

On this page