The Cloudflare tunnel token, Cloudflare API token and git token inside customer_configs.config_json now hold the
05 §16.2 seal (enc:v1:, OFFSITE_SECRET_KEY). Old rows sealed once at start-up without a config_version bump, then
VACUUM + WAL checkpoint (an UPDATE leaves the old plaintext in a freed block). -unseal-box-secrets opens them too.
Eight tests, each red-proved. Built, not deployed. Audit: documentation/audits/hub-token-seal-2026-10-23/.
Opens the four sealed box-secret columns back to plaintext (all or nothing; keeps api_key_hash;
idempotent; counts only in the log) and exits before any start-up sealing, so hub 0.137.0 can run on
the database again.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
hosts.api_key, customer_configs.api_key / retrieval_password and host_pbs_secrets.value now hold the
R-821/R-133 seal (enc:v1:, OFFSITE_SECRET_KEY). The two API keys get an api_key_hash lookup twin
(SHA-256, backfilled keyless in migrate()), so box authentication never needs the sealing key; a row
with no hash is matched on its plaintext only while it is plaintext. SealLegacyBoxSecrets seals legacy
rows at start-up (idempotent, non-fatal). A sealed value that does not open sets SecretsUnreadable:
serve/compare paths answer 500, saves refuse the record, the PBS token is not burned.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS