MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m22s
22 KiB
22 KiB
🧠 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
- 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
devbaut und überschreibtgit.dsit.me/sandrodach/mindsift:dev.
- Alle Frontend-Checks (
- Single-File CSS Theming Engine & Design-System (
frontend/src/themes/,theme.ts,tailwind.config.js):- Jedes Theme ist als genau eine einzige, eigenständige CSS-Datei unter
frontend/src/themes/definiert. - Alle Farben, Kontraste, Oberflächen, Rahmen, Statusfarben und Rundungen sind in 6 klaren Gruppen organisiert.
- 4 vorkonfigurierte Themes (Dark, Light, High Contrast, Soft) plus saubere
theme-template.css-Vorlage für eigene Themes. - Vollständige Trennung von Struktur und Styling: React-Komponenten enthalten keine hardcodierten Farbwerte mehr, sondern ausschließlich semantische Klassen und CSS-Variablen (
text-main,text-muted,bg-canvas,panel-surface,checkbox-square, etc.). - Schnellauswahl im Profil-Dropdown im Header sowie visueller Theme-Manager in den Benutzereinstellungen.
- Jedes Theme ist als genau eine einzige, eigenständige CSS-Datei unter
- Monochromes, eckiges Desktop-Design & Zentrale CSS-Steuerung:
- Zentrale CSS-Variablen (
--bg-canvas,--bg-panel,--accent,--border-color,--radius-card,--radius-btn,--radius-input) in den Theme-Dateien. - Eckige Tabs, eckige Panels/Karten (
0pxRadius im Dark/Monochrome-Theme), nur die Schnell-Eingabe-Blase (InstantCaptureBar) oben im Header nutzt--radius-pill. - Untere doppelte Navigationsleiste entfernt; Schnell-Notiz-Blase sitzt ganz oben im Header über den Tabs.
- Workspace links als eckiger, monochromer Datei-/Ordner-Baum (File Explorer Tree mit Unterordnern).
- Zentrale CSS-Variablen (
- Quick Dump Notes + Triage Swipen + Direkt-Zuordnung (
InstantCaptureBar.tsx,TriageDeck.tsx,server.go):- Quick Dump (Standard): Text oben eingeben +
Enterwirft 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.
- Quick Dump (Standard): Text oben eingeben +
- 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.
- 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 automatischerquickStart-Login mehr beim Seitenaufruf. - Beim ersten Start (
0Benutzer in der Datenbank) erkenntGET /api/v1/auth/statusautomatischneedsSetup: trueund 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, Tabelleuser_invites) oder direkt durch einen Admin (admin/team_admin) angelegt werden.
- Kein hartcodierter Auto-Seed-Benutzer (
- 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, Darstellung & Themes, Multi-Channel-Alarme, Private Webhooks & Daten-Export). - Administration (
AdminSettingsView.tsx— nur sichtbar füradminundteam_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).
- Kontoeinstellungen (
- 3-stufiges Rollensystem:
admin(Server-Admin),team_admin(Team-Admin mit Berechtigung zum Einladen und Verwalten von Teams) undmember(Mitglied). - Layout-Fix im Benutzer-Erstellungsformular (
grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3mitmin-w-0), sodass das Rollen-Dropdown niemals über den Container hinausragt.
- Klick auf den Benutzer oben rechts öffnet ein eckiges, monochromes Dropdown-Menü:
- 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 überdocker-compose.ymlEnvironment-Variablen als auch direkt in der Admin-Oberfläche (system_settingsin SQLite) einstellbar, inklusive Live-Testversand.
- Tab heißt klar Alarme mit frei kombinierbaren Zielen (
- Crash-Fix für „Aufgaben" & „Organisationen & Teams" (
sqlite.go,api.ts,TasksView.tsx):- Alle Go-Storage-Methoden initialisieren Slices strikt mit
make([]T, 0)stattvar s []T, damitjson.Marshalniemalsnullstatt[]liefert. - Zusätzliche
ensureArray()-Normalisierung infrontend/src/lib/api.tssowieViewErrorBoundaryinApp.tsx.
- Alle Go-Storage-Methoden initialisieren Slices strikt mit
- 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/<user_id>/...als Standard-.md-Dateien zur einfachen Daten-Extraktion, synchronisiert mit SQLite.
- Workspace Logseq Outliner-Engine, Zoom-Hoisting & Drag & Drop (
WorkspaceView.tsx,models.go,sqlite.go):- Bullet-Point-basiertes hierarchisches Notizensystem inspiriert von Logseq.
- Jeder Block ist ein Bullet-Point (
•) mit flexibler Einrückungstiefe (Level: 0, 1, 2...). - Schnelle Tastaturnavigation:
Enter: Neuer Bullet-Point auf gleicher Ebene.Tab: Block dem vorherigen unterordnen (einrücken).Shift+Tab: Block ausrücken.Shift+Enter: Weicher Zeilenumbruch innerhalb desselben Blocks.Backspace: Auf leerem Block rückt aus oder entfernt den Bullet-Point.
- Zoom-in Hoisting: Klick auf den Bullet-Dot zoomt tief in diesen Ast hinein (Fokusmodus) mit Breadcrumbs-Navigation und „Zoom aufheben"-Button.
- Drag & Drop: Bullet-Dots dienen als Anfasser zum Verschieben und Umsortieren von Blöcken und ganzen Unterbäumen.
- Slash-Commands (
/): Schnelle Umwandlung in/todo,/h1,/h2,/h3,/code,/table,/callout,/progress,/divider. - Physische Speicherung auf Festplatte unter
/data/workspace/<user_id>/...als Standard-.md-Dateien mit portabler 2-Leerzeichen-Einrückung (- [ ]bzw.-), vollständig kompatibel mit externen Outlinern und Markdown-Viewern.
- Globaler Workspace To-Do Rollup Dashboard (
WorkspaceView.tsx):- Aggregierte Übersicht aller To-Dos (
- [ ]/- [x]) aus sämtlichen Notiz-Dateien über alle Ordner hinweg. - Übersichtliche Gruppierung nach Ordner ➔ Dokument ➔ Aufgaben mit einklappbaren Akkordeons und Zähler für offene Aufgaben.
- Ordner-Drilldown: Klick auf einen Ordner isoliert nur diesen Zweig für fokussiertes Abarbeiten, inklusive Zurücksetzen-Filter.
- Live 2-Wege-Sync: Abhaken oder Aktivieren eines To-Dos im Rollup synchronisiert direkt in Echtzeit zurück in die SQLite-Datenbank und die physische
.md-Datei auf Festplatte.
- Aggregierte Übersicht aller To-Dos (
- Aufgabenlisten-Teilen & Avatar-Stack (
TasksView.tsx,models.go,sqlite.go):- Aufgabenlisten können direkt mit Teams/Spaces geteilt werden.
- Avatar-Stack (farbige Initialen-Bubbles mit Hover-Tooltips) im Header der Liste und in den Tabs visualisiert, wem eine Liste gehört und mit welchen Teammitgliedern sie geteilt ist.
- Admin-Schalter für öffentliche Selbstregistrierung (
AdminSettingsView.tsx):- Unintuitiver Button in den Admin-Einstellungen unter Server & Isolation durch einen flüssig animierten Schiebeschalter (
rounded-pill) mit eindeutigen Status-Beschriftungen ersetzt.
- Unintuitiver Button in den Admin-Einstellungen unter Server & Isolation durch einen flüssig animierten Schiebeschalter (
- Cross-Browser & Performance Fixes (Chrome & Firefox):
- SQLite Connection-Pool Deadlock durch striktes Schließen von
sql.Rowsvor Unterabfragen behoben. Cache-Control: no-storeauf allen API-Routen undindex.html.- Optimistisches Leeren des Capture-Inputs und 12-Sekunden-Fetch-Timeout.
- SQLite Connection-Pool Deadlock durch striktes Schließen von
🎨 1. Single-File CSS Theming Engine & Design-System
Philosophie: 1 Datei = 1 komplettes Theme
Anstatt Styling in Dutzenden Tailwind-Klassen über hunderte Komponenten zu verstreuen, steuert eine einzige CSS-Datei das komplette Erscheinungsbild der Anwendung.
Jedes Theme liegt unter frontend/src/themes/ und gruppiert 6 standardisierte Bereiche:
:root[data-theme="dein-theme"] {
/* ==========================================================================
1. AKZENTFARBE (Fokus, Primäraktionen, Highlights)
========================================================================== */
--accent: #2563eb;
--accent-hover: #3b82f6;
--accent-dim: rgba(37, 99, 235, 0.15);
--accent-contrast: #ffffff;
/* ==========================================================================
2. OBERFLÄCHEN & HINTERGRÜNDE
========================================================================== */
--bg-canvas: #0e1013;
--bg-panel: #16181d;
--bg-panel-elevated: #1f2229;
--bg-input: #121418;
--bg-code: #0b0c0f;
--bg-overlay: rgba(0, 0, 0, 0.75);
/* ==========================================================================
3. TEXT & KONTRASTE
========================================================================== */
--text-main: #f4f4f5;
--text-muted: #a1a1aa;
--text-faint: #71717a;
--text-on-accent: #ffffff;
/* ==========================================================================
4. RAHMEN, LINIEN & SCHATTEN
========================================================================== */
--border-color: rgba(255, 255, 255, 0.08);
--border-strong: rgba(255, 255, 255, 0.18);
--shadow-panel: 0 4px 20px -2px rgba(0, 0, 0, 0.45);
/* ==========================================================================
5. STATUS- & SIGNALFARBEN
========================================================================== */
--status-ok: #22c55e;
--status-err: #ef4444;
--status-warn: #eab308;
--status-info: #3b82f6;
/* ==========================================================================
6. RUNDUNGEN / GEOMETRIE
========================================================================== */
--radius-card: 0px;
--radius-btn: 2px;
--radius-input: 2px;
--radius-checkbox: 2px;
--radius-pill: 9999px;
}
Verfügbare Themes
| Theme-ID | Datei | Charakter | Standard-Geometrie |
|---|---|---|---|
dark |
theme-dark.css |
Standard Monochrom / Dark Slate | Streng eckig (0px Cards, 2px Buttons) |
light |
theme-light.css |
Daylight Clean White / Minimalist Light | Modern sauber (4px Cards, 4px Buttons) |
high-contrast |
theme-high-contrast.css |
Reines Schwarz/Weiß mit maximaler Lesbarkeit (AAA Kontrast) | Streng eckig (0px, 2px Rahmen) |
soft |
theme-soft.css |
Soft Rounded Slate mit warmem Indigo-Akzent | Weich gerundet (12px Cards, 8px Buttons) |
| Template | theme-template.css |
Dokumentierte Vorlage zur Erstellung eigener Themes | Voll anpassbar |
Semantische Komponenten-Klassen (frontend/src/index.css)
.panel-surface/.panel-elevated: Automatisch über--radius-card,--bg-panelund--border-colorgesteuert..btn-primary/.btn-action: Aktionen und Buttons mit--radius-btn,--accentund--text-on-accent..input-field: Formularfelder mit--radius-input,--bg-input,--border-colorund--text-main..checkbox-square: Kontrollkästchen mit--radius-checkboxund--accent..badge-accent,.badge-neutral,.badge-ok,.badge-err: Pillen und Zähler..alert-ok,.alert-err: Hinweiskästen mit Signalfarben..capture-pill: Die markante Schnell-Eingabeleiste im Header mit--radius-pill.
🗄️ 2. Datenbank-Architektur (SQLite Schema & Tabellen)
MindSift speichert alle Daten lokal und hochperformant in SQLite (/data/mindsift.db).
Tabellen-Übersicht
usersid TEXT PRIMARY KEY,email TEXT UNIQUE,password_hash TEXT,display_name TEXTrole TEXT DEFAULT 'member'(admin,team_admin,member)is_active INTEGER DEFAULT 1,created_at DATETIME,updated_at DATETIME
system_settings(Instanzweite globale Konfiguration, 1 Row mitid = 'singleton')sharing_mode TEXT DEFAULT 'teams_only'(strict_private,teams_only,open)allow_registration INTEGER DEFAULT 0(Öffentliche Registrierung erlaubt oder gesperrt)instance_name TEXT DEFAULT 'MindSift'smtp_host TEXT,smtp_port INTEGER,smtp_user TEXT,smtp_pass TEXT,smtp_from TEXT,smtp_tls INTEGER
user_invites(Einladungscodes für neue Registrierungen)id TEXT PRIMARY KEY,code TEXT UNIQUE(MS-XXXXXXXX),email TEXT(optional gebunden)role TEXT DEFAULT 'member',team_id TEXT(optional direkte Team-Zuweisung)created_by TEXT,used_by TEXT,expires_at DATETIME,created_at DATETIME
organizations&organization_teams&team_members- Strukturierung von Benutzern in Abteilungen, Familien oder Projekt-Teams.
- Bildet die Basis für den Sichtbarkeits-Modus
teams_only.
spaces&space_members- Geteilte Kollaborations-Räume mit Einladungscode (
invite_code), Echtzeit-WebSocket Sync und Rollen (owner,editor,viewer).
- Geteilte Kollaborations-Räume mit Einladungscode (
shared_lists&list_items- Geteilte Einkaufs-, Pack- und Inventarlisten mit Kategorien, Mengen und Echtzeit-Abhaken.
tasks&task_lists- Persönliche und geteilte Aufgabenlisten mit Kanban-Spalten (
todo,in_progress,done), Fälligkeit, Priorität und Alarm-Optionen.
- Persönliche und geteilte Aufgabenlisten mit Kanban-Spalten (
quick_dumps(Triage-Deck)- Schnelle Einfälle (
status = 'inbox','discarded','converted'), Fälligkeitsdatum und Text-Notiz.
- Schnelle Einfälle (
documents(Workspace Markdown-Wiki)- Notizen und Dokumentationen mit Folder-Pfad (
folder_path), Tags, Pinned-Status, JSON-Blocks und physischer.md-Spiegelung auf Disk.
- Notizen und Dokumentationen mit Folder-Pfad (
user_alarms&user_webhooks- Multi-Channel Alarme (Mail, Discord, Webhook) und ausgehende Event-Webhooks.
⚡ 3. Triage & Quick-Dump State Machine
stateDiagram-v2
[*] --> InstantCapture: Gedanke eingetippt
InstantCapture --> QuickDump_Inbox: Enter (Standard)
InstantCapture --> TaskCreated: Ziel = 'task'
InstantCapture --> ListItemCreated: Ziel = 'list_item'
InstantCapture --> DocCreated: Ziel = 'document'
QuickDump_Inbox --> TriageDeck: Stapel sichten
TriageDeck --> Discarded: Swipe links / H (Wegwerfen)
TriageDeck --> TaskCreated: Swipe rechts / L (Als Aufgabe)
TriageDeck --> TaskCreated: T (Termin-Aufgabe)
TriageDeck --> DocCreated: D (In Notiz umwandeln)
TriageDeck --> ListItemCreated: Auf Liste schieben
TriageDeck --> QuickDump_Inbox: Leertaste (Später - ans Ende)
Discarded --> [*]
TaskCreated --> [*]
DocCreated --> [*]
ListItemCreated --> [*]
👥 4. Server-Administration & Isolation Modes
Der Server-Administrator (role = 'admin') legt unter AdminSettingsView.tsx global fest, wie Benutzer miteinander interagieren dürfen:
strict_private(Strikt Privat):- Jeder Benutzer arbeitet komplett autark. Keine teamübergreifende Benutzersuche, keine geteilten Spaces.
teams_only(Teams isoliert — Empfohlener Standard):- Benutzer sehen im Adressbuch und bei geteilten Spaces ausschließlich Personen, mit denen sie mindestens in einem gemeinsamen Team sind.
open(Offene Instanz):- Alle Benutzer können sich gegenseitig sehen, zu Spaces einladen und gemeinsam an Listen arbeiten.
📝 5. Workspace: Word/Notion-Toolbar, Wiki-Links & Disk-Sync
- 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%]).
- 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.
- Physische Speicherung auf Festplatte:
- Jede Notiz wird zusätzlich zur SQLite-Tabelle als reine
.md-Datei unter/data/workspace/<user_id>/<folder_path>/<slug>.mdgespeichert. - Ermöglicht jederzeitige manuelle Datensicherung, Git-Versionierung oder Backup-Extraktion ohne Datenbank-Abhängigkeit.
- Jede Notiz wird zusätzlich zur SQLite-Tabelle als reine
🛡️ 6. Kritische Backend-Regeln (SQLite & HTTP)
- NIEMALS verschachtelte Queries bei offenem
sql.Rows-Cursor ausführen:- In
internal/storage/sqlite.gomuss jede Schleifefor rows.Next()zuerst alle Zeilen in ein Slice einlesen und sofort_ = rows.Close()aufrufen, bevor Folgeabfragen (GetListItems,GetSpaceMembers,QueryRowetc.) ausgeführt werden.
- In
- 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)undMaxIdleConns(4)konfiguriert.
- Jede Verbindung im
- Thread-Safe Default User (
EnsureDefaultUser):- Durch
s.initMu.Lock()abgesichert, damit parallele Browser-Requests beim ersten Laden niemals in einenUNIQUE constraint-Konflikt laufen.
- Durch
- Kein Browser-Caching auf API &
index.html:writeJSONund der SPA-Fallback setzenCache-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)://<host>/api/v1/ws/spaces/:spaceId?token=<jwt>
Events
ITEM_CREATED(auch ausgelöst, wenn ein Gedanke per Direkt-Zuordnung oder Triage auf eine Liste geschoben wird)ITEM_TOGGLEDITEM_DELETEDLIST_CREATED/LIST_DELETED/LIST_CLEAREDUSER_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) |
Enter |
Workspace Outliner | Neuen Bullet-Point auf gleicher Ebene erstellen |
Tab |
Workspace Outliner | Bullet-Point einrücken (dem vorherigen unterordnen) |
Shift + Tab |
Workspace Outliner | Bullet-Point ausrücken (Ebene verringern) |
Shift + Enter |
Workspace Outliner | Weicher Zeilenumbruch innerhalb des aktuellen Blocks |
Backspace |
Workspace Outliner | Bei leerem Block: Ebene ausrücken bzw. Bullet löschen |
/ |
Workspace Outliner | Slash-Command-Menü öffnen (/todo, /h1, /code, etc.) |
🚀 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), der Frontend-Typecheck, Vite-Build und Go-Unit-Tests (go test -v ./...inkl.internal/api/server_test.go) direkt beim Image-Bau ausführt und bei Erfolg sofort pusht.