6.1 KiB
Feature: Backup
Ka-Note hat zwei unabhängige Backup-Systeme:
- Scheduled Backup — automatische serverseitige ZIP-Exporte
- 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.tska-note/server/src/routes/backup.tska-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.jsondes 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 (1–4), 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.tska-note/server/src/lib/ai-agent-readme.tska-note/server/src/routes/ai-export.tska-note/client/src/lib/stores/aiLock.tska-note/scripts/download.ps1ka-note/scripts/upload.ps1ka-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.