feat(v2): complete v2 reimplementation

This commit is contained in:
2026-07-31 13:33:39 +02:00
parent 396219e776
commit bd107d6a30
137 changed files with 20737 additions and 155 deletions
+9
View File
@@ -0,0 +1,9 @@
# Notification security policy (M12)
Webhook callbacks accept absolute `http` and `https` URLs only. HTTP is an approved compatibility option, not a relaxation of egress controls. URLs with credentials, fragments, literal IP addresses, or ports outside 80/443/8080/8443 are rejected. Immediately before every request the worker resolves all A/AAAA answers; any non-global answer rejects the whole destination. The transport connects only to an approved answer, verifies the connected peer address, disables proxy environment use, preserves HTTPS SNI/certificate validation, and rejects redirects.
Webhook bodies are canonical JSON event envelopes. `X-Backup-Event-ID` is stable over retries. Each attempt supplies the versioned HMAC-SHA-256 timestamp/body input and one `X-Backup-Signature` header per active or overlap key. Key IDs and monotonically increasing subscription-local versions identify keys; an old key is retained only until its configured overlap expiry. Key material is encrypted in `secrets` and is never returned, logged, exported in recovery bundles, or included in audit/event payloads.
SMTP is configured as one write-only password-backed singleton. Delivery performs EHLO, verified STARTTLS, a second EHLO, and SMTP AUTH; any inability to do this fails closed. Message content is a compact event summary with no attachments, Bcc, paths, raw exception text, credentials, or full webhook payload.
Delivery is at-least-once. A worker crash after a send but before recording success can lead to a duplicate; consumers must deduplicate using the event ID. Redirects, malformed destinations, and SSRF validation failures are terminal. Connect/read transport failures, SMTP transient failures, and HTTP 408/425/429/5xx use bounded retry. Deployment egress controls are defense in depth, not a substitute for this policy.
+35
View File
@@ -0,0 +1,35 @@
# Repository encryption threat model
## Status
This document defines the M11 repository-encryption boundary. Encrypted repository
creation remains disabled until the recovery host-loss acceptance test passes.
## Confidential data
For an `aes-256-gcm` repository, blob contents and signed manifest contents are
AEAD-encrypted. Data keys and signing private keys are never stored in repository
metadata, SQLite, logs, command arguments, environment output, or API responses.
Recovery bundles are separately passphrase-encrypted.
## Intentional leakage
The v1 content-addressed layout retains plaintext SHA-256 blob names. Encryption
therefore leaks blob equality, object count, repository layout, manifest/backup
identifiers, and ciphertext sizes derived from plaintext sizes. It does not claim
to hide those values, a compromised running host with unlocked keys, source data
while it is read, or a recovery-bundle passphrase.
## Key lifecycle
Encryption uses distinct data and signing keys. Rotation creates a new data-key
epoch for subsequent objects and retains historical epochs so existing backups
remain verifiable and restorable. It neither changes immutable repository policy
nor rewrites existing objects.
## Recovery boundary
Recovery export, validation, and import are local CLI operations only. A bundle
contains the required key material and an authenticated catalog; passphrases are
not accepted on command lines. Bundle parsing must reject malformed or unsupported
parameters without revealing whether a passphrase, key, or ciphertext was wrong.