# 🧠 BRAIN.md — MindSift Internal Dev Cheat Sheet & Architecture Log > **Zweck:** Zentrales, technisch prĂ€zises Nachschlagewerk fĂŒr Entwicklung, Design-System, Datenbank-Architektur, State-Machines, Backend-APIs und aktuellen Umsetzungsstand. Wird bei jeder Änderung aktuell gehalten. --- ## 📋 0. Aktueller Projektplan & Umsetzungs-Status ### Erledigte Meilensteine - [x] **CI/CD & Multi-Stage Docker Build (`Dockerfile`, `.gitea/workflows/build-and-publish.yaml`):** - Alle Frontend-Checks (`tsc --noEmit`, `vite build`) und Backend-Tests (`go test -v ./...`) laufen direkt im Multi-Stage Container-Build ohne doppelte Vorab-Steps. - Push auf `dev` baut und ĂŒberschreibt `git.dsit.me/sandrodach/mindsift:dev`. - [x] **Monochromes, eckiges Desktop-Design & Zentrale CSS-Steuerung (`frontend/src/index.css`, `frontend/tailwind.config.js`):** - Zentrale CSS-Variablen (`--bg-app`, `--bg-panel`, `--accent-primary`, `--border-color`, `--radius-card: 0px`) in `frontend/src/index.css`. - Eckige Tabs, eckige Panels/Karten (`0px` Radius), nur die Schnell-Eingabe-Blase oben im Header und Profil-Avatare sind rund (`rounded-full`). - Untere doppelte Navigationsleiste entfernt; Schnell-Notiz-Blase (`InstantCaptureBar`) sitzt ganz oben im Header ĂŒber den Tabs. - Workspace links als eckiger, monochromer Datei-/Ordner-Baum (File Explorer Tree mit Unterordnern). - [x] **Quick Dump Notes + Triage Swipen + Direkt-Zuordnung (`InstantCaptureBar.tsx`, `TriageDeck.tsx`, `server.go`):** - **Quick Dump (Standard):** Text oben eingeben + `Enter` wirft den Gedanken sofort als Quick Dump (`status: 'inbox'`) ins Triage-Deck. - **Direkt-Zuordnung bei der Eingabe:** Über das Auswahl-MenĂŒ (`Quick Dump â–Ÿ`) in der Eingabeleiste kann ein Eintrag alternativ direkt als **Aufgabe** (`target: 'task'`), direkt auf eine **Geteilte Liste** (`target: 'list_item'`) oder direkt als **Workspace-Notiz** (`target: 'document'`) gespeichert werden. - **Triage-Entscheidung & Warteschlange:** Im Triage-Deck per Swipe/Klick **Wegwerfen** (`←` / `H`), **SpĂ€ter** (`Leertaste` – ans Ende schieben), **Auf Liste**, **Als Notiz** (`D`), **Mit Termin** (`T`) oder **Als Aufgabe** (`→` / `L`). Inklusive Inline-Textbearbeitung und Warteschlangen-Liste unter der aktiven Karte. - [x] **Mehrere Aufgabenlisten & Kanban-Board (`TasksView.tsx`, `models.go`, `sqlite.go`):** - Beliebig viele Aufgabenlisten (z.B. Privat, Arbeit, Homelab) mit eigenem Farb- und Icon-Code. - Teilen von Aufgabenlisten mit Teams/Spaces. - Umschalter zwischen kompakter Listenansicht und 3-Spalten-Kanban-Board (`Zu erledigen`, `In Arbeit`, `Erledigt`) mit 1-Klick-Statuswechsel, FĂ€lligkeitsdaten und Notizfeldern. - [x] **Ersteinrichtung (First-Boot Setup Wizard), Echter Login & Einladungscodes (`SetupAndAuthView.tsx`, `server.go`, `sqlite.go`):** - Kein hartcodierter Auto-Seed-Benutzer (`admin@mindsift.local` / `"Sandro"`) und kein automatischer `quickStart`-Login mehr beim Seitenaufruf. - Beim ersten Start (`0` Benutzer in der Datenbank) erkennt `GET /api/v1/auth/status` automatisch `needsSetup: true` und zeigt den **Ersteinrichtungs-Assistenten** (`POST /api/v1/auth/setup`) zum Anlegen des ersten Server-Admin-Kontos und der Instanz-Grundeinstellungen. - Öffentliche Selbstregistrierung ist standardmĂ€ĂŸig deaktiviert (`allowRegistration: false`). Neue Benutzer können nur ĂŒber einen **Einladungscode** (`MS-XXXXXXXX`, Tabelle `user_invites`) oder direkt durch einen Admin (`admin` / `team_admin`) angelegt werden. - [x] **Profile-Dropdown & Vollbild-Einstellungsseiten statt kleinem Modal (`App.tsx`, `UserSettingsView.tsx`, `AdminSettingsView.tsx`):** - Klick auf den Benutzer oben rechts öffnet ein eckiges, monochromes Dropdown-MenĂŒ: - **Kontoeinstellungen** (`UserSettingsView.tsx` — Vollbild-Ansicht fĂŒr Profil & Passwort, Multi-Channel-Alarme, Private Webhooks & Daten-Export). - **Administration** (`AdminSettingsView.tsx` — nur sichtbar fĂŒr `admin` und `team_admin`; Vollbild-Ansicht fĂŒr Benutzer, Rollen, Einladungscodes, Organisationen & Teams, Server-Isolation und SMTP-Mailserver). - **Abmelden** (bereinigt JWT-Token und fĂŒhrt zurĂŒck zum Login-Bildschirm). - 3-stufiges Rollensystem: `admin` (Server-Admin), `team_admin` (Team-Admin mit Berechtigung zum Einladen und Verwalten von Teams) und `member` (Mitglied). - Layout-Fix im Benutzer-Erstellungsformular (`grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3` mit `min-w-0`), sodass das Rollen-Dropdown niemals ĂŒber den Container hinausragt. - [x] **Multi-Channel-Alarme: E-Mail (SMTP), Discord & Eigener Webhook (`UserSettingsView.tsx`, `AdminSettingsView.tsx`, `server.go`):** - Tab heißt klar **Alarme** mit frei kombinierbaren Zielen (`alarmChannels`: `'email'`, `'discord'`, `'webhook'`). - SMTP-Konfiguration (`SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM`, `SMTP_TLS`) sowohl ĂŒber `docker-compose.yml` Environment-Variablen als auch direkt in der Admin-OberflĂ€che (`system_settings` in SQLite) einstellbar, inklusive Live-Testversand. - [x] **Crash-Fix fĂŒr „Aufgaben" & „Organisationen & Teams" (`sqlite.go`, `api.ts`, `TasksView.tsx`):** - Alle Go-Storage-Methoden initialisieren Slices strikt mit `make([]T, 0)` statt `var s []T`, damit `json.Marshal` niemals `null` statt `[]` liefert. - ZusĂ€tzliche `ensureArray()`-Normalisierung in `frontend/src/lib/api.ts` sowie `ViewErrorBoundary` in `App.tsx`. - [x] **Workspace Markdown-Wiki mit Notion-/Word-Toolbar & Disk-Sync (`WorkspaceView.tsx`, `sqlite.go`):** - Word-/Notion-artige Formatierungsleiste oben (Fett, Kursiv, Durchgestrichen, Code, Links, Überschriften H1-H3, Checklisten, AufzĂ€hlungen, Callouts, Markdown-Tabellen, Fortschrittsbalken). - Interne Wiki-Links (`[[Dokumenttitel]]`) mit Klick-Navigation und Auto-Erkennung. - Physische Speicherung auf Festplatte unter `/data/workspace//...` als Standard-`.md`-Dateien zur einfachen Daten-Extraktion, synchronisiert mit SQLite. - [x] **Cross-Browser & Performance Fixes (Chrome & Firefox):** - SQLite Connection-Pool Deadlock durch striktes Schließen von `sql.Rows` vor Unterabfragen behoben. - `Cache-Control: no-store` auf allen API-Routen und `index.html`. - Optimistisches Leeren des Capture-Inputs und 12-Sekunden-Fetch-Timeout. --- ## 🎹 1. Design-System & CSS-Architektur (`frontend/src/index.css`) Alle Farben, AbstĂ€nde und Radien werden zentral in [`frontend/src/index.css`](file:///home/sandro/Dokumente/git/MindSift/frontend/src/index.css) ĂŒber CSS-Variablen gesteuert: ```css :root { /* Monochromer Hintergrund (Dunkles Schiefer/Anthrazit) */ --bg-app: #121316; --bg-panel: #1a1c20; --bg-panel-elevated: #22252a; --bg-panel-hover: #282c33; /* Einzige Akzentfarbe + hellere/gedimmte Variante */ --accent-primary: #2563eb; --accent-hover: #3b82f6; --accent-dim: rgba(37, 99, 235, 0.14); --accent-border: rgba(59, 130, 246, 0.45); /* Kanten & Linien */ --border-color: rgba(255, 255, 255, 0.09); --border-subtle: rgba(255, 255, 255, 0.05); /* Eckiges Layout (0px fĂŒr Karten/Panels, minimal fĂŒr Inputs) */ --radius-card: 0px; --radius-btn: 2px; --radius-input: 2px; } ``` ### Zentrale Komponenten-Klassen - `.panel-surface` / `.panel-elevated`: Eckige Container mit `1px solid var(--border-color)`. - `.btn-action`: Monochromer, kompakter Button (`border-radius: var(--radius-btn)`). - `.btn-primary`: Akzent-Button auf `--accent-primary`. - `.input-field`: Minimal gerundetes (`2px`) Eingabefeld fĂŒr Eigenschaften/Optionen. - `.tab-btn` / `.tab-btn-active`: Eckige, monochrome Header-Tabs. - `.badge-accent`: Kompaktes Akzent-Badge fĂŒr ZĂ€hler und Tags. - **Ausnahme fĂŒr Rundungen (`rounded-full`):** Nur die Schnell-Eingabe-Blase (`InstantCaptureBar`) im Header, der Profil-Avatar und Toggle-Switches sind rund. --- ## đŸ—„ïž 2. Datenbank-Architektur (SQLite Schema & Tabellen) MindSift speichert alle Daten lokal und hochperformant in SQLite (`/data/mindsift.db`). ### Tabellen-Übersicht 1. **`users`** - `id TEXT PRIMARY KEY`, `email TEXT UNIQUE`, `password_hash TEXT`, `display_name TEXT` - `role TEXT DEFAULT 'member'` (`'admin'` | `'member'`) - `is_active INTEGER DEFAULT 1` - `discord_webhook_url TEXT DEFAULT ''` - `notify_before_minutes INTEGER DEFAULT 15` - `created_at DATETIME`, `updated_at DATETIME` 2. **`thoughts` (Quick Dumps, Triage & Aufgaben)** - `id TEXT PRIMARY KEY`, `user_id TEXT`, `content TEXT`, `source TEXT`, `priority TEXT` - `status TEXT` (`'inbox'` | `'converted'` | `'discarded'`) - `converted_type TEXT` (`'task'` | `'document'` | `'list_item'`) - `converted_ref_id TEXT` (Referenz auf Document oder ListItem) - `task_list_id TEXT` (FK auf `task_lists.id`) - `kanban_status TEXT DEFAULT 'todo'` (`'todo'` | `'in_progress'` | `'done'`) - `notes TEXT DEFAULT ''` (zusĂ€tzliche Aufgabenbeschreibung/Notizen) - `due_date DATETIME` (FĂ€lligkeitsdatum) - `alarm_sent INTEGER DEFAULT 0` (Flag fĂŒr Discord-Benachrichtigung) - `created_at DATETIME`, `updated_at DATETIME` 3. **`task_lists` (Mehrere Aufgabenlisten)** - `id TEXT PRIMARY KEY`, `user_id TEXT`, `space_id TEXT` (optional fĂŒr Team-Sharing) - `name TEXT NOT NULL`, `color TEXT DEFAULT '#2563eb'`, `icon TEXT DEFAULT 'list'` - `is_default INTEGER DEFAULT 0`, `created_at DATETIME`, `updated_at DATETIME` 4. **`organizations` & `teams` & `team_members`** - `organizations`: `id TEXT PRIMARY KEY`, `name TEXT`, `owner_id TEXT`, `created_at DATETIME`, `updated_at DATETIME` - `teams`: `id TEXT PRIMARY KEY`, `organization_id TEXT`, `name TEXT`, `created_at DATETIME` - `team_members`: `team_id TEXT`, `user_id TEXT`, `role TEXT DEFAULT 'member'`, `joined_at DATETIME`, `PRIMARY KEY (team_id, user_id)` 5. **`system_settings` (Admin-Konfiguration)** - `key TEXT PRIMARY KEY`, `value TEXT`, `updated_at DATETIME` - Wichtige SchlĂŒssel: - `sharing_isolation_mode`: `'open'` | `'teams_only'` | `'strict_private'` - `allow_public_registration`: `'true'` | `'false'` 6. **`documents` & `document_blocks` (Workspace & Disk Sync)** - `documents`: `id TEXT PRIMARY KEY`, `user_id TEXT`, `space_id TEXT`, `title TEXT`, `folder_path TEXT DEFAULT '/'`, `is_archived INTEGER`, `created_at DATETIME`, `updated_at DATETIME` - `document_blocks`: `id TEXT PRIMARY KEY`, `document_id TEXT`, `block_type TEXT` (`paragraph`, `heading1`, `heading2`, `heading3`, `todo`, `bullet`, `callout`, `code`, `table`, `progress`), `content TEXT`, `order_index INTEGER`, `metadata TEXT`, `updated_at DATETIME` 7. **`spaces`, `space_members`, `shared_lists`, `list_items`, `api_keys`** - Verwaltung geteilter Einkaufs-/Checklisten und privater Ingestion-Keys. --- ## ⚙ 3. State-Machine: Quick Dump, Direkt-Zuordnung & Triage ``` [ HEADER QUICK-CAPTURE BAR ] │ ┌───────────────────────┌───────────────────────┐ │ Standard (Enter) │ Direkt-Option gewĂ€hlt │ â–Œ â–Œ â–Œ status: 'inbox' status: 'converted' status: 'converted' (Quick Dump Deck) ├── target: 'task' ├── target: 'list_item' │ └── target: 'document' └── Broadcast via WS │ ├──â–ș Swipe Links / "Wegwerfen" (H / ←) ──â–ș status: 'discarded' ├──â–ș "SpĂ€ter" (Leertaste) ──â–ș ans Ende der lokalen Queue ├──â–ș Swipe Rechts / "Als Aufgabe" (L/→)──â–ș status: 'converted' (type: 'task') ├──â–ș "Mit Termin" (T) ──â–ș status: 'converted' (type: 'task', dueDate) ├──â–ș "Als Notiz" (D) ──â–ș status: 'converted' (type: 'document' + Doc angelegt) └──â–ș "Auf Liste" ──â–ș status: 'converted' (type: 'list_item' + Item angelegt) ``` ### API-Endpunkt fĂŒr Capture (`POST /api/v1/inbox`) Akzeptiert: - `content`: Fließtext des Gedankens - `priority`: `'low'` | `'medium'` | `'high'` - `target`: `'inbox'` (Standard) | `'task'` | `'list_item'` | `'document'` - `taskListId`: ID der Aufgabenliste (wenn `target === 'task'`) - `targetListId`: ID der Zielliste (wenn `target === 'list_item'`) - `dueDate`: Optionales ISO-Datum --- ## 🔔 4. Discord-Alarm-Scheduler & Webhook-Architektur 1. **Hintergrund-Ticker im Go-Backend (`internal/api/server.go`):** - Ein Hintergrund-Goroutine-Ticker lĂ€uft alle 60 Sekunden. - Fragt `GetDueTasksForAlarm()` ab: Sucht nach offenen Aufgaben (`status = 'converted'`, `converted_type = 'task'`, `kanban_status != 'done'`), deren `due_date` in der Vorwarnzeit liegt (`due_date <= now + notifyBeforeMinutes`) und bei denen `alarm_sent == 0` ist. - Sendet ein JSON-Embed an die in den Benutzer-Einstellungen hinterlegte `discord_webhook_url`: ```json { "username": "MindSift Reminder", "embeds": [{ "title": "⏰ Aufgabe fĂ€llig: ", "description": "", "color": 2450411, "fields": [ {"name": "FĂ€llig am", "value": "", "inline": true}, {"name": "PrioritĂ€t", "value": "", "inline": true} ] }] } ``` - Markiert den Gedanken in SQLite mit `MarkTaskAlarmSent(taskID)` als benachrichtigt. 2. **Eingehende Webhooks / Private API-Tokens:** - Erreichbar unter `POST /api/v1/inbox` mit Header `X-API-Key: ms_...`. - Ermöglicht direkte Einbindung in Shell-Skripte, Crons oder Drittsysteme via `curl`. --- ## 📝 5. Workspace: Word/Notion-Toolbar, Wiki-Links & Disk-Sync 1. **Formatierungs-Werkzeuge:** - Markdown-Syntax wird in Echtzeit formatiert und visuell aufbereitet. - Buttons fĂŒr H1, H2, H3, Fett (`**`), Kursiv (`*`), Durchgestrichen (`~~`), Code-Blöcke (```` ``` ````), AufzĂ€hlungen (`- `), Todos (`- [ ] `), Callouts (`> `), Markdown-Tabellen (`| Spalte 1 | Spalte 2 |`) und Fortschrittsbalken (`[progress:65%]`). 2. **Wiki-Links (`[[Dokumenttitel]]`):** - Interne Querverweise werden als interaktive Links gerendert. - Ein Klick auf `[[Dokumenttitel]]` durchsucht die Workspace-Dokumente und öffnet das verlinkte Dokument direkt im Editor. 3. **Physische Speicherung auf Festplatte:** - Jede Notiz wird zusĂ€tzlich zur SQLite-Tabelle als reine `.md`-Datei unter `/data/workspace///.md` gespeichert. - Ermöglicht jederzeitige manuelle Datensicherung, Git-Versionierung oder Backup-Extraktion ohne Datenbank-AbhĂ€ngigkeit. --- ## đŸ›Ąïž 6. Kritische Backend-Regeln (SQLite & HTTP) 1. **NIEMALS verschachtelte Queries bei offenem `sql.Rows`-Cursor ausfĂŒhren:** - In [`internal/storage/sqlite.go`](file:///home/sandro/Dokumente/git/MindSift/internal/storage/sqlite.go) muss jede Schleife `for rows.Next()` zuerst alle Zeilen in ein Slice einlesen und sofort `_ = rows.Close()` aufrufen, **bevor** Folgeabfragen (`GetListItems`, `GetSpaceMembers`, `QueryRow` etc.) ausgefĂŒhrt werden. 2. **SQLite DSN-Pragmas:** - Jede Verbindung im `sql.DB`-Pool erhĂ€lt ĂŒber den DSN automatisch: `?_pragma=busy_timeout(10000)&_pragma=journal_mode(WAL)&_pragma=synchronous(NORMAL)&_pragma=foreign_keys(1)` - `MaxOpenConns(8)` und `MaxIdleConns(4)` konfiguriert. 3. **Thread-Safe Default User (`EnsureDefaultUser`):** - Durch `s.initMu.Lock()` abgesichert, damit parallele Browser-Requests beim ersten Laden niemals in einen `UNIQUE constraint`-Konflikt laufen. 4. **Kein Browser-Caching auf API & `index.html`:** - `writeJSON` und der SPA-Fallback setzen `Cache-Control: no-store, no-cache, must-revalidate`, damit Chrome und Firefox nach jedem Container-Update sofort den aktuellen Stand zeigen. --- ## 📡 7. WebSocket Realtime Protocol (Geteilte Listen) Verbindungs-URL: `ws(s):///api/v1/ws/spaces/:spaceId?token=` ### Events - `ITEM_CREATED` (auch ausgelöst, wenn ein Gedanke per Direkt-Zuordnung oder Triage auf eine Liste geschoben wird) - `ITEM_TOGGLED` - `ITEM_DELETED` - `LIST_CREATED` / `LIST_DELETED` / `LIST_CLEARED` - `USER_PRESENCE` --- ## ⌚ 8. Tastatur-Shortcuts (Desktop) | Taste | Kontext | Aktion | | :--- | :--- | :--- | | `C` oder `/` | Überall | Fokus sofort oben in die Quick-Dump-Eingabeleiste | | `Enter` | Capture-Leiste | Sofort speichern (Quick Dump oder gewĂ€hltes Direkt-Ziel) | | `Esc` | Capture-Leiste | Eingabe leeren & Dropdown schließen | | `H` oder `←` | Triage-Deck | Aktiven Quick Dump wegwerfen (`discard`) | | `L` oder `→` | Triage-Deck | Aktiven Quick Dump sofort zur Aufgabe machen (`task`) | | `T` | Triage-Deck | Datums-Auswahl fĂŒr Termin-Aufgabe öffnen | | `D` | Triage-Deck | Aktiven Quick Dump sofort in Workspace-Notiz umwandeln | | `Leertaste` | Triage-Deck | Karte ĂŒberspringen („SpĂ€ter" – ans Ende des Stapels schieben) | --- ## 🚀 9. Gitea CI/CD & Docker Workflow - **Arbeits-Branch:** `dev` (`origin/dev`) - **Ziel-Image:** `git.dsit.me/sandrodach/mindsift:dev` - **Build-Prinzip:** Ein einziger Multi-Stage-Build ([`Dockerfile`](file:///home/sandro/Dokumente/git/MindSift/Dockerfile)), der Frontend-Typecheck, Vite-Build und Go-Unit-Tests (`go test -v ./...` inkl. [`internal/api/server_test.go`](file:///home/sandro/Dokumente/git/MindSift/internal/api/server_test.go)) direkt beim Image-Bau ausfĂŒhrt und bei Erfolg sofort pusht.