feat(523): backup destinations - a folder or an S3 bucket, with the S3 secret sealed and kept out of backups
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 15s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 1m8s
CI & Build / Python tests (push) Successful in 1m53s
CI & Build / Build & push image (push) Successful in 36s

services/backup_s3.py is FabledSteward's SigV4 client ported (put + list,
never delete, so an append-only key is enough), with its tests against
AWS's published signatures. services/backup_destination.py holds the
admin config (backup_config JSON) and delivers a dated tar to a mounted
folder or a bucket, and checks either without sending a backup.
services/secrets.py seals the S3 secret with Fernet under a key derived
from SECRET_KEY; backup._SETTINGS_NOT_EXPORTED keeps it out of every
backup. cryptography becomes a direct dependency (already in the image
through pyjwt).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 17:31:08 -04:00
co-authored by Claude Opus 5.5
parent 1942a7a336
commit ff4f2ee5c2
8 changed files with 786 additions and 1 deletions
Generated
+2
View File
@@ -1508,6 +1508,7 @@ dependencies = [
{ name = "asyncpg" },
{ name = "bcrypt" },
{ name = "caldav" },
{ name = "cryptography" },
{ name = "fastembed" },
{ name = "httpx" },
{ name = "hypercorn" },
@@ -1533,6 +1534,7 @@ requires-dist = [
{ name = "asyncpg", specifier = ">=0.29" },
{ name = "bcrypt", specifier = ">=4.0" },
{ name = "caldav", specifier = ">=1.3" },
{ name = "cryptography" },
{ name = "fastembed", specifier = ">=0.4" },
{ name = "httpx", specifier = ">=0.27" },
{ name = "hypercorn", specifier = ">=0.17" },