MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
Remove outdated claims (CRDT, DocRooms, presence, .md files on disk) and document the actual architecture, API, permissions and known flaws. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
88 lines
5.3 KiB
Markdown
88 lines
5.3 KiB
Markdown
# Architektur
|
|
|
|
## Überblick
|
|
|
|
```
|
|
Browser (React SPA, PWA-Manifest)
|
|
│ REST /api/v1/* Authorization: Bearer <JWT | mindsift_sec_…>
|
|
│ WebSocket /api/v1/ws Fallback: SSE /api/v1/events
|
|
▼
|
|
Go-Server (chi) ── internal/api Handler, Middleware, Alarm-Ticker
|
|
│ internal/ws Hub (Räume, Benutzer-Kanäle, SSE)
|
|
│ internal/auth JWT, bcrypt, API-Key-Hash
|
|
▼ internal/config
|
|
SQLite (modernc.org/sqlite, WAL) ── internal/storage
|
|
```
|
|
|
|
Das Frontend liegt per `go:embed` im Binary ([cmd/server/main.go](../cmd/server/main.go)). Unbekannte Pfade liefern `index.html` (SPA-Routing); `index.html`, `sw.js` und `manifest.json` werden mit `no-store` ausgeliefert.
|
|
|
|
## Stack
|
|
|
|
| Schicht | Technik |
|
|
|---|---|
|
|
| Backend | Go 1.23, `go-chi/chi` v5, `go-chi/cors`, `gorilla/websocket`, `golang-jwt/jwt` v5, `x/crypto/bcrypt` |
|
|
| Datenbank | SQLite über `modernc.org/sqlite` (reines Go, kein CGO), WAL, `foreign_keys=ON` |
|
|
| Frontend | React 18, TypeScript, Vite 5, Tailwind 3, framer-motion (Triage-Karten), lucide-react, prismjs (Code-Blöcke) |
|
|
| Auslieferung | Mehrstufiges Dockerfile (Node 22 → Go 1.23 → Alpine 3.21), Image `git.dsit.me/sandrodach/mindsift` |
|
|
|
|
## Verzeichnisse
|
|
|
|
| Pfad | Inhalt |
|
|
|---|---|
|
|
| `cmd/server/` | `main.go`, eingebettetes `dist/` |
|
|
| `internal/api/` | `server.go` (Routen, Handler, Alarm-Ticker, SMTP/Discord/Webhook-Versand) |
|
|
| `internal/storage/` | `sqlite.go` (Schema, Migrationen, gesamte Datenlogik) |
|
|
| `internal/domain/` | Strukturen (`models.go`), ID-Erzeugung, Tag-Extraktion |
|
|
| `internal/ws/` | `hub.go` |
|
|
| `internal/auth/` | Tokens und Passwörter |
|
|
| `internal/config/` | Umgebungsvariablen |
|
|
| `frontend/src/features/` | `triage`, `workspace`, `lists`, `teams`, `settings`, `capture`, `auth`, `help` |
|
|
| `frontend/src/lib/` | `api.ts` (REST-Client, Transport-Umschaltung WS/SSE), `types.ts`, `markdown.tsx`, `theme.ts` |
|
|
| `frontend/src/themes/` | CSS pro Theme |
|
|
|
|
## Start und Laufzeit
|
|
|
|
1. `config.Load()` liest die Umgebung (siehe unten).
|
|
2. `storage.NewStore()` öffnet SQLite (`busy_timeout`, WAL, max. 8 Verbindungen) und führt `migrate()` aus.
|
|
3. SMTP-Werte aus der Umgebung werden in `system_settings` übernommen, sofern dort noch nichts steht.
|
|
4. Mit Demo-Flag legt `EnsureDemoAccounts` die Konten `admin/admin` und `user/user` an.
|
|
5. `api.NewServer` startet den **Alarm-Ticker** (jede Minute) und baut den Router. Server-Timeouts: Lesen 15 s, Schreiben 30 s, Leerlauf 60 s. Beim Beenden wird sauber heruntergefahren.
|
|
|
|
## Konfiguration
|
|
|
|
| Variable | Standard | Bedeutung |
|
|
|---|---|---|
|
|
| `PORT` | `8080` | HTTP-Port |
|
|
| `DATA_DIR` | `./data` (Container: `/data`) | Verzeichnis der Datenbank |
|
|
| `DATABASE_URL` | leer | `sqlite:///pfad/datei.db` oder Pfad; ohne Angabe `DATA_DIR/mindsift.db`. Postgres-URLs werden **nicht** unterstützt (siehe Hinweis) |
|
|
| `JWT_SECRET` | festes Fallback (unsicher!) | Signaturschlüssel der Tokens; unbedingt setzen, siehe [FLAW-04](flaws.md) |
|
|
| `BASE_URL` | `http://localhost:<PORT>` | Basis-URL der Instanz |
|
|
| `ALLOW_REGISTRATION` | `false` | Startwert; die Einstellung im Admin-UI (`system_settings`) hat Vorrang |
|
|
| `LOG_LEVEL` / `DEBUG` | `info` / `false` | `debug`, `info`, `warn`, `error`; `DEBUG=true` erzwingt `debug` |
|
|
| `MINDA_DEMO` (auch `MINDSIFT_DEMO`, `DEMO_MODE`) | `false` | Demo-Konten anlegen |
|
|
| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM`, `SMTP_TLS` | leer / `587` / `true` | Mailversand, auch im Admin-UI einstellbar |
|
|
|
|
Hinweis: `DATABASE_URL` mit `postgres…` führt dazu, dass der Standardpfad in `DATA_DIR` genutzt wird; Postgres ist nicht implementiert.
|
|
|
|
## Authentifizierung
|
|
|
|
- **Login** mit E-Mail, Benutzername (aus dem E-Mail-Präfix) oder `login`. Passwörter: bcrypt (`DefaultCost`).
|
|
- **JWT:** HS256, Laufzeit 30 Tage, Claims `userId`, `email`, `displayName`, `tokenVersion`, `jti`. Gültig nur, wenn Token nicht in `revoked_tokens` steht, das Konto aktiv ist und `tokenVersion` mit `users.token_version` übereinstimmt. `token_version` wird bei Passwortänderung, Rollenwechsel, Deaktivierung und „Alle Sitzungen beenden“ erhöht.
|
|
- **Logout** schreibt den Token-Hash in `revoked_tokens`.
|
|
- **API-Keys:** `mindsift_sec_<hex>`, gespeichert als SHA-256, nur das Präfix bleibt sichtbar. Der Key gilt als Bearer-Token oder in `X-API-Key` und authentifiziert als Besitzer ([FLAW-07](flaws.md)).
|
|
- **Registrierung:** nur mit Einladungscode oder wenn `allow_registration` aktiv ist. Das erste Konto entsteht über `/auth/setup` und wird Administrator.
|
|
|
|
## Hintergrundjob: Alarme
|
|
|
|
`startAlarmTicker` prüft jede Minute alle offenen, noch nicht gemeldeten Aufgaben mit Fälligkeit. Ist `due_date <= heute` (Serverzeit), sendet er über die Kanäle des Benutzers (`email`, `discord`, `webhook`) und setzt `alarm_sent`, sobald mindestens ein Kanal erfolgreich war. Details und Einschränkungen: [modules/tasks.md](modules/tasks.md), [FLAW-12](flaws.md).
|
|
|
|
## Build
|
|
|
|
```
|
|
Stage 1 node:22-alpine npm ci && npm run build → frontend/dist
|
|
Stage 2 golang:1.23 go vet, go test, go build → /app/mindsift (dist wird eingebettet)
|
|
Stage 3 alpine:3.21 nur Binary, ca-certificates, tzdata
|
|
```
|
|
|
|
Die Tests laufen beim Image-Build (`go test -v ./...`); ein Fehler bricht den Build ab. Frontend-Tests existieren nicht ([FLAW-19](flaws.md)).
|