feat(limb): persist pairing & access-policy state across API restarts#332
feat(limb): persist pairing & access-policy state across API restarts#332xu75 wants to merge 4 commits intozts212653:mainfrom
Conversation
…d access policies Implements the SQLite persistence layer for zts212653#331. Two tables: limb_pairings and limb_access_policies, with WAL mode and versioned migrations following the SqliteEvidenceStore pattern. [宪宪/Opus-46🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Write-through to SqliteLimbPersistence on every mutation. Optional constructor param — no persistence = pure in-memory (backward compat). initialize() loads persisted state into Map on startup. [宪宪/Opus-46🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On startup: open limb.sqlite → load approved pairings → create offline RemoteLimbNode stubs. Heartbeat flips them online. Env: LIMB_DB overrides default path. Closes zts212653#331 [宪宪/Opus-46🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Verifies: register → approve → set policy → teardown → reload from SQLite → offline stub → heartbeat → online. Full zts212653#331 cycle. [宪宪/Opus-46🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bbdaddd to
e3a8ec9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3a8ec9d4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }; | ||
|
|
||
| this.requests.set(request.requestId, request); | ||
| this.persistence?.upsertPairing(request); |
There was a problem hiding this comment.
Persist approved-pairing reconnect updates
Ensure reconnect-time mutations are written through to SQLite: createRequest() only persists when a new request is created, but the reconnect flow in registerLimbNodeRoutes mutates existing approved requests (notably endpointUrl) in place. With this commit’s restart recovery, those in-memory changes are lost on process restart, so recovered stubs can point to stale endpoints and route invokes to the wrong/unreachable host until another full re-register occurs.
Useful? React with 👍 / 👎.
PR Type
Related Issue
Closes #331
What
SQLite-backed persistence for the limb domain so approved pairings and access policies survive API restarts.
Changes
SqliteLimbPersistence(new) — WAL-mode SQLite layer with two tables (limb_pairings,limb_access_policies), versioned migrations following the existingSqliteEvidenceStorepattern.LimbPairingStore— optionalpersistenceconstructor param; write-through oncreateRequest(),approve(),reject();initialize()loads persisted state. No persistence = pure in-memory (backward compat).LimbAccessPolicy— same write-through pattern forsetPolicy();initialize()loads persisted policies.index.tsstartup recovery — on boot: openlimb.sqlite→ load approved pairings → create offlineRemoteLimbNodestubs → heartbeat flips them online.LIMB_DBenv var overrides default path.Tests (12 new)
sqlite-limb-persistence.test.js— 6 tests for raw SQLite CRUDlimb-pairing-store-persistence.test.js— 3 tests for PairingStore round-triplimb-access-policy-persistence.test.js— 2 tests for AccessPolicy round-triplimb-persistence-integration.test.js— 1 full lifecycle test (register → approve → policy → teardown → reload → offline stub → heartbeat → online)Why
Every API restart wipes all limb registrations. Users must re-approve pairings each time, making limb integrations fragile for production use.
Tradeoff
Test Evidence
All 102 existing + new tests pass (
pnpm --filter @cat-cafe/api test).AC Checklist
anytypes, biome clean