Vault-Synchronisation — Feature-Epic #76
Labels
No labels
herkunft/alpha-feedback
status
blockiert
status
zu-testen
typ
bug
typ
docs
typ
enhancement
typ
feature
typ
idea
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
iris/Iris#76
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Vault-Synchronisation über ein gemeinsames Forgejo-Repo. Plan:
obsidian-docs/plans/VAULT-SYNC.md(Iris-Vault-Ordner).Architektur
Sync-Logik auf den Servern (Mac-Server + Linux-Server), GUI auf allen Clients (Iris, IrisClient, IrisRemote). Byte-identisches Wire-Protokoll. Mechanisch, kein LLM.
Grundregeln
ours= lokales Vault).409 busy.merge --abort), Statusconflict, der Job läuft trotzdem. Kein Push solangeconflict.--force, nie Dateien überschreiben.Wire-Protokoll (neue Routen
/vault/sync/*, Bearer-Auth)GET status→{has_git, has_remote, sync_state, ahead, behind, conflict_count, last_sync_at, lfs_available, error?}POST pull/POST push→ manuellGET conflicts→ base/ours/theirs aus Commits (git show), nicht aus dem Working TreePOST resolve→ Wahl pro Pfad (ours|theirs|merged); Merge läuft, sobald alle Pfade eine Wahl habenPOST forge/login→ Anmeldung am Forgejo mit Benutzer + Passwort (Token wird einmalig erzeugt, nur im Speicher), antwortet mit der Repository-Liste;POST forge/create→ neues privates RepositoryPOST configure→ „Vault verbinden“: Body{remote_url, username, token}oder{remote_url, use_login: true}; Klon, Union (nie überschreiben, Kollisionen werden gemeldet), Veröffentlichen oder nur Zugangsdaten aktualisierenGET events(SSE) → live Statussync_state:not_configured | no_remote | synced | syncing | offline | pending | conflict | errorSync-Trigger (serverseitig)
git ls-remotealle 60 s (nur ausgehend, kein Webhook); bei geändertem Hash fetch + Merge, sobald der Vault sauber ist. Dieselbe Abfrage ist die Reachability-Probe.Zugangsdaten
Das Forgejo-Token liegt in einer 0600-Datei außerhalb des Vaults (Mac:
Application Support/Iris, Linux:/data), git bekommt es pro Aufruf perGIT_CONFIG_*(http.<Server>.extraHeader). Nicht in.git/config, nicht im Vault-Backup, kein Keychain-Zugriff. Nur http(s), keine Zugangsdaten in der URL.Stand (2026-10-20)
Gebaut und gemergt: Linux-Server und Mac-Server (Sync-Logik, Routen,
configure), GUI in Iris, IrisClient und IrisRemote (Lampe, Konflikt-Dialog, Sheet „Vault verbinden“), die Verzweigung des Vault-Schritts im Onboarding und die Wire-Doku. Details und Prüfstand: PlanVAULT-SYNC.md, Abschnitt „Stand der Umsetzung“. Nur lokal mit echtem git getestet; weder gegen echtes Forgejo über HTTP noch mit dem Notebook als zweitem Peer.Bestehende Bausteine, die sich ändern
/vault/git/reset-hard) wird mit Remote ein neuer Commit/vault/git/initdarf auf einem geklonten Vault nicht mehr laufen_attachments/wird LFS-getracktVersionier-Scope
Nutzerinhalt + Obsidian-Konfiguration (
.obsidian/*.json). Zustand pro Maschine bleibt draußen:.obsidian/workspace.json,.obsidian/plugins/,.claude/,.claudian/,.DS_Store._attachments/per LFS, Full-Clone.Notebook-Bootstrap
git clone(mit LFS) in ein leeres Verzeichnis, nicht rsync: Das Linux-Vault hat eigene Historie und ließe sich nicht auf das Studio-Repo pushen.Abnahmekriterien
conflict, Vault sauber, Job läuft, Dialog mit 3 Optionen und 3-Wege-Diff; „Meine Version" = lokales Vaultconflictkeine Commits mit Konfliktmarkern; Rollback bleibt nach dem nächsten Sync erhaltenworkspace.json/plugins/einer Maschine beeinflussen die andere nichtpytestgrünOffene Punkte
ALLOWED_HOST_LIST)Plan-Stand 2026-10-19
Der Plan
VAULT-SYNC.mdliegt jetzt im Iris-Vault (plans/) und wurde gegen Code und Vault-Repo geprüft und überarbeitet. Die Beschreibung oben ist entsprechend nachgezogen.Befund (im Code/Repo verifiziert)
.obsidian/ist nicht komplett ignoriert: sechs Konfig-Dateien sind getrackt, ignoriert sind nurworkspace.jsonundplugins/. Der Plan übernimmt jetzt den Ist-Stand./vault/git/init). Ein rsync-Bootstrap ließe sich nicht auf das Studio-Repo pushen → Klon statt Kopie.add -Aalle 30 s) würde in einem Rebase-Konflikt Konfliktmarker committen → ein Sperrmechanismus und ein Vault, das nie im Merge-Zustand bleibt.:2:/:3:vertauscht (ours = Server), der Dialog wäre falsch beschriftet → Merge.reset-hardwürde vom nächsten Merge rückgängig gemacht → Rollback als neuer Commit.git, aber kein git-lfs;_attachments/ist dort ignoriert.Entscheidungen
.obsidian/*.jsonbleibt synchron, Zustand pro Maschine nicht.git ls-remotealle 60 s statt Webhook (Webhook-Erreichbarkeit der Server von Forgejo aus ist ein Problem; ausgehend funktioniert unterwegs und hinter NAT). Kein Fetch, nur ein Hash-Vergleich.Neu im Wire-Protokoll:
sync_statesyncingunderror,409 busy,POST resolvepro Pfad.Offen: siehe Beschreibung (Konflikt-Dialog-Design, iOS-Routen, Editor-Überschreiben, Hook-Migration, optionaler Webhook).
Noch nichts gebaut. Nächster Schritt: Phase 1 auf dem Linux-Server.
PR #54 gemergt: feat(vault-sync): Sync-Logik und /vault/sync/*-Routen auf dem Linux-Server (iris/Iris#76)
iris/iris-linux-server#54
Commits:
Linux-Server: Sync-Logik und Routen (PR iris/iris-linux-server#54)
Gebaut (Phase 1, Schritt 1):
vault_git_sync.pyundvault_sync_routes.pymit allen sechs Routen aus dem Plan (status,pull,push,conflicts,resolve,events); git-lfs im Image.conflict, der Job läuft weiter. Kein Push, solange ein Konflikt offen ist.SYNC_LOCK→409 busy, Merge unterHOOK_LOCK).ls-remotealle 60 s (Reconnect schiebt dabei auch ausstehende lokale Commits hinaus)./vault/git/reset-hard) ist mit Remote ein neuer Commit;/vault/git/initüberschreibt bei vorhandenem Remote nichts und nutzt LFS, wenn git-lfs da ist.Geprüft: 24 lokale Tests (
test_vault_git_sync.py: Fast-Forward, Merge ohne Konflikt, Non-FF-Push, Konflikt mit sauberem Vault, ours/theirs/merged, alle Pfade nötig, veralteter Konflikt, Binär, offline, Reconnect, Erkennung, Rollback, busy, LFS-Roundtrip, Wire-Format) laufen mit echtem git gegen ein Bare-Repo. Deploy aufalf@iris-server(git 2.47.3, git-lfs 3.6.1 im Image),test_vault_sync_routes.py,test_vault_git.py,test_job_hooks.pygegen den laufenden Server grün (14).Grenzen / offen:
git config.vault_sync_routes.pystatt invault_git_routes.py(Zirkelimport).VaultSyncController.swift) und Wire-Parität.PR #96 gemergt: feat(vault-sync): Sync-Logik und /vault/sync/*-Routen im Mac-Server (#76)
#96
Commits:
Mac-Server: Sync-Logik und Routen (PR #96)
Gebaut (Phase 1, Schritt 2):
VaultSyncController.swift(Actor, Port vonvault_git_sync.py) und die sechs Routen/vault/sync/{status,pull,push,conflicts,resolve,events}inIrisRemoteServer.swift, Wire-Format wie auf dem Linux-Server (Fehlerantworten wie bei den übrigen Mac-Routen als{"error": …}mit HTTP-Status).merge --abort(Vault bleibt sauber), eine Sperre (zweiter API-Aufruf →409 busy), Commit/Merge überJobHookManager.runExclusive, Konfliktzustand in.git/iris-sync-state.jsonim selben Format wie auf Linux.credential.helper=leer.createJob/sendFollowUpstarten den Prozess jetzt erst nachprepareVaultForJobStart: Änderungen sichern, dann Fetch + Merge; offline sofort; nicht, wenn ein anderer Job läuft), Jobende (executeHooksstößt nach dem Hook den Push an),ls-remote-Erkennung alle 60 s (IRIS_VAULT_SYNC_INTERVAL)./vault/git/reset-hard) ist mit Remote ein neuer Commit;VaultGitSetup.initVaultGitRepotut bei vorhandenem Remote nichts.Geprüft: Beide Schemes (Iris und IrisClient) bauen über Xcode fehlerfrei. Nicht zur Laufzeit geprüft: Iris.app wurde nicht neu gestartet, die Routen sind gegen den Mac-Server noch nie aufgerufen worden. Die Swift-Logik ist ein Port der Python-Logik, die mit 24 lokalen Tests abgedeckt ist, aber selbst ungetestet.
Grenzen / offen:
ahead0), sollte aber bei der Migration entfallen.PR #97 gemergt: test(vault-sync): git-Kern in VaultSyncCore.swift ausgelagert, Tests gegen echte Temp-Repos (#76)
#97
Commits:
Mac-Server: Tests für den git-Kern (PR #97)
Der git-Kern liegt jetzt in
Iris/VaultSyncCore.swift(git-Aufrufe, Konfliktzustand, Merge, Auflösung; ohne Abhängigkeit zu Iris-Typen).VaultSyncController.swiftenthält nur noch den Actor. Dazuscripts/test-vault-sync-core.sh: übersetzt den Kern mit swiftc und prüft ihn gegen echte Temp-Repos (Bare-Repo als „Forgejo“, zwei Arbeitskopien), ohne Xcode-Build und ohne Iris-Neustart.Geprüft (56 Prüfungen, 0 Fehler): Fast-Forward, Merge ohne Konflikt, lokal voraus, ungesicherte Änderungen (kein Merge), Konflikt (Vault bleibt sauber, kein
MERGE_HEAD, Konfliktpfad und die drei Fassungen aus Commits), Auflösungours/theirs/mergedinklusive Push zum anderen Peer, veralteter Konflikt (stale), Binär-Erkennung,ls-remote-Exitcodes und Fehlerklassifikation. Beide Schemes bauen weiterhin.Noch nicht geprüft: der Actor selbst (Sperre, Trigger, Jobstart-Verzögerung) und die Routen gegen den laufenden Mac-Server. Die Routen dürfen nicht mit
pull/pushgegen das echte Studio-Vault getestet werden (echtes Forgejo, 3 Commits voraus, ungesicherte Änderungen); möglich sind nur die lesenden Aufrufestatusundconflicts.PR #98 gemergt: feat(vault-sync): Lampe, Synchronisieren-Button und Konflikt-Dialog im Vault-Browser (#76)
#98
Commits:
macOS-GUI: Lampe, Synchronisieren, Konflikt-Dialog (PR #98)
Gebaut (Phase 2, Schritte 4 und 5):
VaultSyncModel.swift(Modell, Wire-Parser,RemoteVaultSyncService, View-Modell) undVaultSyncViews.swift(VaultSyncStatusView,VaultConflictResolverView). Eingebaut in die Toolbar desRemoteVaultBrowserView. Das ist auch der Vault-Browser von Iris.app (gegen den eingebetteten Mac-Server), also bekommen Iris und IrisClient dieselbe Oberfläche; es gibt keinen zweiten Pfad.sync_state, Text ohne Jargon („Synchronisiert vor 2 Min“, „Änderungen warten“, „Offline“, „Konflikt – bitte entscheiden“), unsichtbar ohne Forgejo-Remote oder gegen einen älteren Server ohne Sync-Routen. Status per Poll alle 10 s, solange die Ansicht sichtbar ist.errorunddetail) werden gleich behandelt.Geprüft: Beide Schemes (Iris, IrisClient) bauen. Nicht gesehen und nicht bedient: die Oberfläche ist noch nie gestartet worden.
Offen: IrisRemote (iOS, Schritt 6), Onboarding-Schritt „Vault-Synchronisation“ und die Zugangsdaten-Einrichtung (Token statt Passwort in der Remote-URL; dafür fehlt noch eine Server-Route zum Setzen), SSE statt Poll, Menüeintrag im Client-Fenster (bewusst weggelassen).
PR #99 gemergt: fix(vault-sync): Lampe blieb unsichtbar, weil .task an einer leeren View nie anlief (#76)
#99
Commits:
Fix: Lampe blieb unsichtbar (PR iris/Iris, nach #98)
Befund: Im Vault-Browser war nach #98 keine Lampe zu sehen, obwohl der Server
GET /vault/sync/statuskorrekt beantwortet (has_git,has_remote,sync_stategeprüft). Ursache:VaultSyncStatusViewrendert, solange der Status unbekannt ist, nichts. Das.task, das den Status holt, hing an dieser leeren View und lief deshalb nie an. Der Status wurde nie geladen, die Lampe blieb für immer unsichtbar.Fix: Die View hat jetzt immer einen festen Anker (
HStackmit unsichtbarer 0×0-Fläche), an dem.task, Sheet und Alert hängen.Geprüft: Beide Schemes bauen. Die Lampe selbst ist erst nach einem Neustart von Iris sichtbar — Prüfung steht beim Nutzer aus.
PR #100 gemergt: fix(vault-sync): Button-Text 'Synchronisieren' wird in der Toolbar nicht mehr gekürzt (#76)
#100
Commits:
PR #55 gemergt: fix(vault-sync): Gitlinks mit Änderungen halten den Vault nicht mehr dauerhaft auf „ungesichert“ (iris/Iris#76)
iris/iris-linux-server#55
Commits:
PR #101 gemergt: fix(vault-sync): Gitlinks mit Änderungen halten den Vault nicht mehr dauerhaft auf „ungesichert“ (#76)
#101
Commits:
Fix: Gitlinks hielten den Vault dauerhaft auf „Änderungen warten“ (Mac und Linux, nach #99)
Befund (am echten Studio-Vault verifiziert): Die Lampe wurde nicht grün.
git status --porcelainmeldet die drei Waisen-Gitlinks (04 Ressourcen/Bernini,…/ComfyUI/Bernini,…/LTX Director CS) dauerhaft als geändert (M), weil in den verschachtelten Repos Dateien liegen. Mit--ignore-submodules=allist der Status leer. Folge war schlimmer als eine falsche Farbe:isDirtywar damit immer wahr, also hat die Änderungserkennung nie gemergt (sie holt nur bei sauberem Vault) undmergeRemotehätte immerdirtygeliefert. Auf dem Studio wären Änderungen des Notebooks nie angekommen. Das ist die Kehrseite der Entscheidung „Waisen-Gitlinks in Durchgang 1 ignorieren“ aus dem Plan.Fix:
isDirtyignoriert Gitlinks auf beiden Servern (vault_git_sync.py::_is_dirty,VaultSyncGit.isDirty). Der Statuspendingkommt jetzt nur noch von echten ungesicherten Änderungen oderahead/behind.Geprüft: Neuer Test auf beiden Seiten (Linux: 25 Fälle, Mac: 60 Prüfungen): Vault mit Gitlink, dessen verschachteltes Repo geändert ist, wird nicht als ungesichert gemeldet und mergt trotzdem. Der Linux-Test schlägt ohne den Fix fehl (gegengeprüft). Beide Mac-Schemes bauen.
Offen: Die Gitlinks bleiben im Repo (ihr Inhalt kommt auf dem Notebook nicht an, siehe Plan §8). Iris neu starten und den Linux-Dev-Server neu deployen, damit der Fix läuft.
PR #20 gemergt: feat(vault-sync): Lampe, Synchronisieren-Button und Konflikt-Dialog im Vault-Browser (iris/Iris#76)
iris/2ndbrain-ios#20
Commits:
iOS-GUI und Linux-Deploy (PR iris/2ndbrain-ios#20)
Gebaut (Phase 2, Schritt 6): In IrisRemote
VaultSyncModel.swift(Modell, Wire-Parser,VaultSyncServiceüberServerConnection, View-Modell) undVaultSyncViews.swift(Lampe mit „Synchronisieren“, Konflikt-Dialog), eingebaut oben inVaultBrowserSheet. SwiftUI-Port der macOS-Ansichten; die Texte sind dieselben, ohne Jargon. Auf dem iPhone statt zweier Spalten ein Umschalter „Meine Version“ / „Version vom Server“ (markierte Zeilen), darunter drei Buttons, „Zusammenführen“ als Sheet mit Texteditor; Anhänge nur die ersten zwei. Pull/Push/Resolve laufen über die Sitzung mit langem Zeitlimit (agentSession). Gleiche Falle wie auf dem Mac vermieden:.taskhängt an einem immer vorhandenen Anker, sonst bliebe die Lampe unsichtbar.Geprüft: IrisRemote baut für iOS (
xcodebuild, generisches Gerät, ohne Signatur). Nicht auf einem Gerät oder Simulator gestartet, die Oberfläche ist nicht gesehen.Linux-Dev-Server: Der Fix für Gitlinks (nach #99) ist deployt und im Container verifiziert (
ignore-submodules=allinvault_git_sync.py).Offen: Onboarding-Schritt „Vault-Synchronisation“ in allen Clients und die Zugangsdaten-Einrichtung (Server-Route zum Setzen von Remote und Token auf beiden Servern), Notebook-Bootstrap, SSE statt Poll, ein echter Konflikt-Durchlauf (Sandbox), Paritätsprüfung Mac gegen Linux mit denselben Szenarien.
PR #56 gemergt: feat(vault-sync): POST /vault/sync/configure verbindet das Vault mit Forgejo, Token außerhalb des Vaults (iris/Iris#76)
iris/iris-linux-server#56
Commits:
PR #102 gemergt: feat(vault-sync): POST /vault/sync/configure im Mac-Server, Token außerhalb des Vaults (#76)
#102
Commits:
Server: Vault mit Forgejo verbinden,
POST /vault/sync/configure(Mac und Linux)Entscheidungen (mit dem Nutzer):
Application Support/Iris/vault-sync-credentials.json, Linux:/data/vault-sync-credentials.json). Git bekommt es pro Aufruf per Umgebungsvariable (http.<Server>.extraHeader, nur für diesen Server), also nicht in.git/config, nicht inps, nicht im Vault und nicht im Vault-Backup. Kein Keychain-Zugriff.Wire:
POST /vault/sync/configure, Body{remote_url, username, token}→{ok: true, mode: cloned | connected | published | credentials_updated}oder{ok: false, error: auth | unreachable | unrelated_history | collisions | failed, paths?, message?}; 400 bei ungültiger Eingabe (nur http(s), keine Zugangsdaten in der URL), 409busy.Ablauf (beide Server gleich): erst
ls-remotemit den Zugangsdaten, ohne etwas zu ändern (auth/unreachablebrechen hier ab); dann Zugangsdaten speichern und verbinden:git lfs install);init,fetch,checkout -B … --track: lokale Dateien bleiben (Union, der Wächter committet sie später), gleichnamige Dateien →collisionsmit Pfadliste, nichts bleibt halb eingerichtet;published);connected), sonstunrelated_history; mit Remote → nurcredentials_updated.Scheitert ein Schritt, werden Vault und Zugangsdaten zurückgesetzt.
Geprüft: Linux 41 Tests (16 neu), Mac 86 Prüfungen (26 neu), alle mit echtem git gegen lokale Repos (
file://nur im Test erlaubt). Beide Mac-Schemes bauen. Nicht gegen ein echtes Forgejo und nicht über HTTP getestet; der Linux-Dev-Server ist noch nicht neu deployt.Offen: Einrichten-Sheet („Vault verbinden“) mit „Verbindung prüfen“ in den Clients, die Lampe zeigt dann „Synchronisation einrichten …“ statt zu verschwinden; Verzweigung des Vault-Schritts im Onboarding (Mac-Onboarding, Client-Onboarding, iOS); Wire-Doku (
Entwicklerdokumentation/02-Wire-Protokoll.mdkennt/vault/sync/*noch nicht).PR #103 gemergt: feat(vault-sync): Sheet "Vault verbinden" und Lampe "Synchronisation einrichten …" (#76)
#103
Commits:
PR #21 gemergt: feat(vault-sync): Sheet "Vault verbinden" und Eintrag "Synchronisation einrichten …" (iris/Iris#76)
iris/2ndbrain-ios#21
Commits:
Sheet „Vault verbinden“ (macOS und iOS)
Gebaut: In den Clients (Iris, IrisClient, IrisRemote) ein Sheet „Vault verbinden“ (Adresse des Repositorys, Benutzer, Token, Button „Verbinden“) gegen
POST /vault/sync/configure. Die Lampe zeigt bei einem Vault ohne Remote „Synchronisation einrichten …“ statt zu verschwinden (gegen ältere Server ohne Sync-Routen bleibt sie unsichtbar). Ergebnis in Klartext: Klon, hochgeladen, verbunden, Zugangsdaten aktualisiert; Fehlerauth,unreachable,unrelated_history,collisions(mit der Pfadliste),failed. Beim Verbinden läuft ein Fortschrittskreis, das Token wird nach Erfolg aus dem Feld gelöscht. Pull/Push/Verbinden laufen mit langem Zeitlimit (Klon großer Vaults).Geprüft: Beide Mac-Schemes bauen, IrisRemote baut für iOS. Die Oberfläche wurde weder auf dem Mac noch auf dem iPhone bedient, und
configurelief noch nie gegen ein echtes Forgejo.Bewusst weggelassen: der Button „Verbindung prüfen“ (die Route prüft vor dem Verbinden ohnehin und ändert bei einem Fehler nichts).
Offen: Verzweigung des Vault-Schritts im Onboarding (Backup / Default-Vault / KI / Vault verbinden) in Mac-Onboarding, Client-Onboarding und iOS-Onboarding; Wire-Doku; Linux-Dev-Server mit
configuredeployen und einmal echt durchspielen.PR #104 gemergt: feat(vault-sync): Vault-Schritt im Onboarding verzweigt: Backup, Default-Vault, KI, Vault verbinden (#76)
#104
Commits:
PR #22 gemergt: feat(vault-sync): Vault-Schritt im iOS-Onboarding mit "Vault verbinden" (iris/Iris#76)
iris/2ndbrain-ios#22
Commits:
Onboarding-Verzweigung und Wire-Doku
Gebaut: Der Vault-Schritt verzweigt jetzt in Aus Backup zurücklesen / Default-Vault / Per KI einrichten / Vault verbinden:
ClientOnboardingStepVaultView, Iris und IrisClient): vier Wege bei leerem Vault; „Backup“ öffnetRemoteBackupRestoreView, „Vault verbinden“ das Sheet; ein bereits gefüllter Vault bietet „Vault mit Forgejo verbinden …“. Nach dem Schließen wird der Vault neu geprüft.OnboardingStepVaultSetupView, englische Texte wie im Rest des Schritts): „Restore from backup“ (vorhandene Backup-Ansicht, beendet den Assistenten) und „Connect vault (Forgejo)“. Der Sync-Controller arbeitet auf dem Pfad ausIrisConfig, den der Schritt sonst erst beim Weitergehen einträgt: deshalb legt „Connect vault“ den Ordner an und registriert den Pfad vorab. Dafür gibt esLocalVaultSyncService(Controller im selben Prozess, kein HTTP).RemoteOnboardingStepVaultView): „Vault verbinden“, „Default-Vault“, „Per KI einrichten“. „Aus Backup zurücklesen“ fehlt: IrisRemote hat keine Backup-Ansicht.Wire-Doku:
Entwicklerdokumentation/02-Wire-Protokoll.mdhat den Abschnitt „Vault-Synchronisation“ (alle Routen, Zustände, Regeln,configure-Modi, Zugangsdaten, Fehlerformat).Geprüft: Beide Mac-Schemes und IrisRemote bauen. Keine der Oberflächen wurde bedient.
Offen: echter Durchlauf (Sandbox, Konflikte, Offline, LFS, Notebook als zweiter Peer), Parität Mac gegen Linux, Studio-Passwort durch Token ersetzen, iOS ohne Backup-Weg, Editor-Überschreiben prüfen, SSE in den Clients.
PR #105 gemergt: feat(vault-sync): Weiche im Vault-Schritt des Mac-Onboardings: erst wählen, dann das Formular (#76)
#105
Commits:
Weiche im Mac-Onboarding (Nutzerfund im VM-Test)
Befund: Direkt nach dem Embedding-Provider kam das Formular des Vault-Schritts (Name, Sprache, Ort, Obsidian) mit dem blauen Knopf „Mit KI einrichten“; die vier Wege standen nur als kleine unterstrichene Links darunter. Eine Weiche im Sinne der Entscheidung (erst wählen, dann das passende Formular) war das nicht. Mein Fehler: ich hatte die Wege als Zusatzlinks eingebaut statt den Schritt zu verzweigen.
Fix: Ist am gewählten Pfad noch kein Vault, zeigt der Schritt zuerst die Weiche „Wie soll dein Vault entstehen?“ mit vier Karten: Aus Backup zurücklesen (öffnet sofort die Backup-Ansicht), Vault verbinden, Default-Vault, Per KI einrichten. Erst nach der Wahl erscheint das Formular, und nur mit den Feldern, die der Weg braucht (Vault verbinden: nur der Ort; Default und KI: Name, Sprache, Ort, Obsidian); dazu der passende Knopf und „Andere Wahl treffen“. Ein vorhandenes Vault geht wie bisher durch den Schritt und bietet „Mit Forgejo verbinden …“. Texte der neuen Elemente sind deutsch.
Client-Onboarding (IrisClient) und iOS: dort beginnt der Vault-Schritt bei leerem Vault ohnehin mit der Auswahl (keine Eingabefelder davor); die Weiche besteht dort aus den Wegen als Schaltflächen und wurde nicht auf Karten umgebaut.
Geprüft: beide Mac-Schemes bauen. Nicht bedient.
PR #57 gemergt: fix(vault-sync): Repository nicht gefunden (z. B. nur Server-Adresse) ist ein eigener Fehler statt roher git-Ausgabe (iris/Iris#76)
iris/iris-linux-server#57
Commits:
PR #106 gemergt: fix(vault-sync): Repository nicht gefunden als eigene Meldung, Adresse ohne Repository-Pfad wird vorab abgewiesen (#76)
#106
Commits:
PR #23 gemergt: fix(vault-sync): Repository nicht gefunden als eigene Meldung, Adresse ohne Repository-Pfad wird vorab abgewiesen (iris/Iris#76)
iris/2ndbrain-ios#23
Commits:
PR #58 gemergt: feat(vault-sync): Forgejo-Anmeldung mit Passwort, Repository-Liste und Neu anlegen (iris/Iris#76)
iris/iris-linux-server#58
Commits:
PR #107 gemergt: feat(vault-sync): Vault verbinden per Forgejo-Anmeldung: Repository aus Liste wählen oder neu anlegen (#76)
#107
Commits:
PR #24 gemergt: feat(vault-sync): Vault verbinden per Forgejo-Anmeldung: Repository aus Liste wählen oder neu anlegen (iris/Iris#76)
iris/2ndbrain-ios#24
Commits:
„Vault verbinden“ für Laien: Anmeldung statt Repository-Namen
Anlass (VM-Test): Der Nutzer trug nur die Server-Adresse ein; git meldete „repository … not found“, im Sheet stand rohe git-Ausgabe. Dahinter steckt das eigentliche Problem: Ein nicht technischer Anwender kennt den Namen seines Repositorys nicht.
Behoben:
benutzer/repositorywird vorab abgewiesen. Gegen den echten Forgejo geprüft, dass seine Fehlertexte richtig klassifiziert werden.iris-vault). „Erweitert“ nimmt Adresse und Token von Hand (Konten ohne Passwort).POST /vault/sync/forge/loginerzeugt mit dem Passwort einmalig ein Token (write:repository,read:user) und listet die Repositories; das Passwort wird nie gespeichert, das Token bleibt im Speicher des Servers (30 min) und verlässt ihn nie.POST /vault/sync/forge/createlegt ein privates, leeres Repository an.configurenimmtuse_login: true, schreibt das Token erst nach erfolgreichem Verbinden in die Zugangsdaten-Datei und verwirft es; die Adresse muss auf denselben Server zeigen.Geprüft: Linux 52 Tests, Mac 116 Prüfungen, jeweils mit einem Forgejo als Attrappe (Anmelden, falsches Passwort, Zwei-Faktor, kein Forgejo, nicht erreichbar, Repository anlegen, ungültige Namen, Name vergeben, Ablauf der Anmeldung, falscher Server). Linux-Dev-Server deployt und mit falschen Eingaben angesprochen. Beide Mac-Schemes und IrisRemote bauen.
Nicht geprüft: Token-Erzeugung mit Passwort, Zwei-Faktor-Header (
X-GITEA-OTP) und die genauen Rechte gegen einen echten Forgejo; die Oberfläche wurde nicht bedient. Ein Forgejo mit selbstsigniertem Zertifikat wird abgelehnt.PR #59 gemergt: fix(vault-sync): Vault mit LFS ohne git-lfs wird nicht mehr still als Zeigerdateien geklont (iris/Iris#76)
iris/iris-linux-server#59
Commits:
PR #108 gemergt: fix(vault-sync): Vault mit LFS ohne git-lfs wird nicht mehr still als Zeigerdateien geklont; git-lfs wird eingerichtet (#76)
#108
Commits:
PR #25 gemergt: fix(vault-sync): Meldung, wenn git-lfs auf dem Server fehlt (iris/Iris#76)
iris/2ndbrain-ios#25
Commits:
PR #109 gemergt: feat(onboarding): git-lfs wird mit den Abhängigkeiten installiert und ist Pflicht, damit Vault-Anhänge aus der Schachtel funktionieren (#76)
#109
Commits:
Vault ohne git-lfs wurde still als Zeigerdateien geklont — behoben, git-lfs jetzt im Onboarding
Befund (VM
mac-vm, Nutzerhinweis „ging verdächtig schnell“, später „die ganzen Anhänge fehlen“):duzeigt 550 MB statt ~58 GB,git lfsist nicht installiert (Homebrew ja, git-lfs nein), alle 12 493 Dateien in_attachments/sind nur Zeigerdateien,git clonelief ohne Fehler durch. Zusätzlich wären neue Anhänge ohne git-lfs als gewöhnliche Dateien im Verlauf gelandet.Behoben:
configure(beide Server) klont ohne Checkout, prüft die.gitattributesdes Remotes und bricht bei fehlendem git-lfs mitlfs_missingab; nichts bleibt zurück, es werden keine Zugangsdaten gespeichert. Der Mac versucht davor, git-lfs einzurichten.statusmeldetsync_state: errormit Klartext, wenn git-lfs bei einem LFS-Vault fehlt.brew install git-lfs, danachgit lfs install --skip-repo, sichtbar unter „System Requirements“, Teil von „Alle installieren“).Geprüft: Linux 57 Tests, Mac 123 Prüfungen (Klon und Union ohne git-lfs abgelehnt, kein halber Klon, ohne LFS-Regel kein git-lfs nötig, Installer-Hook), beide Mac-Schemes und IrisRemote bauen. Nicht geprüft: die Brew-Installation in einer frischen VM durchgespielt. Der Linux-Dev-Server (
iris-server) war beim letzten Deploy nicht erreichbar (SSH-Zeitüberschreitung, kein Ping), die LFS-Änderung ist dort noch nicht deployt.Offen: Die VM ist weiter ein Zeigerdatei-Klon (Reparatur: git-lfs installieren,
git lfs install --local && git lfs pull, oder Ordner löschen und neu verbinden); iOS hat keinen Installationsweg (Linux-Server hat git-lfs im Image).PR #60 gemergt: feat(vault-sync): Fortschrittsanzeige für Klon, Anhänge, Hochladen: GET /vault/sync/progress (iris/Iris#76)
iris/iris-linux-server#60
Commits:
PR #110 gemergt: feat(vault-sync): Fortschrittsanzeige beim Verbinden und Synchronisieren: Balken, Menge, Tempo, Restzeit (#76)
#110
Commits:
PR #26 gemergt: feat(vault-sync): Fortschrittsanzeige beim Verbinden und Synchronisieren (iris/Iris#76)
iris/2ndbrain-ios#26
Commits:
Fortschrittsanzeige für große Übertragungen
Anlass (Nutzer, beim Verbinden eines ~60-GB-Vaults): Stundenlang bewegt sich auf dem Bildschirm nichts; das wirkt wie ein Absturz.
Gebaut (Linux- und Mac-Server gleich, Mac/IrisClient/iOS):
GET /vault/sync/progress→{active: false}oder{active, phase, percent, files_done, files_total, bytes_done, bytes_total, speed, eta_seconds}.--progress,GIT_PROGRESS_DELAY=0) und von git-lfs (GIT_LFS_PROGRESS, Bytes je Datei, aufsummiert). Die Gesamtgröße der Anhänge kommt exakt aus den Zeigerdateien (git lfs ls-files --json), der Prozentwert beim Laden der Anhänge also nach Bytes; Tempo und Restzeit aus den letzten 15 Sekunden (Restzeit nur geschätzt).git lfs fetch), damit der Fortschritt sichtbar ist und der Merge nicht Stunden still steht.git lfs fetch --progressgibt es nicht und hätte jeden Pull in ein LFS-Vault scheitern lassen. Regressionstest (rot ohne den Fix).Geprüft: Linux 63 Tests (echtes git/git-lfs: Parser, Aufsummieren, großer LFS-Klon mit exakter Gesamtgröße, Route, Pull mit neuen Anhängen), Swift 143 Prüfungen (u. a. echter LFS-Klon mit 20 MB Anhängen), beide Mac-Schemes und IrisRemote bauen, Linux-Dev-Server deployt (
{"active": false}).Nicht geprüft: die Anzeige bei einem echten 58-GB-Transfer und die Oberfläche selbst (nicht bedient); Tempo und Restzeit sind bei kurzen Übertragungen ungenau. Wartezeit bis zum ersten Prozentwert: git meldet den Fortschritt der Anhänge erst, sobald die ersten Dateien durch sind.
PR #61 gemergt: fix(vault-sync): Fehlende Anhänge auf dem Server brechen das Verbinden nicht mehr ab, unterbrochener Download setzt fort, Wächter lässt unfertigen Klon in Ruhe (iris/Iris#76)
iris/iris-linux-server#61
Commits:
PR #111 gemergt: fix(vault-sync): Fehlende Anhänge auf dem Server brechen das Verbinden nicht ab, unterbrochener Download setzt fort, Wächter lässt unfertigen Klon in Ruhe (#76)
#111
Commits:
PR #27 gemergt: fix(vault-sync): Meldungen für fehlende Anhänge und unterbrochenen Download (iris/Iris#76)
iris/2ndbrain-ios#27
Commits:
Fehlender Anhang auf dem Server und unterbrochener Download
Befund (VM, nach Stunden): „Not Found … smudge filter lfs failed“ für
04 Ressourcen/Aseprite/_attachments/50d98e8d_video.mp4. Das Objekt (37 MB) ist auf dem Studio vorhanden (git lfs fsckok), fehlt aber im LFS-Speicher von Forgejo (404), es wurde dort nie hochgeladen. Der Checkout brach ab, und der Fehlerzweig löschte den ganzen Klon samt allen geladenen Anhängen.Behoben (Linux- und Mac-Server gleich):
git lfs fetch, mit Fortschritt); der Checkout kommt danach aus dem lokalen Speicher.filter.lfs.required=false: Fehlt ein Anhang (404), bricht nichts ab. Seine Zeigerdatei bleibt im Vault und wird zurückgeschrieben (der Filter schreibt sonst eine leere Datei; der Wächter würde sie committen und beim anderen Rechner an die Stelle des Anhangs setzen). Die Antwort vonconfigurezählt sie inmissing_attachments..git/iris-setup-incomplete: Klon und geladene Anhänge bleiben bei einem Abbruch (Netz, Zugangsdaten) stehen,configureantwortetresumable: true, ein erneutes „Verbinden“ setzt fort (mode: resumed). Solange der Klon unfertig ist, behandeln Wächter, Erkennung und Status das Vault als nicht eingerichtet; sonst committetegit add -A„alles gelöscht“.Geprüft: Linux 66 Tests, Swift 156 Prüfungen (echtes git/git-lfs; fehlendes Objekt per
GIT_LFS_SKIP_PUSH, Netzabbruch und Fortsetzen, Marker, saubere Arbeitskopie nach dem Zurückschreiben der Zeiger), beide Mac-Schemes und IrisRemote bauen, Linux-Dev-Server deployt. Nicht geprüft: ein echter Transfer von ~58 GB mit Unterbrechung.Offen / Ursache: Auf dem Server fehlen weiter Objekte (mindestens
50d98e8d_video.mp4). Auf dem Studio liefertgit lfs push --all originsie nach (ändert den echten Forgejo, nicht ausgeführt, wartet auf das Okay des Nutzers).Entscheidung: eigener Forgejo auf jeder Iris-Installation (Standard)
Frage (Nutzer): Wo kommt der Forgejo-Server bei einer Neuinstallation von Null her (Henne-Ei)? Linux: Container im Iris-Image; Mac: ohne Docker?
Entscheidung des Nutzers: Jede Iris-Installation bringt per Standard einen eigenen, kleinen Forgejo mit. Er stört nicht (eine Datei, SQLite) und wird später für das Plugin iris-dev gebraucht (Nutzer entwickeln selbst an Iris; dafür braucht jeder einen Test-Forgejo auf der eigenen Maschine).
Geprüft (nur Fakten, nichts gebaut): Forgejo hat keine offiziellen macOS-Binaries (nur Linux amd64/arm64/arm), Homebrew hat eine Formel (16.0.6, Release 17.0.0, der Dev-Server läuft mit 15.0.9). Homebrew ist bei Iris ohnehin Pflicht, auf dem Mac geht es also ohne Docker per
brew install forgejo+ Hintergrunddienst; auf Linux als weiterer Compose-Dienst.Plan: Abschnitt §7a in
VAULT-SYNC.md(Entwurf, Teilschritte, offene Entscheidungen: Port ≠ 3000, nur lokales Netz, Token-Pflicht, Backup der Forgejo-Daten, Mac-Dienst perbrew servicesoder von Iris gestartet, Updates, Erreichbarkeit unterwegs). Iris richtet Administrator, Repositoryiris-vaultund Token selbst ein; weitere Rechner verbinden sich mit einem Verbindungscode statt Passwort. Der Weg zu einem fremden Forgejo bleibt daneben.Der Entwurf „Eigener Forgejo auf jeder Iris-Installation“ (Plan §7a) ist nach einer Grill-me-Runde ein eigenes Feature: iris/Iris#112. Dort stehen die Spezifikation und die Meilensteine M1 bis M5. Dieses Issue (#76) bleibt der Vault-Sync; der interne Forgejo löst dort das Henne-Ei-Problem und den Verbindungsweg „Dieser Rechner“.
Linux-Server-Teil (iris/iris-linux-server#105, gemergt)
GET /vault/sync/statusliefert zusätzlichremote(server[:port]/benutzer/repository, ohne Schema, Zugangsdaten und.git), nur mit Remote. Abwärtskompatibel: Clients behandeln das Feld als optional.tests/test_vault_git_sync.pykomplett (68 grün, lokal in einer Wegwerf-venv), darin neutest_status_remote_for_displayundtest_display_remote(Zugangsdaten werden entfernt, Port bleibt).PR #211 gemergt: feat(vault-sync): Klick auf die Statuslampe zeigt Erklärung und Git-Server (#76)
#211
Commits:
Stand: Klick auf die Statuslampe öffnet ein Info-Fenster
server/benutzer/repository), den letzten Abgleich und einen Hinweis auf Einstellungen → Git-Server …; „Verbindung ändern …“ öffnet „Vault verbinden“. Wire:GET /vault/sync/statushat das optionale Feldremote(Mac-Server, Linux-Server in eigenem PR, Wire-Doku im Wurzel-Repo). Handbuchkapitel „Vault-Synchronisation“ um den Klick ergänzt.scripts/test-vault-sync-core.sh(165 Prüfungen, 0 Fehler, darin neu die Adressanzeige ohne Zugangsdaten); Xcode-Build von Iris erfolgreich.remotesteht „Adresse nicht verfügbar“.PR #52 gemergt: feat(vault-sync): Klick auf die Lampe zeigt Erklärung und Git-Server (iris/Iris#76)
iris/2ndbrain-ios#52
Commits:
Stand (IrisRemote): Klick auf die Lampe zeigt Erklärung und Verbindung
remoteaus/vault/sync/status), letztem Abgleich und Hinweis zur Konfiguration; „Verbindung ändern …“ öffnet „Vault verbinden“. Gleiche Texte wie am Mac.xcodebuildfürgeneric/platform=iOSohne Signierung: BUILD SUCCEEDED.PR #125 gemergt: docs(wire): Vault-Sync-Status um remote erweitert (iris/Iris#76)
alf/2ndbrain#125
Commits:
PR #111 gemergt: feat(forgejo): Repository beim Bereitstellen wählen, kein vorbereitetes iris-vault (iris/Iris#76)
iris/iris-linux-server#111
Commits:
Stand (Linux-Server): Repository beim Bereitstellen wählen, kein vorbereitetes
iris-vaultensure_setuplegt nur noch den Administrator an, kein Repository mehr. Neu:GET /forgejo/repositories(Liste des eigenen Git-Servers, gleiche Felder wie die Anmeldeliste).POST /forgejo/publish-vaultnimmt{repository?}(Standardiris-vault, fehlendes wird privat angelegt;400 invalid_repository_namebei unzulässigem Namen). So lassen sich mehrere Vaults auf einem Git-Server ablegen.test_forgejo_service.py(angepasst, neue Tests für Liste, gewählten Namen, ungültige Namen) undtest_forgejo_sharing.pygrün (35). Live auf iris-server:GET /forgejo/repositoriesliefertiris-vault, ein ungültiger Name wird mit 400 abgelehnt.PR #214 gemergt: feat(vault-sync): Kein Sync als Standard, Repository beim Bereitstellen wählen (#76)
#214
Commits:
Stand (App): Vault standardmäßig ohne Forgejo, „Kein Sync“, Repository beim Bereitstellen wählen
iris-vault; das Vault sollte außerdem nicht automatisch verbunden werden.iris-vault, sonstiris-vault-2…), angelegt wird es erst mit „Verbinden“. „Anmelden …“ führt wie bisher zur Auswahl/Neuanlage nach der Anmeldung. (3) Mac-Server:GET /forgejo/repositories,publish-vault {repository?}, Administrator ohne vorbereitetes Repository. (4) Backup-Wiederherstellung verbindet das Vault nur noch, wenn es vorher auf dem eigenen Git-Server lag (Marker; enthält jetzt den Repository-Namen). (5) Handbuchkapitel angepasst.test-forgejo-core.sh41 Prüfungen, 0 Fehler (neu: Repository-Namen).iris-vault.PR #53 gemergt: feat(vault-sync): Kein Sync und Repository-Auswahl bei Dieser Rechner (iris/Iris#76)
iris/2ndbrain-ios#53
Commits:
Stand (IrisRemote): „Kein Sync“ und Repository-Auswahl bei „Dieser Rechner“
iris-vault, sonst-2…), „Verbinden“ legt es an und lädt das Vault hoch. NutztGET /forgejo/repositoriesundpublish-vault {repository}.xcodebuildfürgeneric/platform=iOSohne Signierung: BUILD SUCCEEDED.PR #127 gemergt: docs(wire): Repository-Auswahl beim Bereitstellen auf dem eigenen Git-Server (iris/Iris#76)
alf/2ndbrain#127
Commits:
PR #112 gemergt: fix(forgejo): Zertifikat der Freigabe mit serverAuth, macOS lehnte es ab (iris/Iris#76)
iris/iris-linux-server#112
Commits:
Stand (Linux-Server): „Stimmt – vertrauen“ scheiterte, weil dem Zertifikat serverAuth fehlte
forgejo_sharing.pyausgestellte Zertifikat hatte keine Extended Key UsageserverAuth. macOS lehnt das auch bei bestätigter CA ab (security verify-cert: „Invalid Extended Key Usage for policy“); OpenSSL (curl, git) prüft das nicht, deshalb liefen meine Tests über curl/git durch.serverAuthund KeyUsagedigitalSignature. Ein Zertifikat des älteren Aufbaus wird beim nächsten Serverstart automatisch neu ausgestellt (CERT_VERSION); die CA und damit der Fingerabdruck bleiben unverändert.test_forgejo_sharing.pygrün). Deploy auf iris-server: neues Zertifikat trägt „TLS Web Server Authentication“, CA unverändert,security verify-certauf dem Mac: „certificate verification successful“.PR #113 gemergt: fix(vault-sync): Anmeldung ignoriert Leerzeichen um das Passwort (iris/Iris#76)
iris/iris-linux-server#113
Commits:
Stand (Linux-Server): Anmeldung ignoriert Leerzeichen/Zeilenumbruch um das Passwort
vault_forge.loginschneidet Leerzeichen und Zeilenumbrüche an den Rändern des Passworts ab (Einfügen aus der Zwischenablage). Testtest_login_ignores_whitespace_around_a_pasted_password.test_forgejo_service.pygrün (25); auf iris-server deployt.PR #215 gemergt: fix(vault-sync): Passwort anzeigen, kopieren und Längenhinweis beim Verbinden (#76)
#215
Commits:
Stand (App): Passwort beim Verbinden besser prüfbar; Kopieren-Knopf
auth). Der Nutzer berichtet, im eingefügten Passwort fehlten die Unterstriche; im Feld standen 27 statt 32 Zeichen. Die Ursache des Verlusts ist nicht gefunden.VaultForge.login); in den Git-Server-Einstellungen neuer Knopf „Passwort kopieren“ (legt den exakten Text in die Zwischenablage) und die Anzeige ohne Markdown (Text(verbatim:)). iOS: Auge und Längenhinweis.PR #54 gemergt: fix(vault-sync): Passwort anzeigen und Längenhinweis beim Verbinden (iris/Iris#76)
iris/2ndbrain-ios#54
Commits:
PR #216 gemergt: feat(vault-sync): Passwort beim Verbinden standardmäßig als Text anzeigen (#76)
#216
Commits:
PR #55 gemergt: feat(vault-sync): Passwort beim Verbinden standardmäßig als Text anzeigen (iris/Iris#76)
iris/2ndbrain-ios#55
Commits:
Stand 2026-10-28: Test Linux-Server ↔ frische Mac-VM
https://192.168.178.153:3300, Fingerabdruck der Iris-CA bestätigt). Automatischer Abgleich in beide Richtungen ohne „Synchronisieren“: Anlegen einer Notiz auf der VM → Wächter-Commit nach 92 s → Push nach 9 s → Linux-Server holt nach 28 s (gesamt 2 min 9 s, per Mitschnitt auf der VM und Git-Verlauf auf dem Server gemessen). Änderungen und Löschungen im Quell-Vault (Linux) erschienen ohne manuellen Abgleich auf der VM (Aussage des Nutzers). Der Nutzer ist mit der Geschwindigkeit zufrieden, kein Echtzeitabgleich nötig.serverAuth(macOS lehnte es ab);.gitdes Vaults undvault-sync-credentials.jsongehörten root (#107); Freigabe des Git-Servers auch auf dem Linux-Server; Repository beim Bereitstellen wählbar statt festiris-vault; graue Lampe „Kein Sync“ als Standard; Info-Fenster zur Lampe mit Git-Server-Adresse; Passwort im Anmeldefeld sichtbar, Längenhinweis, „Passwort kopieren“._load_credentials()meldet einen unlesbaren Datei-Zugriff als „Zugangsdaten abgelehnt“ (nicht entschieden); Deploy-Vorlagedocker-compose.deploy.yml.templateohne Port 3300.