diff --git a/docs/runbook-migrations.md b/docs/runbook-migrations.md deleted file mode 100644 index 9c1dcac..0000000 --- a/docs/runbook-migrations.md +++ /dev/null @@ -1,65 +0,0 @@ -# nsecbunkerd migration & DB-maintenance runbook - -Operational notes for applying schema migrations and ACL/pairing maintenance on -deployed, **LNbits-connected** nsecbunkerd instances. - -## ⚠️ Never full-wipe `nsecbunker.db` on an LNbits-connected instance - -The nsecbunkerd ↔ LNbits pairing is **split across both systems**: - -- **Bunker** (`nsecbunker.db`): per-account `KeyUser` binding (keyed by LNbits's - stable client pubkey) + redeemed `Token` + a shared `Policy`. -- **LNbits** (`accounts.signer_config`, `RemoteBunkerSigner`): - `{token, client_nsec, policy_id}`. - -`RemoteBunkerSigner.sign_event()` signs **directly with the stored `client_nsec`** -— it does NOT re-connect/re-redeem, and there is **no auto-repair** on restart or -sign-failure. `provision()` runs only at new-account creation and mints a NEW -npub (which changes the user's nostr identity). - -**Consequence of a full `nsecbunker.db` wipe:** the `KeyUser` bindings are -deleted → every LNbits account's stored config dangles → all signing fails, and -the only standard "repair" (`provision()`) changes identities. **Do not do it.** - -### Correct way to strip the #24 materialized photocopies - -Post-#27, token grants are evaluated live via the ACL step-4 `Token → Policy → -PolicyRule` join, so the old materialized `SigningCondition` rows are redundant -— and, written with `expiresAt = NULL`, they would keep granting past a token's -expiry (silently re-opening #24 for already-paired clients). Strip them with a -**targeted delete** that preserves the pairing: - -```sql --- Verify first. -SELECT COUNT(*) FROM Token WHERE redeemedAt IS NOT NULL; -- bindings to preserve -SELECT COUNT(*) FROM SigningCondition; -- photocopies to strip - --- Keeps KeyUser + Token + Policy intact. Live-token clients keep working --- untouched; only the stale photocopies are removed. -DELETE FROM SigningCondition; -``` - -Run against each instance's `nsecbunker.db`. If an instance was already -full-wiped, recover by restoring the pre-wipe `nsecbunker.db` backup, then run -the targeted delete. - -> Manual-override grants (`add_signing_condition`, web-approval) also live in -> `SigningCondition`. On an LNbits-only bunker there typically are none, so a -> blanket `DELETE FROM SigningCondition` is safe. If an instance uses manual -> overrides, delete only the policy-derived rows you intend to strip. - -## Keys are never in the DB - -Key material lives in `nsecbunker.json` (`keys`), never in `nsecbunker.db`. A DB -wipe loses ACL/pairing state, never keys. LNbits holds the bunker **admin nsec** -(`LNBITS_NSEC_BUNKER_ADMIN_NSEC`) and is the sole admin client. - -## Schema migrations - -Migrations are applied by the deploy's `prisma migrate deploy`, **not** by the -daemon on boot — the in-`start.js` `npm run prisma:migrate` step is a no-op -(tracked in #31). After adding a migration, make sure the deploy applies it. - -Prisma on NixOS needs the engine env pinned to `prisma-engines_6` (the bare -`prisma-engines` attr is now 7.x with no `libquery_engine.node`; devShell fix -tracked in #30). The deploy's `package.nix` already pins `_6`.