#192: deploy-level backup target allowlist #247

Merged
fable-5 merged 1 commits from feat/192-backup-allowlist into main 2026-07-30 12:34:14 +02:00
Collaborator

Implements #192 (ADR 0026):

  • BACKUP_ALLOWED_TARGETS: deploy-level, comma-separated allowlist of permissible backup destination HOSTS - deliberately env-only so a compromised Site-Admin cannot widen it. Shared policy helpers (parse, host extraction for WebDAV URLs and rsync user@host:/path targets, case-insensitive match) in packages/shared.
  • api enforcement: settings write and connection test reject non-allowlisted hosts (codes backup_target_not_allowed / backup_remote_disabled_by_policy, i18n de+en); a configured target outside the list resolves to null (no remote listing/restore source).
  • Sidecar enforcement at the point of egress: resolveRemoteTarget (WebDAV upload + remote restore fetch) and resolveMirrorConfig (rsync mirror) return null with a warn log for blocked hosts.
  • BREAKING: empty default disables ALL remote targets - local only, the VS-NfD reference configuration. Existing deployments (Prod: Nextcloud + BASEL mirror) must set BACKUP_ALLOWED_TARGETS in the stage .env, called out in .env.example and operations.md - NOTE for the next release: the stage .env files on ONE need the value BEFORE the release rolls out, or uploads/mirror stop.
  • Admin UI distinguishes unavailable-by-policy from unconfigured (note + disabled controls) and shows the permitted hosts.

Tested: shared 189 (4 new policy tests), backup 48 (blocked-host cases for mirror and WebDAV), api full suite 455 green vs fresh DB twice (7 new allowlist e2e tests in two files - env is read at app boot; existing backup-admin suite allowlists its in-test WebDAV host), web 131, i18n:check, typecheck + lint green.

Refs #192 (close manually after green CI + merge).

Generated with Claude Code (Claude Fable 5)

Implements #192 (ADR 0026): - BACKUP_ALLOWED_TARGETS: deploy-level, comma-separated allowlist of permissible backup destination HOSTS - deliberately env-only so a compromised Site-Admin cannot widen it. Shared policy helpers (parse, host extraction for WebDAV URLs and rsync user@host:/path targets, case-insensitive match) in packages/shared. - api enforcement: settings write and connection test reject non-allowlisted hosts (codes backup_target_not_allowed / backup_remote_disabled_by_policy, i18n de+en); a configured target outside the list resolves to null (no remote listing/restore source). - Sidecar enforcement at the point of egress: resolveRemoteTarget (WebDAV upload + remote restore fetch) and resolveMirrorConfig (rsync mirror) return null with a warn log for blocked hosts. - BREAKING: empty default disables ALL remote targets - local only, the VS-NfD reference configuration. Existing deployments (Prod: Nextcloud + BASEL mirror) must set BACKUP_ALLOWED_TARGETS in the stage .env, called out in .env.example and operations.md - NOTE for the next release: the stage .env files on ONE need the value BEFORE the release rolls out, or uploads/mirror stop. - Admin UI distinguishes unavailable-by-policy from unconfigured (note + disabled controls) and shows the permitted hosts. Tested: shared 189 (4 new policy tests), backup 48 (blocked-host cases for mirror and WebDAV), api full suite 455 green vs fresh DB twice (7 new allowlist e2e tests in two files - env is read at app boot; existing backup-admin suite allowlists its in-test WebDAV host), web 131, i18n:check, typecheck + lint green. Refs #192 (close manually after green CI + merge). Generated with Claude Code (Claude Fable 5)
fable-5 added 1 commit 2026-07-30 12:17:32 +02:00
#192: deploy-level backup target allowlist
All checks were successful
CI / Lint, typecheck, test (pull_request) Successful in 4m52s
CI / Build container images (pull_request) Successful in 3m54s
CI / Auth e2e pack (pull_request) Successful in 8m4s
CI / Import/export fidelity gate (pull_request) Successful in 56s
CD / Build and push images (push) Successful in 19s
CD / Deploy to Test (push) Successful in 13s
CD / Smoke tests against Test (push) Successful in 1m14s
CD / Promote to Int (push) Successful in 11s
CI / Lint, typecheck, test (push) Successful in 5m0s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 7m41s
CI / Import/export fidelity gate (push) Successful in 56s
394d1c811d
BACKUP_ALLOWED_TARGETS (comma-separated destination hosts) constrains
where backups may go, enforced twice: the api rejects settings writes
and connection tests towards non-allowlisted hosts with admin-visible
error codes and resolves a non-allowlisted configured target to null,
and the sidecar enforces the same policy at the point of egress for the
WebDAV upload and the rsync mirror alike (shared policy helpers in
packages/shared/src/backup-target-policy.ts).

BREAKING: the empty default disables every remote target - backups stay
local only, the VS-NfD reference configuration (ADR 0026). Existing
deployments with a remote target must list its host or uploads and
mirror stop. The admin UI distinguishes unavailable-by-policy from
unconfigured (i18n de+en) and shows the permitted hosts.

Refs #192 (ADR 0026)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0168Ph5uBmHm8X28CSVpbpnJ
fable-5 merged commit 394d1c811d into main 2026-07-30 12:34:14 +02:00
Sign in to join this conversation.
No description provided.