Dateiformate: App-Konfiguration und .dionotes-Marker #4

Closed
opened 2026-08-27 12:32:54 +00:00 by RDietermann · 1 comment
Owner

Part of #1

Question

Welche Dateien schreibt DioNotes, wohin, in welchem Format — und was steht drin?

Es sind zwei getrennte Dinge:

1. Die anwendungsweite Konfiguration (Ort kommt aus dem Recherche-Ticket): enthält mindestens die Liste bekannter Workspaces. Zu entscheiden: Dateiformat (JSON? TOML? RON?), welche Felder pro Eintrag (Pfad, Anzeigename, zuletzt geöffnet?), Reihenfolge der Liste, und ob eine Versionsangabe mitgeschrieben wird.

2. Der .dionotes/-Marker im Workspace-Ordner: Zu entscheiden, ob darin überhaupt eine Datei liegt oder das leere Verzeichnis als Marker reicht. Falls Datei: welche Felder (Name? Erstellungszeitpunkt? Schema-Version?) und wozu sie dienen, die noch in dieser Map gebraucht werden — nicht spekulativ befüllen.

Querschnittsfrage für beide: Was passiert bei einer Datei, die nicht geparst werden kann? Und braucht es jetzt schon eine Versionsangabe, oder ist das Vorsorge für ein Problem, das noch niemand hat?

Zielgröße: für beide Dateien je ein Beispielinhalt, den man abtippen könnte.


Nachtrag nach der Recherche zum Ablageort (#3). Der Pfad ist geklärt, aber dabei ist eine dritte Entscheidung aufgetaucht, die hierher gehört:

3. Welche Crate ermittelt den Pfad? Die Recherche empfiehlt directories 6.0.0. Zu entscheiden ist, ob die zusätzliche Abhängigkeit das wert ist:

  • dirs 6.0.0 liegt über wry/tray-icon bereits im Lockfile, kostet also nichts.
  • Das Hauptargument für directories war die automatische Namensnormalisierung (unter Linux dionotes statt DioNotes) — die man auch mit einem .join("dionotes") von Hand bekommt.
  • Zu prüfen: Bietet dirs selbst ein state_dir()? Wenn ja, schrumpft der Unterschied auf eine Zeile Code gegen eine Crate im Graph, und die Empfehlung wäre neu zu bewerten.

Die Fakten zum Pfad selbst stehen in #3 und auf dem Branch research/config-ablageort; sie sind von dieser Frage unberührt.

Part of #1 ## Question Welche Dateien schreibt DioNotes, wohin, in welchem Format — und was steht drin? Es sind zwei getrennte Dinge: **1. Die anwendungsweite Konfiguration** (Ort kommt aus dem Recherche-Ticket): enthält mindestens die Liste bekannter Workspaces. Zu entscheiden: Dateiformat (JSON? TOML? RON?), welche Felder pro Eintrag (Pfad, Anzeigename, zuletzt geöffnet?), Reihenfolge der Liste, und ob eine Versionsangabe mitgeschrieben wird. **2. Der `.dionotes/`-Marker** im Workspace-Ordner: Zu entscheiden, ob darin überhaupt eine Datei liegt oder das leere Verzeichnis als Marker reicht. Falls Datei: welche Felder (Name? Erstellungszeitpunkt? Schema-Version?) und wozu sie dienen, die noch in dieser Map gebraucht werden — nicht spekulativ befüllen. Querschnittsfrage für beide: Was passiert bei einer Datei, die nicht geparst werden kann? Und braucht es jetzt schon eine Versionsangabe, oder ist das Vorsorge für ein Problem, das noch niemand hat? Zielgröße: für beide Dateien je ein Beispielinhalt, den man abtippen könnte. --- **Nachtrag nach der Recherche zum Ablageort (#3).** Der Pfad ist geklärt, aber dabei ist eine dritte Entscheidung aufgetaucht, die hierher gehört: **3. Welche Crate ermittelt den Pfad?** Die Recherche empfiehlt `directories 6.0.0`. Zu entscheiden ist, ob die zusätzliche Abhängigkeit das wert ist: - `dirs 6.0.0` liegt über `wry`/`tray-icon` **bereits im Lockfile**, kostet also nichts. - Das Hauptargument für `directories` war die automatische Namensnormalisierung (unter Linux `dionotes` statt `DioNotes`) — die man auch mit einem `.join("dionotes")` von Hand bekommt. - Zu prüfen: Bietet `dirs` selbst ein `state_dir()`? Wenn ja, schrumpft der Unterschied auf eine Zeile Code gegen eine Crate im Graph, und die Empfehlung wäre neu zu bewerten. Die Fakten zum Pfad selbst stehen in #3 und auf dem Branch `research/config-ablageort`; sie sind von dieser Frage unberührt.
RDietermann added the wayfinder:grilling label 2026-08-27 12:32:54 +00:00
RDietermann added a new dependency 2026-08-27 12:35:51 +00:00
RDietermann added a new dependency 2026-08-27 12:36:04 +00:00
RDietermann added a new dependency 2026-08-27 12:36:05 +00:00
RDietermann self-assigned this 2026-08-27 13:28:56 +00:00
Author
Owner

Antwort

Format für beide Dateien: RON. Bewusst gegen serde_json/toml, die bereits transitiv im Lockfile liegen — RON kostet eine zusätzliche Dependency, serialisiert dafür Rust-Enums und Option ohne Umwege. Das zahlt sich bei den Workspace-Einstellungen und Versionierungsoptionen aus, die noch kommen.

Pfad-Ermittlung: dirs 6.0.0, nicht directories. dirs liegt über wry bereits im Graph und hat sowohl state_dir() als auch config_local_dir() — der einzige Mehrwert von directories wäre die Kleinschreibung des Ordnernamens gewesen, und die gibt es hier durch eine Konstante.


1. Die Workspace-Liste

Ort — ein Ausdruck für alle Plattformen, ohne #[cfg]:

const APP_DIR: &str = "dionotes"; // klein, auf allen Plattformen

let dir = dirs::state_dir()
    .unwrap_or_else(|| dirs::config_local_dir().expect("kein Konfigurationsverzeichnis"))
    .join(APP_DIR);
let file = dir.join("workspaces.ron");
Plattform Ergebnis
Windows C:\Users\<Benutzer>\AppData\Local\dionotes\workspaces.ron
Linux ~/.local/state/dionotes/workspaces.ron
macOS ~/Library/Application Support/dionotes/workspaces.ron

Windows bekommt Local, nicht Roaming: absolute Workspace-Pfade sind maschinenspezifisch und würden beim Roaming auf einem anderen Rechner ins Leere zeigen. Linux bekommt $XDG_STATE_HOME statt ~/.config, weil die XDG-Spec „recently used files" wörtlich als State führt — state_dir() liefert nur dort Some, deshalb trägt der Fallback ohne Fallunterscheidung. Das Verzeichnis muss die App selbst anlegen (create_dir_all), die Basis existiert garantiert.

Inhalt — eine Liste von Pfaden, sonst nichts:

(workspaces: [
    "C:\\Users\\marvin\\Notizen",
    "D:\\Projekte\\DioNotes-Testdaten",
])
  • Kein Anzeigename. Der Name ist der Ordnername (path.file_name()). Ein eigenes Feld wäre nach dem ersten Umbenennen des Ordners falsch.
  • Kein last_opened. Die Reihenfolge der Liste ist die Sortierung; wer einen Workspace öffnet, dessen Eintrag wandert nach vorn. Spart einen Zeitstempel samt Zeitzonen- und Uhrumstellungsfragen für eine reine Sortierreihenfolge.
  • Keine Schema-Version. Diese Datei enthält nichts Unwiederbringliches — geht sie verloren, wählt der Nutzer seine Ordner einmal neu. Damit entfallen Migrationspfad und Reparaturlogik.
  • Beim Hinzufügen wird auf gleichen Pfad geprüft, damit derselbe Workspace nicht doppelt in der Liste steht.

Bei beschädigter Datei: verwerfen und mit leerer Liste starten. Kein Reparaturversuch.

2. Der .dionotes/-Marker

Er ist kein leeres Verzeichnis, sondern enthält .dionotes/workspace.ron. Heute steht darin genau ein Feld:

(schema_version: 1)
  • schema_version ab 1. Anders als bei der Workspace-Liste ist das Wachstum des Schemas bereits angekündigt (Passwortschutz, Workspace-Einstellungen, Versionierungsoptionen). Das Feld ist der einzige Weg, eine künftig geschriebene Datei beim Einlesen als „neuer als diese App" zu erkennen, statt sie halb zu verstehen. Der billigste Zeitpunkt dafür ist jetzt, bevor Dateien in freier Wildbahn sind.
  • Kein created_at. Das Erstellungsdatum des Ordners kennt das Dateisystem (fs::metadata().created()). Es zu duplizieren schafft eine zweite Wahrheit, die beim Kopieren des Ordners auseinanderläuft.
  • Keine Vorratsfelder. Serde erlaubt mit #[serde(default)], Felder später bruchfrei zu ergänzen — ein password_hash: None, das noch nichts bedeutet, müsste dagegen jeder Leser interpretieren. Die Felder entstehen mit dem Feature, das sie braucht.

Bei beschädigter Datei: Workspace nicht öffnen, Fehler zeigen — nicht neu anlegen. Das ist heute, mit nur schema_version im Marker, überstreng. Es ist die richtige Entscheidung, sobald dort ein Passwort-Hash liegt: „Datei kaputt, App legt sie ohne Hash neu an" wäre sonst ein Weg, den Schutz auszuhebeln. Diese Gewohnheit jetzt zu setzen ist billiger, als sie später umzustellen.


Anschlussfrage, bewusst nicht hier entschieden

Ein Passwort-Hash in .dionotes/ sperrt den Zugang über DioNotes. Die .md-Dateien liegen unverschlüsselt daneben und sind mit jedem Editor lesbar. Soll der Schutz gegen jemanden mit Dateisystemzugriff wirken, braucht es Verschlüsselung der Notizinhalte — eigener Effort, als Fog auf der Map vermerkt.

## Antwort **Format für beide Dateien: RON.** Bewusst gegen `serde_json`/`toml`, die bereits transitiv im Lockfile liegen — RON kostet eine zusätzliche Dependency, serialisiert dafür Rust-Enums und `Option` ohne Umwege. Das zahlt sich bei den Workspace-Einstellungen und Versionierungsoptionen aus, die noch kommen. **Pfad-Ermittlung: `dirs 6.0.0`**, nicht `directories`. `dirs` liegt über `wry` bereits im Graph und hat sowohl `state_dir()` als auch `config_local_dir()` — der einzige Mehrwert von `directories` wäre die Kleinschreibung des Ordnernamens gewesen, und die gibt es hier durch eine Konstante. --- ### 1. Die Workspace-Liste **Ort** — ein Ausdruck für alle Plattformen, ohne `#[cfg]`: ```rust const APP_DIR: &str = "dionotes"; // klein, auf allen Plattformen let dir = dirs::state_dir() .unwrap_or_else(|| dirs::config_local_dir().expect("kein Konfigurationsverzeichnis")) .join(APP_DIR); let file = dir.join("workspaces.ron"); ``` | Plattform | Ergebnis | | --- | --- | | Windows | `C:\Users\<Benutzer>\AppData\Local\dionotes\workspaces.ron` | | Linux | `~/.local/state/dionotes/workspaces.ron` | | macOS | `~/Library/Application Support/dionotes/workspaces.ron` | Windows bekommt **Local, nicht Roaming**: absolute Workspace-Pfade sind maschinenspezifisch und würden beim Roaming auf einem anderen Rechner ins Leere zeigen. Linux bekommt `$XDG_STATE_HOME` statt `~/.config`, weil die XDG-Spec „recently used files" wörtlich als State führt — `state_dir()` liefert nur dort `Some`, deshalb trägt der Fallback ohne Fallunterscheidung. Das Verzeichnis muss die App selbst anlegen (`create_dir_all`), die Basis existiert garantiert. **Inhalt** — eine Liste von Pfaden, sonst nichts: ```ron (workspaces: [ "C:\\Users\\marvin\\Notizen", "D:\\Projekte\\DioNotes-Testdaten", ]) ``` - **Kein Anzeigename.** Der Name ist der Ordnername (`path.file_name()`). Ein eigenes Feld wäre nach dem ersten Umbenennen des Ordners falsch. - **Kein `last_opened`.** Die *Reihenfolge der Liste* ist die Sortierung; wer einen Workspace öffnet, dessen Eintrag wandert nach vorn. Spart einen Zeitstempel samt Zeitzonen- und Uhrumstellungsfragen für eine reine Sortierreihenfolge. - **Keine Schema-Version.** Diese Datei enthält nichts Unwiederbringliches — geht sie verloren, wählt der Nutzer seine Ordner einmal neu. Damit entfallen Migrationspfad und Reparaturlogik. - **Beim Hinzufügen wird auf gleichen Pfad geprüft**, damit derselbe Workspace nicht doppelt in der Liste steht. **Bei beschädigter Datei: verwerfen und mit leerer Liste starten.** Kein Reparaturversuch. ### 2. Der `.dionotes/`-Marker Er ist **kein leeres Verzeichnis**, sondern enthält `.dionotes/workspace.ron`. Heute steht darin genau ein Feld: ```ron (schema_version: 1) ``` - **`schema_version` ab 1.** Anders als bei der Workspace-Liste ist das Wachstum des Schemas bereits angekündigt (Passwortschutz, Workspace-Einstellungen, Versionierungsoptionen). Das Feld ist der einzige Weg, eine künftig geschriebene Datei beim Einlesen als „neuer als diese App" zu erkennen, statt sie halb zu verstehen. Der billigste Zeitpunkt dafür ist jetzt, bevor Dateien in freier Wildbahn sind. - **Kein `created_at`.** Das Erstellungsdatum des Ordners kennt das Dateisystem (`fs::metadata().created()`). Es zu duplizieren schafft eine zweite Wahrheit, die beim Kopieren des Ordners auseinanderläuft. - **Keine Vorratsfelder.** Serde erlaubt mit `#[serde(default)]`, Felder später bruchfrei zu ergänzen — ein `password_hash: None`, das noch nichts bedeutet, müsste dagegen jeder Leser interpretieren. Die Felder entstehen mit dem Feature, das sie braucht. **Bei beschädigter Datei: Workspace nicht öffnen, Fehler zeigen — nicht neu anlegen.** Das ist heute, mit nur `schema_version` im Marker, überstreng. Es ist die richtige Entscheidung, sobald dort ein Passwort-Hash liegt: „Datei kaputt, App legt sie ohne Hash neu an" wäre sonst ein Weg, den Schutz auszuhebeln. Diese Gewohnheit jetzt zu setzen ist billiger, als sie später umzustellen. --- ### Anschlussfrage, bewusst nicht hier entschieden Ein Passwort-Hash in `.dionotes/` sperrt den Zugang *über DioNotes*. Die `.md`-Dateien liegen unverschlüsselt daneben und sind mit jedem Editor lesbar. Soll der Schutz gegen jemanden mit Dateisystemzugriff wirken, braucht es Verschlüsselung der Notizinhalte — eigener Effort, als Fog auf der Map vermerkt.
Sign in to join this conversation.