# InkNote – Projektkonventionen für Claude Code Selbst gehostete Notiz-App, privat produktiv im Einsatz. Änderungen laufen auf echten Daten – im Zweifel erst fragen, nicht erst ausprobieren. Die ausführliche Beschreibung steht im [readme.md](readme.md); diese Datei hält nur fest, was beim Arbeiten gilt und sich nicht aus dem Code ergibt. ## Feste Regeln Diese Punkte sind Entscheidungen von Marc, keine offenen Fragen: - **Backend immer mit Docker starten**, nie mit `go run` o. Ä. `docker compose -f docker-compose.dev.yml up -d --build` - **Direkt auf `main` pushen.** Keine Feature-Branches, kein PR-Umweg. - **Kein Backup-Feature bauen.** Die Daten liegen über Bind-Mounts auf dem Host (`INKNOTE_DATA_DIR`, Standard `/srv/inknote`), und was den Host sichert – Proxmox Backup – sichert damit auch InkNote. - **Die Verschlüsselung bleibt.** Notizinhalte, Zeichnungen und hochgeladene Dateien liegen AES-256-GCM-verschlüsselt auf dem Server. Nichts davon entfernen, um etwas anderes einfacher zu machen. - **Keine öffentliche Registrierung.** Konten legt ein Administrator an. Ein Admin darf anlegen, löschen und Passwörter zurücksetzen – aber **keine** weiteren Admins ernennen und **keine** fremden Konten umbenennen. - **OIDC ist die zweite Anmeldeart, nicht die einzige.** Wer sich beim Anbieter anmelden darf, bekommt hier ein Konto (Marcs Entscheidung, 18.08.2026) – aber **nie** Admin-Rechte, die werden weiter nur in der App vergeben. Der Passwort-Login bleibt immer erreichbar, sonst sperrt ein kaputter Anbieter alle aus. Ohne `INKNOTE_OIDC_*` in der `.env` ist davon nichts zu sehen. - **Bundle-Größe bleibt, wie sie ist.** Bewusst so entschieden. - **Dashboard und Seitenleiste sind vertagt.** Die offenen Befunde dazu sind bekannt; nicht ungefragt damit anfangen. ## Tests Beides muss vor einem Push grün sein. ```bash # Unit (~4 s) docker run --rm -v "$PWD/frontend:/w" -w /w node:20-alpine npx vitest run # Browser, vierzehn Suiten – braucht den Dev-Stack ./e2e/run.sh # alle ./e2e/run.sh editor drawing # einzelne ``` Die Browser-Suiten melden sich mit Marcs Admin-Konto an (`INKNOTE_ADMIN` / `INKNOTE_ADMIN_PASS`, Standard `marc`/`geheim123`) und legen sich damit Wegwerf-Nutzer an. Sie laufen gegen `./data`, nicht gegen `/srv/inknote`. Screenshots landen in `e2e/shots/` und sind gitignored. `attachments-lifecycle` ruft `POST /admin/housekeeping` auf – das schreibt auf echten Daten. Nicht gegen die Produktionsinstanz laufen lassen. ## Ausliefern ```bash ./build.sh # baut beide Images und schiebt sie ins Gitea-Registry ``` Nur das Image bauen, das sich geändert hat. Nach dem Push den Digest bei der Registry gegenprüfen, nicht nur der Ausgabe von `docker push` glauben: ```bash docker buildx imagetools inspect gitea.honeyy.duckdns.org/docker/inknote-web:latest ``` Auf dem Server: `docker compose pull && docker compose up -d`. ## Änderungen festhalten Jede Runde, die als Image rausgeht, bekommt einen Eintrag in [CHANGELOG.md](CHANGELOG.md) – mit den Image-Digests, damit später nachvollziehbar ist, was auf dem Server läuft. Der `readme.md` beschreibt den *jetzigen* Stand und wird mitgeändert, wenn sich Verhalten ändert; das Changelog beschreibt den Weg dahin. ## Betrieb bei Marc InkNote läuft hinter **Pangolin** (Reverse Proxy mit eigener Anmeldung), über HTTPS, und wird am Handy als PWA auf **Android** genutzt. Daraus folgen drei Dinge, die bei PWA- oder Sync-Fehlern zuerst zu prüfen sind: - `/manifest.json` und `/sw.js` müssen die Datei liefern, nicht die Login-Seite des Proxys. Eine **Weiterleitung** auf `sw.js` lässt die Registrierung scheitern — dann gibt es weder Install noch Offline. - `/api/*` unverändert durchreichen, `/ws` mit WebSocket-Upgrade. - Jede UI-Änderung auch am Handy denken: Touch löst kein HTML5-Drag aus, und `onMouseEnter` gibt es dort nicht. ## Stil Der Code erklärt in Kommentaren das *Warum*, nicht das *Was* – oft mit dem Fehler, den die Zeile verhindert. Neue Kommentare in dem Ton, englisch wie der Rest. Die Oberfläche ist durchgehend englisch, das Gespräch mit Marc deutsch.