v0.289.0: off-site key cannot delete — append-only rclone transport, box sends only its public key (hub registrar), retention only inside a hub window behind the fake-snapshot guard (decisions 68-69, R-820, R-822)
gates / gates (push) Successful in 27s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-03 17:01:36 +02:00
parent 09453325d1
commit 55bb6c3d32
15 changed files with 1039 additions and 386 deletions
+10
View File
@@ -314,6 +314,10 @@ type OffboxTarget struct {
// apply-bridge. 0 = no soft limit (dedicated boxes are Hetzner-enforced; manual targets unset).
// Felhom-enforced: at ≥100% NEW backup runs are refused (prune/restore never are); ≥80% warns.
QuotaGB int `json:"quota_gb,omitempty"`
// Transport (v0.289.0, decision 69): "rclone-pinned" for the HUB-provisioned Storage Box tier — the
// box's key reaches only an append-only rclone server and cannot delete; "" (the default) is the
// household's own SFTP NAS target, unchanged. Set by ApplyOffsiteTarget, never by a form.
Transport string `json:"transport,omitempty"`
// Runtime status (written by the off-box runner; never holds a secret).
LastRun string `json:"last_run,omitempty"` // RFC3339
@@ -1330,6 +1334,12 @@ func (s *Settings) GetOffboxTarget() *OffboxTarget {
}
// SetOffboxTarget saves (or clears, on nil) the off-box target config.
// TransportRclonePinned marks the hub-provisioned, append-only off-site tier (decision 69).
const TransportRclonePinned = "rclone-pinned"
// Pinned reports whether the target is the append-only hub tier.
func (t *OffboxTarget) Pinned() bool { return t != nil && t.Transport == TransportRclonePinned }
func (s *Settings) SetOffboxTarget(t *OffboxTarget) error {
s.mu.Lock()
defer s.mu.Unlock()