The config schema accepts usage_db = "<path>" (see conf/config.dev.toml:13 and the deployed config rendered by postguard-ops in main.tf:423), but CryptifyConfig in src/config.rs doesn't parse the field and nothing in src/store.rs ever reads or writes it. Quota state lives only in Store.shared.state.usage: HashMap<String, VecDeque<UploadRecord>> (src/store.rs:97), so any pod restart or redeploy wipes everyone's rolling quota — and there's no way to inspect or reset usage for a single user without a code change.
We should back the usage map with SQLite at the path given by usage_db:
- Parse
usage_db in RawCryptifyConfig / CryptifyConfig.
- On startup, open the DB and load existing records into the in-memory map (or query on demand).
- On
record_upload / prune_records, write through to SQLite.
- Mount a PVC for
cryptify_data_dir in the dev/prod Kubernetes deployments so the file survives pod restarts (currently /tmp/data, no volume).
Nice-to-have once persisted: a small admin endpoint to reset quota for a single email, which today requires restarting the whole pod.
The config schema accepts
usage_db = "<path>"(seeconf/config.dev.toml:13and the deployed config rendered by postguard-ops inmain.tf:423), butCryptifyConfiginsrc/config.rsdoesn't parse the field and nothing insrc/store.rsever reads or writes it. Quota state lives only inStore.shared.state.usage: HashMap<String, VecDeque<UploadRecord>>(src/store.rs:97), so any pod restart or redeploy wipes everyone's rolling quota — and there's no way to inspect or reset usage for a single user without a code change.We should back the usage map with SQLite at the path given by
usage_db:usage_dbinRawCryptifyConfig/CryptifyConfig.record_upload/prune_records, write through to SQLite.cryptify_data_dirin the dev/prod Kubernetes deployments so the file survives pod restarts (currently/tmp/data, no volume).Nice-to-have once persisted: a small admin endpoint to reset quota for a single email, which today requires restarting the whole pod.