Hooks Reference

The package exports exactly three hooks: useIdentity, useSecret, and useP47h. All must be used inside a <P47hProvider>.

Identity & Session

useIdentity()

Authentication state and actions — register, login, logout, recover.

const {
  did,              // string | null  — the current DID
  isAuthenticated,  // boolean
  isLoading,        // boolean         — an auth operation is in progress
  error,            // Error | null
  storedIdentities, // string[]        — DIDs available locally
  register,         // (password: string) => Promise<{ did: string; recoveryCode: string }>
  login,            // (password: string, did?: string) => Promise<void>
  logout,           // () => void
  recover,          // (recoveryCode: string, newPassword: string) => Promise<void>
} = useIdentity();

Behavior:

  • register creates a new identity and returns its did and a one-time recoveryCode. Store the code offline.
  • login derives the master key and unlocks the vault.
  • logout locks the vault and zeroizes keys from WASM memory.
  • State updates trigger re-renders automatically.

Encrypted State

useSecret(key)

Read and write a single encrypted value. Returns an object (not a tuple).

const {
  value,   // string | null            — decrypted value, null if absent or locked
  set,     // (value: string) => void  — encrypts + persists (debounced)
  status,  // 'idle' | 'loading' | 'saving' | 'error'
  exists,  // boolean                  — value !== null
  locked,  // boolean                  — true when no identity is unlocked
  error,   // Error | null
} = useSecret("stripe_key");

Behavior:

  • Auto-loads when the vault unlocks; value is null while locked.
  • set is debounced to avoid excessive writes during typing.
  • Each key is independent and cached.

Vault Lifecycle

useP47h()

Low-level access to the full vault context. Prefer useIdentity / useSecret; reach for this only when they don’t cover your case.

const {
  state,           // current vault state (init / ready / locked / unlocked …)
  did,             // string | null
  isAuthenticated, // boolean
  isLoading,       // boolean
  error,           // Error | null
  // …plus the same identity actions exposed by useIdentity
} = useP47h();

Warning: this is the raw context. For reactive secret values, prefer useSecret.

There is no useSecrets, useVault, or useVaultStatus hook, and no policy hook (can / require). Those are not part of the published package.


Common Patterns

Conditional rendering based on auth

function App() {
  const { isAuthenticated, isLoading } = useIdentity();

  if (isLoading) return <Spinner />;
  if (!isAuthenticated) return <LoginForm />;

  return <Dashboard />;
}

Storing an API key

function ApiKeyInput() {
  const { value, set, status } = useSecret("openai_key");

  return (
    <input
      value={value ?? ""}
      onChange={(e) => set(e.target.value)}
      disabled={status === "loading"}
      placeholder="sk-..."
    />
  );
}

Auto-lock on inactivity

function AutoLock({ timeout = 300000 }) {
  const { logout, isAuthenticated } = useIdentity();

  useEffect(() => {
    if (!isAuthenticated) return;

    let timer: number;
    const reset = () => {
      clearTimeout(timer);
      timer = window.setTimeout(logout, timeout);
    };

    window.addEventListener("mousemove", reset);
    window.addEventListener("keypress", reset);
    reset();

    return () => {
      clearTimeout(timer);
      window.removeEventListener("mousemove", reset);
      window.removeEventListener("keypress", reset);
    };
  }, [isAuthenticated, logout, timeout]);

  return null;
}

Failure Modes

Wrong password

login() rejects with an AuthenticationError. The vault stays locked; no data is corrupted.

try {
  await login(password);
} catch (e) {
  // e is an AuthenticationError
}

Locked vault

While locked, useSecret(...).value is null and locked is true. Gate your UI on locked rather than assuming a value.

WASM load failure

If the WASM core fails to load, the provider surfaces the error: useP47h().error is set and the vault never becomes ready. <P47hProvider errorFallback={…}> lets you render a fallback. Common causes: a strict CSP blocking wasm-unsafe-eval, or the WASM asset not served at the expected path.

For cryptographic details, see Security Model.