0009: Catalog identity for inventories and previews¶
Date: 2026-10-07 · Status: accepted
Context¶
Every object Keeper writes is encrypted with age to the store's recipients, and the private key is meant to be kept offline or in a tightly held secret used only by restores. The console, however, has to read inventories (tables, rows, schema) and masked change previews to show versions, diffs and "what changed". These are small and hold no row data except masked previews. Giving keeper-api the restore key would let a compromised API decrypt every backup.
Decision¶
BackupStore.spec.encryption.catalogRecipientslists extra age recipients. The mover encrypts only the inventory object, and the streamer encrypts only preview objects, to the store recipients plus the catalog recipients. Data objects (dumps, base backups, WAL, binlogs, exports) use the store recipients only.BackupStore.spec.encryption.catalogIdentitySecret(in Keeper's namespace) holds the matching identity. Only keeper-api reads it.- Without a catalog identity keeper-api falls back to the store's data identity secret. That is less isolation, so production stores should configure a catalog key. If neither secret is readable, the console still works from manifests (sizes, times, counts, schema hash) and shows inventory, diff and previews as "not available".
Consequences¶
A leaked keeper-api can expose schemas and masked previews, never table data. Rotating the catalog key affects new backups only. Older inventories stay readable with the store identity. Restore jobs keep using the store identity.