Summary
On 2026-07-04 an agent misidentified the live Hindsight banks as orphaned and issued DELETE /api/memory/banks/{bank_id}, irreversibly cascade-deleting ~632 records across private__hermes-agent (275 facts), private__hermes, and shared. Recovered from a PBS backup.
Root cause
DELETE /api/memory/banks/{bank_id} (src/hal0/api/routes/memory_admin.py, _FORWARDS) is a bare passthrough to Hindsight with no confirmation, no soft-delete, no auth. The entire /api/memory/* surface is unauthenticated and bound on 0.0.0.0:8080, so any LAN host — or an agent's terminal/tool — can wipe a bank with one curl, bypassing the UI confirm dialog. Contributing UX bug: the dashboard mislabels the banks (colon vs double-underscore spelling; list?bank returns wrong data) which fed the misdiagnosis.
Fixes (branch fix/memory-tab-functional, hotpatched on CT105)
DELETE /banks/{id} now requires ?confirm=<bank_id> (or body {"confirm":...}); mismatch → 400, no forward.
GET /api/memory/list?bank= alias mapped to dataset (was silently returning default-dataset rows).
Remaining hardening (this issue)
- Reintroduce write-auth (bearer or localhost-only) on mutating
/api/memory/* routes; keep reads open if desired.
- Soft-delete / tombstone for banks (rename + TTL purge) so deletes are reversible.
- Audit-log every destructive memory op.
Summary
On 2026-07-04 an agent misidentified the live Hindsight banks as orphaned and issued
DELETE /api/memory/banks/{bank_id}, irreversibly cascade-deleting ~632 records acrossprivate__hermes-agent(275 facts),private__hermes, andshared. Recovered from a PBS backup.Root cause
DELETE /api/memory/banks/{bank_id}(src/hal0/api/routes/memory_admin.py,_FORWARDS) is a bare passthrough to Hindsight with no confirmation, no soft-delete, no auth. The entire/api/memory/*surface is unauthenticated and bound on0.0.0.0:8080, so any LAN host — or an agent's terminal/tool — can wipe a bank with one curl, bypassing the UI confirm dialog. Contributing UX bug: the dashboard mislabels the banks (colon vs double-underscore spelling;list?bankreturns wrong data) which fed the misdiagnosis.Fixes (branch
fix/memory-tab-functional, hotpatched on CT105)DELETE /banks/{id}now requires?confirm=<bank_id>(or body{"confirm":...}); mismatch → 400, no forward.GET /api/memory/list?bank=alias mapped to dataset (was silently returning default-dataset rows).Remaining hardening (this issue)
/api/memory/*routes; keep reads open if desired.