# FileFriend vault backend — honest status (B19)

Date: 2026-09-16. Live: OFF.

## The tag

**`local-vault` · cloudSync: false · "Local vault only — cloud sync is not
connected. Envelopes move between devices by handoff link."**

This is the live status, derived in code by `backendTag(null)` in
`vault-sync.mjs` and painted on `sign.html` (`#backend-tag`). It is not a
roadmap slide: until a remote is configured, the page says local vault.

## What works today (no backend)

- `sign.html` creates signature envelopes (`sign-envelope.mjs`).
- The signer opens the handoff link on a **second device**, signs on a canvas,
  and sends the result link back — full cross-device collection over any
  messenger, no account, no login.
- Every envelope also lands in the on-device vault (`localStorage`), with
  last-writer-wins merge by `(version, updatedAt)` (`vault-sync.mjs`).

## What "cloud vault sync" means when connected

Set `window.FILEFRIEND_VAULT_URL` (or wire the host page) to a JSON endpoint
implementing:

- `GET <base>/vault/pull[?since=]` → `{ "envelopes": { <id>: <envelope> } }`
- `POST <base>/vault/push` with the vault state → `2xx`

Then `syncWithRemote()` pushes/pulls, `backendTag()` flips to
`cloud-vault · cloudSync: true`, and the page badge flips with it. The
`httpRemote()` adapter, the merge rules, and the failure codes
(`VAULT_REMOTE_UNCONFIGURED`, `VAULT_REMOTE_ERROR`, `VAULT_REMOTE_HTTP_<n>`)
are built and tested; only the server URL is missing. No server URL exists in
this repo and none is invented here.

## What is NOT claimed

- Signatures carry an FNV-1a integrity checksum, **not** a cryptographic seal.
- Nothing is "synced to the cloud" anywhere in the UI or copy.

---

# FileFriend Filo drafting — honest status (B20)

Date: 2026-09-16. Live: OFF.

## The tag

**`template fallback` · "Filo drafting is not connected on this door yet."**

This is the live status: no `/api/filo/build` route and no model key are
configured on this static door, so `filo.html` paints the fallback tag and
the Draft button routes to a blank envelope (`sign.html`). It is not a
roadmap slide: until a route is wired, the page says fallback.

## What works today (no key)

- `filo.html` + `filo.js` take a one-paragraph brief and hand back a next
  step — today that step is the honest template fallback
  (`FILO_TEMPLATE_FALLBACK`, `reason: 'no-key'`), linking the real
  `sign.html` create view. Never a dead button, never an invented library.
- The keyed path and the credit meter are built and tested below; only the
  founder key is missing, and none is invented here.

## What "keyed-live" means when connected (B20 contract)

1. The host mounts `filo-route.mjs` as `POST /api/filo/build` (the `app.js`
   contract in `BACKLOG-2026-07-28.md`) and sets **`GEMINI_API_KEY`** in the
   server environment — the exact founder key this item waits on. The client
   never sends, sees, or holds the key (`filo.js` POSTs only `{ prompt }`).
2. The host wires a meter (`filo-meter.mjs`, default 1 credit per build) and
   grants credits (pay-per-doc / Rail Pass). `buildWithFilo()` charges BEFORE
   touching the network — broke callers get `FILO_NO_CREDITS` (HTTP 402) with
   zero model spend — and refunds the reserved credit when the model call
   itself fails (you pay for drafts you got, not for our outage).
3. Set `window.FILEFRIEND_FILO_URL` to the route URL; the `filo.html` tag
   flips to "keyed drafting behind the credit meter" and drafts render.
   Balances never go negative; the key travels in the `x-goog-api-key`
   header (never the URL) and never appears in results or logs.

## What is NOT claimed

- Filo drafts are AI-generated starting text, **not** legal advice and
  **not** counsel (counsel/RON/legal Q&A stay lawyer-gated per `PATH.md`).
- Nothing here sends mail, files, or pays anything by itself.
