Stefan-Wunsch: ARIA-Aenderungen an Dateien sollen vom System (nicht
von ARIA selbst) automatisch versioniert werden. Im Datei-Manager:
Versionen auflisten, einzelne downloaden, oder als neue aktive Version
setzen (Restore = non-destructive neuer Commit).
Implementierung (alles im diagnostic-Container, da der eh schon
File-Handling kann):
1. Dockerfile: apk add git
2. server.js — Auto-Commit-Loop:
- Beim Start: /shared/uploads als git-Repo initialisieren (idempotent;
bestehendes .git wird uebernommen)
- setInterval(30s): git status --porcelain → wenn dirty, add+commit
mit "auto: <ISO-Timestamp>"-Message
- Re-Entrancy-Guard fuer langsame git-Ops
3. server.js — drei neue HTTP-Routen:
GET /api/files-versions?path=X
→ [{hash, ts, subject, isCurrent}] aus git log --follow
GET /api/files-version-content?path=X&hash=Y
→ Binary-Stream der Datei aus diesem Commit (Content-Disposition
attachment mit "name@<short-hash>.ext" als Default-Dateiname)
POST /api/files-version-restore body={path, hash}
→ non-destructive: schreibt alten Inhalt als NEUE Version, neuer
Commit "restore: <path> <- <short>". Aktive Version damit
weiterhin rollback-bar.
4. index.html — Datei-Manager:
- Pro Datei zusaetzlich 🕒-Button neben ⬇/🗑
- Klick zeigt Modal mit Version-Liste (timestamp, short-hash,
'AKTIV'-Marker fuer den jeweils letzten)
- Pro Version: ⬇ Download + ⟲ Restore (mit Confirm)
- Restore broadcasted file_version_restored damit Browser refreshen
Path-Safety: alle Pfade muessen relative-to-uploads sein, kein '..',
kein '/', kein '.git/'. Hash muss [0-9a-f]{7,40}.
.gitignore zunaechst keine — uploads/ ist eh nur User-/ARIA-Dateien,
kein Log-Noise erwartet. Falls Disk explodiert: spaeter ergaenzen.
Step-2 (App-Side via RVS-Messages) folgt im naechsten Commit, sobald
das hier in Diagnostic funktioniert.
Diagnostic + App bekommen Mehrfach-Auswahl im Datei-Manager. Mehr als eine
Datei ausgewaehlt → Download als ZIP. Genau eine ausgewaehlt → einzeln.
Bulk-Delete loescht alle markierten in einem Rutsch.
diagnostic/Dockerfile
zip via apk add — fuer das ZIP-Streaming im /api/files-download-zip.
diagnostic/server.js
POST /api/files-download-zip Body: {paths:[...]} → spawnt 'zip -j -q -',
Pipes stdout in Response. Whitelist auf
/shared/uploads/.
POST /api/files-delete-batch Body: {paths:[...]} → loescht alle, broadcastet
file_deleted pro Pfad an Browser + RVS.
diagnostic/index.html
filesSelected Set + Checkbox-UI pro Datei + "Alle markieren". Wenn 2+
ausgewaehlt: POST an /api/files-download-zip, Browser saugt das als
Blob runter. Bei 1: normaler Single-Download.
bridge/aria_bridge.py
file_delete_batch_request → ruft Diagnostic /api/files-delete-batch,
antwortet mit file_delete_batch_response.
file_zip_request {paths,reqId} → ruft Diagnostic /api/files-download-zip,
base64-kodiert, capped auf 30 MB,
sendet file_zip_response.
rvs/server.js
ALLOWED_TYPES: file_delete_batch_request/response, file_zip_request/response.
android/src/screens/SettingsScreen.tsx
fileManagerSelected Set + Checkbox-UI pro Datei + "Alle markieren"-Zeile
oben. Bulk-Bar oben mit count, "⬇ ZIP" / "⬇ Download" (je nach Anzahl),
und "🗑 Löschen". ZIP-Response landet base64 → RNFS in Downloads-Folder
(aria-files-<timestamp>.zip), Toast mit Pfad.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>