Ka-Note/docs/feature-backup.md

6.1 KiB
Raw Blame History

Feature: Backup

Ka-Note hat zwei unabhängige Backup-Systeme:

  1. Scheduled Backup — automatische serverseitige ZIP-Exporte
  2. AI Workspace Export — lock-basierter Export/Import für KI-Agenten

1. Scheduled Backup

Konfiguration (Umgebungsvariablen)

Variable Default Beschreibung
BACKUP_ENABLED false Feature aktivieren
BACKUP_DIR /data/backups Speicherort
BACKUP_RETENTION_COUNT 14 Letzte N Backups behalten
BACKUP_CRON_HOUR 3 UTC-Stunde für automatischen Lauf

Ablauf

  • Server startet Scheduler beim Hochfahren (msUntilNextRun())
  • Täglich zur konfigurierten UTC-Stunde: ZIP pro User → backup-{userId}-{timestamp}.zip
  • Alte Backups werden automatisch gelöscht (Retention Count)

API Endpoints

Method Path Beschreibung
GET /api/backup/status Konfiguration & Schedule-Status
GET /api/backup/export On-demand Export (kein Lock)
POST /api/backup/run Geplanten Backup manuell auslösen
GET /api/backup/list Gespeicherte Backups auflisten
GET /api/backup/download/:filename Backup herunterladen
DELETE /api/backup/:filename Backup löschen
PATCH /api/backup/config Retention Count ändern

Client UI (/backup)

  • "Jetzt herunterladen" → GET /api/backup/export
  • Auto-Backup-Statusanzeige (nur wenn BACKUP_ENABLED=true): nächster Lauf, letzter Lauf, Retention-Editor
  • "Jetzt ausführen" → POST /api/backup/run
  • Tabelle gespeicherter Backups (neueste zuerst) mit Download/Löschen

Relevante Dateien

  • ka-note/server/src/lib/backup-service.ts
  • ka-note/server/src/routes/backup.ts
  • ka-note/client/src/routes/backup/+page.svelte

2. AI Workspace Export

Lock-basierter Export/Import für KI-Agenten. Verhindert Sync-Konflikte während KI-Edits.

Workflow

download.ps1  →  [KI bearbeitet work/]  →  upload.ps1
     |                                           |
 Lock acquired                            Lock released

Bei Unterbrechung: unlock.ps1 gibt Lock frei ohne Upload.

Lock-Mechanismus

  • Lock-Ablauf: AI_LOCK_EXPIRY_HOURS (Standard 24h, Projekt: 168 = 7 Tage)
  • Solange Lock aktiv: normaler Sync pausiert
  • Token im manifest.json des ZIPs → wird beim Upload validiert

API Endpoints

Method Path Beschreibung
GET /api/ai/status Lock-Status prüfen
GET /api/ai/download Export + Lock acquiren
POST /api/ai/upload Import + Lock freigeben
POST /api/ai/unlock Lock ohne Upload freigeben

Upload-Parameter: ?force=true überschreibt Version-Konflikte.

ZIP-Struktur

manifest.json            # userId, exportedAt, lockToken, expiresAt, exportVersion
contexts.json            # alle Contexts (inkl. soft-deleted)
topics.json              # alle Topics
ratings.json             # alle Ratings
history/{id}.meta.json   # History-Entry-Metadaten
history/{id}.md          # History-Entry-Text
wiki/{id}.meta.json      # Wiki-Seiten-Metadaten
wiki/{id}.md             # Wiki-Seiten-Text
images/{id}.{ext}        # Binäre Bildblobs
notebooks.json
page_notebooks.json

manifest.json-Felder: userId, exportedAt, lockToken, expiresAt, exportVersion

Pflichtfelder pro Entity

Context: id, name, type, sortOrder, meta, archivedAt, isFavorite, updatedAt, deletedAt, purgedAt, version

Topic: id, contextId, title, status, snoozeUntil, sortOrder, isNew, updatedAt, deletedAt, purgedAt, version

History (meta): id, topicId, date (YYYY-MM-DD), sortOrder, linkedContextId, doneAt, wiedervorlageDate, wiedervorlageResolvedAt, updatedAt, deletedAt, purgedAt, version → Kein contextId, kein title — History ist topic-scoped!

Rating: id, topicId, historyEntryId, personName, value (14), comment, updatedAt, deletedAt, purgedAt, version

Versions-Konfliktauflösung

Bedingung Aktion
Client-Version > Server-Version Update
Client-Version = Server-Version Skip (keine Änderung)
Client-Version < Server-Version Conflict
Conflicts ohne force=true 409-Response, keine Änderungen
Mit -Force (PS-Script) Retry mit ?force=true

PowerShell Scripts (ka-note/scripts/)

Script Beschreibung
download.ps1 work/ leeren, ZIP holen, entpacken, Lock-Info anzeigen
upload.ps1 ZIP mit .NET ZipArchive erstellen (Forward-Slash-Fix!), hochladen
unlock.ps1 Lock ohne Upload freigeben
show-bundle.ps1 Bundle-Inhalt (Lock-Token, Ablauf, Counts) anzeigen
get-token.ps1 Azure AD Bearer-Token holen/cachen
set-token.ps1 Token aus Clipboard/Argument speichern

Wichtig: download.ps1 löscht work/ beim Start — Token nie dort ablegen!

Windows-Pfad-Fix: upload.ps1 verwendet .NET ZipArchive statt Compress-Archive, da Compress-Archive Backslash-Pfade erzeugt, der Server aber Forward-Slashes erwartet.

Token-Workflow

# Token aus Browser kopieren, dann:
.\set-token.ps1          # liest Clipboard → speichert nach ~\.ka-note\token.txt
.\get-token.ps1          # prüft JWT-Ablauf, gibt Token zurück

Import-Helpers (import-helpers.ps1)

Dot-sourcen für eigene Import-Scripte:

. .\import-helpers.ps1
Upsert-Context -Id "..." -Name "..." -Type "meeting"
Add-Topic -ContextId "..." -Title "..."
Add-HistoryEntry -TopicId "..." -Date "2026-02-24" -Body "..."

Vorhandene Import-Scripte: import-jf-sysadmins.ps1, import-jf-landata.ps1

Relevante Dateien

  • ka-note/server/src/lib/ai-export-service.ts
  • ka-note/server/src/lib/ai-agent-readme.ts
  • ka-note/server/src/routes/ai-export.ts
  • ka-note/client/src/lib/stores/aiLock.ts
  • ka-note/scripts/download.ps1
  • ka-note/scripts/upload.ps1
  • ka-note/scripts/unlock.ps1

Gemeinsames ZIP-Format

Beide Systeme erzeugen strukturell identische ZIPs, unterscheiden sich nur im manifest.json:

  • Scheduled Backup: type: "backup"
  • AI Export: enthält lockToken + expiresAt

Soft-deleted Entities werden immer exportiert (mit gesetztem deletedAt). Hard-delete existiert nicht.