7.0 KiB
7.0 KiB
Feature Specification: Backup Scheduling MVP (032)
Feature: Automatisierte Backups per Zeitplan (pro Tenant) Created: 2026-01-05 Status: Ready for implementation (MVP) Risk: Medium (Backup-only, no restore scheduling) Dependencies: Tenant Portfolio + Tenant Context Switch ✅
Context
TenantPilot unterstützt manuelle Backups. Kunden/MSPs benötigen regelmäßige, zuverlässige Backups pro Tenant (z. B. nightly), inkl. nachvollziehbarer Runs, Fehlercodes und Retention.
Goals
- Pro Tenant können 1..n Backup Schedules angelegt werden.
- Schedules laufen automatisch via Queue/Worker.
- Jeder Lauf wird als Run auditierbar gespeichert (Status, Counts, Fehler).
- Retention löscht alte Backups nach Policy.
- Filament UI: Schedules verwalten, Run-History ansehen, “Run now”, “Retry”.
Clarifications
Session 2026-01-05
- Q: Wie sollen wir mit
policy_typesumgehen, die nicht inconfig('tenantpilot.supported_policy_types')enthalten sind? → A: Beim Speichern hart validieren und ablehnen; zur Laufzeit defensiv re-checken (Legacy/DB), unknown types skippen und Run alspartialmarkieren miterror_code=UNKNOWN_POLICY_TYPEund Liste betroffener Types. - Q: Wenn zur Laufzeit alle
policy_typesunbekannt sind (0 valid types nach Skip) – welcher Status? → A:skipped(fail-safe).
Non-Goals (MVP)
- Kein Kalender-UI als Pflicht (kann später ergänzt werden).
- Kein Cross-Tenant Bulk Scheduling (MSP-Templates später).
- Kein “drift-triggered scheduling” (kommt nach Drift-MVP).
- Kein Restore via Scheduling (nur Backup).
Definitions
- Schedule: Wiederkehrender Plan (daily/weekly, timezone).
- Run: Konkrete Ausführung eines Schedules (scheduled_for + status).
- BackupSet: Ergebniscontainer eines Runs.
MVP Semantik: 1 Run = 1 neues BackupSet (kein Rolling-Reuse im MVP).
Requirements
Functional Requirements
- FR-001: Schedules sind tenant-scoped via
tenant_id(FK auftenants.id). - FR-002: Dispatcher erkennt “due” schedules und erstellt genau einen Run pro Zeit-Slot (idempotent).
- FR-003: Run nutzt bestehende Services:
- Sync Policies (nur selektierte policy types)
- Create BackupSet aus lokalen Policy-IDs (inkl. Foundations optional)
- FR-003a:
policy_typessind ausschließlich Keys ausconfig('tenantpilot.supported_policy_types'). - FR-003b: UI/Server-side Validation verhindert das Speichern unbekannter
policy_types. - FR-003c: Laufzeit-Validierung (defensiv): Unbekannte
policy_typeswerden geskippt; wenn mindestens ein gültiger Type verarbeitet wurde, wird der Run alspartialmarkiert underror_code=UNKNOWN_POLICY_TYPEgesetzt (inkl. Liste der betroffenen Types insummary). - FR-003d: Wenn zur Laufzeit nach dem Skip 0 gültige Types verbleiben, wird kein BackupSet erzeugt und der Run als
skippedmarkiert (miterror_code=UNKNOWN_POLICY_TYPEund Liste der betroffenen Types insummary). - FR-004: Run schreibt
backup_schedule_runsmit Status + Summary + Error-Codes. - FR-005: “Run now” erzeugt sofort einen Run (scheduled_for=now) und dispatcht Job.
- FR-006: “Retry” erzeugt einen neuen Run für denselben Schedule.
- FR-007: Retention hält nur die letzten N BackupSets pro Schedule (soft delete BackupSets).
- FR-008: Concurrency: Pro Schedule darf nur ein Run gleichzeitig laufen. Wenn bereits ein Run läuft, wird ein neuer Run nicht parallel gestartet und stattdessen als
skippedmarkiert (mit Fehlercode).
UX Requirements (Filament)
- UX-001: Schedule-Liste zeigt Enabled, Frequency, Time+Timezone, Policy Types Summary, Retention, Last Run, Next Run.
- UX-002: Run-History pro Schedule zeigt scheduled_for, status, duration, counts, error_code/message, Link zum BackupSet.
- UX-003: “Run now” und “Retry” sind nur mit passenden Rechten verfügbar.
Security / Authorization
- SEC-001: Tenant Isolation: User sieht/managt nur Schedules des aktuellen Tenants.
- SEC-002 (MVP): Authorization erfolgt über TenantRole (wie Tenant Portfolio):
readonly: Schedules ansehen + Runs ansehenoperator: zusätzlich “Run now” / “Retry”manager/owner: zusätzlich Schedules verwalten (CRUD)
- SEC-003: Dispatcher, Run-Execution und Retention schreiben tenant-scoped Audit Logs (keine Secrets/Tokens), inkl. Run-Start/Run-Ende und Retention-Ergebnis (z. B. Anzahl gelöschter BackupSets).
Reliability / Non-Functional Requirements
- NFR-001: Idempotency durch Unique Slot-Constraint (
backup_schedule_id+scheduled_for). - NFR-002: Klare Fehlercodes (z. B. TOKEN_EXPIRED, PERMISSION_MISSING, GRAPH_THROTTLE, UNKNOWN).
- NFR-003: Retries: Throttling (z. B. 429/503) → Backoff; 401/403 → kein Retry; Unknown → begrenzte Retries und danach failed.
- NFR-004: Missed runs policy (MVP): No catch-up — wenn offline, wird nicht nachgeholt, nur nächster Slot.
Scheduling Semantics
scheduled_forist minute-basiert (Slot), in UTC gespeichert. Due-Berechnung erfolgt in der Schedule-Timezone.- DST (MVP): Bei ungültiger lokaler Zeit wird der Slot übersprungen (Run
skipped). Bei ambiger lokaler Zeit wird die erste Occurrence verwendet.
Data Model
backup_schedules
idbiginttenant_idFK tenants.idnamestringis_enabledbool default truetimezonestring default 'UTC'frequencystring enum: daily|weeklytime_of_daytimedays_of_weekjson nullable (array, weekly only; 1=Mon..7=Sun)policy_typesjsonb (array)include_foundationsbool default trueretention_keep_lastint default 30last_run_atdatetime nullablelast_run_statusstring nullablenext_run_atdatetime nullable- timestamps
Indexes:
- (tenant_id, is_enabled)
- (next_run_at) optional
backup_schedule_runs
idbigintbackup_schedule_idFKtenant_idFK (denormalisiert)scheduled_fordatetimestarted_atdatetime nullablefinished_atdatetime nullablestatusstring enum: running|success|partial|failed|canceled|skippedsummaryjsonb (policies_total, policies_backed_up, errors_count, type_breakdown, warnings)error_codestring nullableerror_messagetext nullablebackup_set_idFK nullable- timestamps
Indexes:
- (backup_schedule_id, scheduled_for)
- (tenant_id, created_at)
- Unique: (backup_schedule_id, scheduled_for)
Acceptance Criteria
- User kann pro Tenant einen Schedule anlegen (daily/weekly, time, timezone, policy types, retention).
- Dispatcher erstellt Runs zur geplanten Zeit (Queue Worker vorausgesetzt).
- UI zeigt Last Run + Next Run + Run-History.
- Run now startet sofort.
- Fehlerfälle (Token/Permission/Throttle) werden als failed/partial markiert mit error_code.
- Unbekannte
policy_typeskönnen nicht gespeichert werden; falls Legacy-Daten vorkommen, werden sie zur Laufzeit geskippt: mit valid types →partial, ohne valid types →skipped(jeweilserror_code=UNKNOWN_POLICY_TYPE). - Retention hält nur die letzten N BackupSets pro Schedule.