safety layer: hard daily budget, user quotas, spend report, forgetme + privacy

This commit is contained in:
Oleksandr Kozachuk
2026-07-13 13:21:45 +02:00
parent f6c3e7d8e5
commit 02c989946b
11 changed files with 465 additions and 6 deletions
+44
View File
@@ -31,3 +31,47 @@ and game descriptions are attacker-influenced input.
The `hack` envelope field remains as an advisory signal (logged,
staff-notified) but is no longer the defense.
### SAF-04 — Hard daily budget, fail-closed (coverage: test)
When `daily-budget-usd` is configured and today's estimated spend
reaches it, no further model or image calls happen: the responder
refuses before calling the API, and the bot answers nothing until
midnight. Staff get exactly one alert per day about the silence.
Cost estimation uses `price-input-per-m` (default 1.0),
`price-output-per-m` (default 6.0) and `price-per-image` (default
0.05). A budget of 0 means fully silent — fail-closed by
construction.
### SAF-05 — Usage is metered and survives restarts (coverage: test)
Token counts (prompt/completion) from every model call and every
generated image are recorded per calendar day; with a store
configured the counters persist across restarts (usage table,
schema v2).
### SAF-06 — Per-user daily message quota (coverage: test)
When `user-daily-messages` is configured, messages beyond the cap
from one user on one day are ignored (logged, no model call). The
`system` user (bot-initiated flows) is exempt.
### SAF-07 — Per-user daily image quota (coverage: test)
When `user-daily-images` is configured, picture requests beyond the
user's daily cap are stripped from the response (the text answer
still goes out).
### SAF-08 — !forgetme purges a user's history (coverage: test)
`!forgetme` removes the requesting user's messages from all live
responder histories and from the store, then confirms in-channel.
v1 limitation, stated in the confirmation: the single-string channel
memory may still contain summarized traces — full fact-level erasure
arrives with the structured memory (FDB-007).
### SAF-09 — !privacy states the data practice (coverage: test)
`!privacy` answers with the configured `privacy-notice` (a default
notice ships in code): what is stored, that `!forgetme` exists.
Works even while the bot is paused.
+6
View File
@@ -56,3 +56,9 @@ the alert text is written to the error log — never silently dropped.
`!bot tasks off` disables bot-initiated posting (today: the boreness
loop; later: the FDB-011 scheduler); `!bot tasks on` restores.
Bot-initiated posts also respect pause/quiet.
### OPS-10 — Spend report (coverage: test)
`!bot spend` answers in the staff channel with today's estimated
spend in USD, token and image counts, and the configured budget.
Management sees the cost, not just the cap.
+8 -1
View File
@@ -28,9 +28,16 @@ accident).
### PER-04 — Database hygiene (coverage: test)
The database runs in WAL journal mode, carries `PRAGMA user_version`
= schema version (currently 1) for future migrations/rollback
= the store's current schema version for the migration/rollback
policy, and the file is chmod 0600 (it stores conversation data).
### PER-06 — Schema migrations run forward automatically (coverage: test)
Opening a database with an older `user_version` applies the missing
migration steps in order (v1 → v2 adds the usage table) and preserves
existing rows. Deploy rollback policy: never roll binaries back past
a schema bump without restoring the pre-deploy backup.
### PER-05 — Writes run off the event loop (coverage: test)
History and memory persistence happen in a worker thread