--- name: passport-bootstrap description: Use when the user installs mnemo-mcp on a fresh machine and wants to restore prior memory state from S3 or Google Drive (Phase 2 passport sync). Triggers on phrases like "set up mnemo on this machine", "restore my memory passport", "import passport", "bootstrap mnemo", or when the user says they got a new laptop / VM and wants their memories back. argument-hint: "[backend: s3 | gdrive]" --- # Passport Bootstrap Restore an encrypted memory passport from a configured backend so a fresh mnemo-mcp install picks up the user's full memory history. ## When to Use Trigger on explicit signals: - "set up mnemo on this machine" - "restore my passport" / "import my memory passport" - "bootstrap mnemo on this laptop / VM" - New-machine context: "I just installed mnemo on a new device" - Recovery context: "I lost my memories, can you restore from S3?" Do NOT trigger when the user is on an already-configured machine (check `config(action="status")` first - if `total_memories > 0`, ask before importing because import LWW-merges and may NOT overwrite local rows newer than the bundle). ## Workflow ### Step 1: Detect configured backend Call `config(action="status")` and inspect the response. The default backend is the first entry of `SYNC_BACKEND` env (defaults to `gdrive`). If both `s3` and `gdrive` are configured, ask the user which one to import from. If neither is configured, stop and tell the user they need to run the relay form first (`config(action="setup_start")` in HTTP mode, or set `SYNC_S3_BUCKET` + `GOOGLE_DRIVE_CLIENT_ID` env vars in stdio mode). ### Step 2: Confirm passphrase The bundle is AES-256-GCM-encrypted with an Argon2id-derived key from the user's passphrase. The MCP server needs the RAW passphrase to decrypt - the Argon2id hash stored in `config.enc` is verification- only. In stdio mode: instruct the user to set `SYNC_PASSPHRASE` env var before running `mnemo-mcp` (or to relaunch with the env exported). In HTTP mode: prompt the user to submit the relay form's passphrase field again (the raw value is held in process memory only and is cleared on restart - it is NEVER persisted). ### Step 3: Import the bundle Call `config(action="import_passport", key="")` where `` is `s3` or `gdrive`. The server pulls the latest bundle from the chosen backend, decrypts with the supplied passphrase, and applies each row via last-write-wins per row (local rows newer than the bundle row are preserved + an audit row is written to `sync_overrides`). ### Step 4: Verify After the response lands, call `config(action="status")` again and confirm `total_memories` matches expectations. If the response from step 3 reports `inserted > 0` but `total_memories` did not move, something else is wrong (caller should escalate, not silently proceed). ## Failure Modes - **"SYNC_PASSPHRASE not set"** -> Step 2 was skipped. Re-prompt for the passphrase, do NOT pick a default value. - **"Passphrase mismatch or tampered bundle"** -> wrong passphrase, OR the bundle was modified at rest. Generic message by design (no passphrase oracle). Tell the user to double-check the passphrase; if confirmed correct, the bundle may need re-upload from a clean source. - **"no_passport"** -> the backend bucket / folder is empty. Either the user has never run `config(action="sync_now")` from another machine, or the bucket name in the relay form was wrong. Ask them to verify on the source machine. - **`KeyError` on backend name** -> backend isn't registered. Means `SYNC_S3_BUCKET` is empty (for s3) or the gdrive token is missing. Run the relay form to populate. ## Anti-Patterns - Do NOT call `config(action="sync_now")` before import - that would push the empty local DB on top of the remote, deleting other machines' state. - Do NOT call `memory(action="import", data=...)` - that imports Phase 1 JSONL files, NOT Phase 2 encrypted passport bundles. - Do NOT proceed silently when the user supplied no passphrase. Importing yields cryptic "Passphrase mismatch" errors instead of the cleaner "passphrase missing" pre-flight check.