Files
pamietnik/README.md
Christoph K. a49416854e Remove nginx/webapp container; single Go server serves SPA + API
- Add root Dockerfile: node build → copy dist into Go embed path → distroless binary
- Update docker-compose: one service (api on :9050), DB renamed ralph→pamietnik
- Remove references to RALPH/reisejournal across all docs and configs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 10:32:04 +02:00

673 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Pamietnik ist eine Journal App (Android + Webapp + Go Server)
1. Zielbild
Die Applikation besteht aus folgenden Komponenten
- Backend in go programmiert mit Postgres DB und REST API
- Webapp, eine simple im schlichten design umgesetzte Web App
- Android app loggt Standortdaten im Background, cached offline, und lädt per HTTP backend
Fuer Nutzung ist ein Account und Login notwendig.
Das Backend soll basierend auf Logdaten Vorschläge für bestimmte Standorte machen (z. B. wenn man sich länger an einem Ort aufhält). Die Standortinformationen (Reverse-Geocoding/Place-Info) sollen über eine kostenlose API bezogen werden.
Es möglich sein, manuell Punkte hinzuzufügen (ohne GPS).
2. Festlegungen (Decisions)
DEC-CLIENT-01: Android (Kotlin), UI mit Jetpack Compose.
DEC-CLIENT-LANG-01: Android wird in Kotlin implementiert (Android „Kotlin-first").
DEC-LOC-01: Standortlogging im Background ist erforderlich.
DEC-API-01: Server-Schnittstelle ist HTTP/REST (MQTT verworfen).
DEC-DOC-01: Alle wesentlichen Inhalte werden in Markdown gepflegt; Diagramme in Mermaid.
DEC-DB-01: Android lokal/offline: SQLite (über Room); Backend: PostgreSQL.
DEC-WEB-01: Server bietet Website mit Login; Anzeige der Trackpoints pro Tag.
DEC-AUTH-01: Für die Website wird Session-basierte Auth (Session Cookie) bevorzugt; JWT ist optional für spätere Erweiterungen (z. B. API-first/SSO).
DEC-MAP-01: Für Kartenanzeige wird OpenStreetMap-Datenbasis genutzt, mit MapLibre als SDK/Renderer (Android) bzw. Web-Kartenbibliothek nach Wahl; Tile-Quelle wird konfigurierbar gehalten.
DEC-GEO-01: Für Reverse-Geocoding (kostenlos) wird initial Nominatim (OSM) eingeplant, aber nur mit striktem Caching/Rate-Limiting und „Provider austauschbar"-Design.
DEC-OPENAPI-01: Die Backend-HTTP-Schnittstelle wird als OpenAPI-Dokument gepflegt (OpenAPI 3.1, YAML oder JSON).
3. Produktanforderungen (PRD Requirements)
3.1 Background-Logging & Permissions
REQ-LOC-01: Die App MUSS Standort im Vordergrund und im Hintergrund erfassen können.
REQ-LOC-02: Manifest & Runtime: COARSE (und optional FINE) MUSS deklariert und zur Laufzeit angefragt werden; die App MUSS mit „approximate" funktionieren.
REQ-LOC-03: Background-Location: Für Hintergrundzugriff MUSS Background-Location berücksichtigt und korrekt angefordert werden (wenn Background-Logging aktiviert ist).
REQ-LOC-04: Falls Tracking als Foreground Service umgesetzt wird, MUSS beim Service der Location-Typ gesetzt werden (foregroundServiceType="location").
3.2 Offline-First, Upload bevorzugt
REQ-SYNC-01: Trackpoints MÜSSEN zuerst lokal persistiert werden (keine rein RAM-basierte Queue).
REQ-SYNC-02: Upload ist bevorzugter Weg; bei Server-Nichterreichbarkeit MUSS gecached werden und später automatisch nachgesendet werden (Retry).
REQ-SYNC-03: Hintergrund-Upload SOLL über WorkManager erfolgen, mit Constraints „Network connected" und Retry/Backoff.
REQ-SYNC-04: Retries dürfen keine Duplikate erzeugen; es MUSS eine Idempotenz-Strategie geben (event_id).
3.3 Manuelle Punkte
REQ-MAN-01: Die App MUSS es erlauben, manuell einen Punkt hinzuzufügen (mindestens: lat, lon, timestamp; optional: Name/Notiz).
REQ-MAN-02: Manuelle Punkte MÜSSEN lokal in SQLite/Room gespeichert werden, genauso wie GPS-Punkte.
REQ-MAN-03: Manuelle Punkte MÜSSEN in den Upload-Flow (Queue) integriert sein und zum Server hochgeladen werden (inkl. event_id).
REQ-MAN-04: Manuelle Punkte MÜSSEN validiert werden (z. B. Pflichtfelder, Wertebereich) und bei Fehlern im UI eine verständliche Fehlermeldung anzeigen; Validierung kann „as the user types" erfolgen.
REQ-MAN-05: Der Nutzer SOLL optional „aktuellen Zeitpunkt" und/oder „aktuelle Position" als Vorschlag übernehmen können, aber die Eingabe bleibt manuell editierbar.
3.4 Export (sekundär)
REQ-EXP-01: Nutzer MUSS Logs/Trips in eine Datei exportieren können.
REQ-EXP-02: Export MUSS über Storage Access Framework erfolgen (z. B. ACTION_CREATE_DOCUMENT; Nutzer wählt Speicherort, App schreibt in URI).
3.5 Server Website
REQ-WEB-01: Der Server MUSS eine Website bereitstellen, die nur nach Login zugänglich ist (Auth erforderlich).
REQ-WEB-02: Nach Login MUSS die Website pro Tag die gespeicherten Punkte anzeigen können (z. B. Tagesliste + Detailansicht eines Tages).
REQ-WEB-03: Die Website MUSS die Daten nutzerspezifisch anzeigen (ein Nutzer sieht nur seine eigenen Daten / Devices/Trips innerhalb seiner Berechtigung).
REQ-WEB-04: Die Website SOLL eine Kartenansicht bieten (zusätzlich zur Liste), um Punkte/Stops pro Tag visuell darzustellen.
3.6 Security / Auth
REQ-AUTH-01: Passwörter DÜRFEN nicht im Klartext gespeichert werden; Password Hashing MUSS sicher erfolgen (Argon2id bevorzugt).
REQ-AUTH-02: Session-basierte Auth (Cookie) ist erlaubt; Sessions SOLLEN serverseitig verwaltet werden, damit Sessions invalidierbar sind (Logout/Expire).
REQ-AUTH-03: Auth muss auch für Web-Query-Endpoints gelten (Tagesliste/Tagesdetail sind geschützt).
3.7 Vorschläge/Stops
REQ-SUG-01: Das Backend MUSS aus Trackpoints „Stops" erkennen können (Aufenthalte an ungefähr gleicher Position über eine Mindestdauer).
REQ-SUG-02: Das Backend MUSS aus Stops „Vorschläge" ableiten können.
REQ-SUG-03: Stops/Vorschläge MÜSSEN pro Nutzer/Device/Trip zuordenbar sein und in der Website pro Tag sichtbar sein (Liste + Karte).
3.8 Kostenlose Standortinfo-API
REQ-GEO-01: Reverse-Geocoding/Place-Info MUSS über einen kostenlosen Dienst erfolgen (initial Nominatim), mit Caching und klaren Limits/Retry-Strategie.
REQ-GEO-02: Geocoding-Provider MUSS austauschbar sein (z. B. via Server-Config/Proxy), ohne App-Update.
REQ-GEO-03: Bulk/periodische Reverse-Geocoding Requests SOLLEN vermieden werden; Geocoding wird bevorzugt ereignisbasiert (z. B. pro erkanntem Stop) und gecached.
3.9 Karten-Dienst
REQ-MAP-01: Kartenanzeige SOLL auf OpenStreetMap-Daten basieren; Rendering/SDK via MapLibre (Android) oder äquivalente Open-Source Web-Kartenkomponente.
REQ-MAP-02: Tile-Quelle MUSS konfigurierbar sein (später Self-hosting oder Provider-Wechsel möglich).
3.10 OpenAPI
REQ-OPENAPI-01: Die Backend-HTTP-Schnittstelle MUSS im OpenAPI-Format dokumentiert werden (OAS 3.1).
REQ-OPENAPI-02: Das OpenAPI-Dokument MUSS als YAML oder JSON im Repository versioniert werden (Entry-Point: openapi.yaml oder openapi.json).
REQ-OPENAPI-03: Das OpenAPI-Dokument MUSS alle implementierten Endpoints, Schemas (Request/Response), Fehlerformate und Security-Schemes enthalten.
REQ-OPENAPI-04: Cookie-basierte Auth für Web-Endpoints SOLL im OpenAPI über type: apiKey, in: cookie beschrieben werden (CookieAuth).
3.11 Google Play / Transparenz
REQ-PRIV-01: Bei Standortzugriff im Hintergrund MUSS eine klare In-App-Erklärung/Disclosure vorhanden sein; Background-Location ist zu begründen und sauber zu deklarieren.
3.13 Hashtags
REQ-TAG-01: Trackpoints und manuelle Punkte MÜSSEN mit einem oder mehreren Hashtags versehen werden können (z. B. `#restaurant`, `#aussicht`, `#hotel`).
REQ-TAG-02: Hashtags MÜSSEN lokal in SQLite/Room gespeichert und beim Upload zum Server übertragen werden (als Teil des Trackpoint-Schemas, Feld `tags: string[]`).
REQ-TAG-03: Der Server MUSS Hashtags persistieren und pro Trackpoint/Stop abfragbar machen.
REQ-TAG-04: Die Webapp MUSS eine Filteransicht bieten, die alle Trackpoints eines Tages oder Trips nach einem oder mehreren Hashtags filtert.
REQ-TAG-05: Hashtags SOLLEN bei der Eingabe in der App als Vorschläge angezeigt werden (aus bereits verwendeten Tags des Nutzers).
REQ-TAG-06: Die Webapp SOLL eine Tag-Übersicht bieten, die alle verwendeten Hashtags des Nutzers mit Häufigkeit auflistet.
3.12 Dokumentationsstil
REQ-DOC-STYLE-01: Alle wesentlichen Anforderungen, Architekturentscheidungen, API-Contracts, Testanforderungen und Tasks MÜSSEN in diesem Markdown gepflegt werden.
REQ-DOC-STYLE-02: Im Chat wird nur minimal kommentiert; Details stehen im Markdown.
REQ-DOC-STYLE-03: Änderungen erfolgen als fortlaufende Updates dieses Dokuments.
4. Architektur-Dokumentation (arc42-orientiert)
Die Architekturdokumentation MUSS Kontextsicht, Bausteinsicht, Laufzeitsicht und Verteilungssicht enthalten.
Alle Diagramme MÜSSEN Mermaid sein.
Architektur wird zuerst erstellt und abgestimmt, bevor Implementierung beginnt.
4.1 Kontextsicht
Fachlicher Kontext (Kommunikationspartner)
Benutzer mobil (startet/stopt Trips, sieht Status, exportiert, fügt manuell Punkte hinzu).
Benutzer web (loggt sich ein, sieht pro Tag Punkte/Stops/Vorschläge).
Android OS / Location Services (liefert Standortupdates).
Webserver (nimmt Trackpoints entgegen, berechnet Stops, stellt Website bereit).
Geocoding-Dienst (liefert Adress-/Place-Infos).
Dateisystem via SAF (Export-Ziel).
Technischer Kontext (Schnittstellen)
Android → Server: HTTPS/REST (JSON oder Protobuf, Entscheidung offen).
Browser → Server: HTTPS (Web UI, Login, Views).
Server → Geocoding: HTTPS (Reverse-Geocoding; Provider austauschbar, gecached).
Android → SAF: ACTION_CREATE_DOCUMENT und Schreiben in content:// URI.
text
flowchart LR
UserM[User Mobile] -->|Start/Stop Trip, Export, Manual point| App[Android App]
OS[Android Location Services] -->|Location updates| App
App -->|HTTPS REST: trackpoints| API[Go REST API]
API --> DB[(PostgreSQL)]
API -->|HTTPS reverse-geocode cached| GEO[Geocoding Provider]
UserW[User Web] -->|HTTPS| Web[Go Web UI]
Web --> API
App -->|SAF create document| SAF[Android Storage Access Framework]
SAF --> File[(Exported file)]
4.2 Bausteinsicht
Bausteine (initial):
Android App: UI (Compose), Domain/Use-Cases, Background Location Logging, Manuelle Punkt-Eingabe, Lokale DB + Upload-Queue, Upload Worker, Export, Map View (optional).
Go Server: REST Router/Handler, Validation, Idempotenz/Dedupe, Persistenz, Observability.
Go Web UI: Login, Tagesübersicht, Tagesdetail (Punktliste + Karte), Vorschläge.
Suggestion Engine: Stop Detection + Reverse-Geocoding + Vorschlagslogik.
Geocoding Adapter: Provider/Proxy + Cache/RateLimit.
text
flowchart TB
subgraph Mobile[Android App]
UI[Compose UI]
Domain[Domain / Use-Cases]
Loc[Background Location Logging]
Manual[Manual Point Entry + Validation]
Store[(SQLite/Room: Local DB + Upload Queue)]
Worker[Upload Worker]
Export[Export SAF]
UI --> Domain
Domain --> Loc
Domain --> Manual
Loc --> Store
Manual --> Store
Store --> Worker
Domain --> Export
end
subgraph Server[Go Server]
API[HTTP REST API]
Val[Validation]
Idem[Idempotency/Dedupe]
Auth[Auth users sessions]
Web[Web UI login day view map]
Suggest[Stop Detection + Suggestions]
Geo[Geocoding Adapter + Cache]
SDB[(PostgreSQL)]
API --> Val --> Idem --> SDB
API --> Suggest --> SDB
Suggest --> Geo
Geo -->|HTTPS| Provider[Geocoding Provider]
Web --> Auth
Web --> API
Auth --> SDB
end
Worker -->|HTTPS Batch Upload| API
4.3 Laufzeitsicht (Szenarien)
Szenarien:
R1: Trip starten → Background-Logging → Trackpoints in lokale DB.
R2: Offline → Queue wächst → Online → Batch Upload → Ack → Queue markiert als sent.
R3: Retry/Duplicate → gleiche event_id erneut → Server erkennt Duplicate → kein doppelter Insert.
R4: Export → Nutzer wählt Datei → App schreibt Export.
R5: Web Login → Tagesübersicht → Tagesdetail (Punktliste + Karte).
R6: Stop erkannt → Reverse-Geocoding (cached) → Vorschlag wird gespeichert → Web zeigt Vorschlag.
R7: Nutzer fügt Punkt manuell hinzu → Validierung → SQLite/Room persistiert → Queue pending → später Upload.
text
sequenceDiagram
participant U as User
participant A as Android App
participant L as Location Services
participant D as Local DB Queue
U->>A: Start Trip
A->>L: Request location updates
L-->>A: Location update trackpoint
A->>D: Persist trackpoint pending
text
sequenceDiagram
participant A as Android App
participant W as WorkManager Worker
participant D as Local DB Queue
participant S as Go REST API
W->>D: Fetch pending batch
W->>S: POST /v1/trackpoints:batch
alt Server unreachable timeout
S--xW: Network error
W->>D: Keep pending; schedule retry
else Success
S-->>W: Ack accepted_ids rejected[]
W->>D: Mark accepted as sent; keep rejected with reason
end
text
sequenceDiagram
participant B as Browser
participant W as Go Web UI
participant A as Auth sessions
participant API as Go REST API
participant DB as PostgreSQL
B->>W: GET /login
B->>W: POST /login username + password
W->>A: Verify credentials + create session
A->>DB: Load user + verify hash
A-->>W: Session created
W-->>B: Set-Cookie session + redirect
B->>W: GET /days
W->>API: GET /v1/days auth
API->>DB: Query days group filter by date
API-->>W: days[]
W-->>B: Render days view
B->>W: GET /days/yyyy-mm-dd
W->>API: GET /v1/trackpoints?date=YYYY-MM-DD
API->>DB: Query trackpoints for date
API-->>W: trackpoints[]
W-->>B: Render day detail
text
sequenceDiagram
participant W as WorkManager Worker
participant S as Go REST API
participant DB as PostgreSQL
participant SE as Suggestion Engine
participant G as Geocoding Adapter Cache
participant P as Geocoding Provider
W->>S: POST /v1/trackpoints:batch
S->>DB: Persist trackpoints
S->>SE: Trigger stop detection async
SE->>DB: Read recent points
SE->>G: Reverse-geocode stop if not cached
alt Cache hit
G-->>SE: Place info cached
else Cache miss
G->>P: HTTPS reverse-geocode
P-->>G: Place info
G-->>SE: Place info
end
SE->>DB: Persist stop + suggestion
text
sequenceDiagram
participant U as User
participant A as Android App
participant V as Validation ViewModel
participant D as SQLite Room Queue
participant W as Upload Worker
participant S as Go REST API
U->>A: Add manual point lat/lon/time/note
A->>V: Update fields as user types
V-->>A: Show validation errors or OK
A->>D: Persist trackpoint source=manual pending
W->>D: Fetch pending batch
W->>S: POST /v1/trackpoints:batch
S-->>W: Ack
W->>D: Mark sent
4.4 Verteilungssicht
text
flowchart LR
Phone[Android Device] -->|Internet HTTPS| Edge[Reverse Proxy LB optional]
Browser[Web Browser] -->|Internet HTTPS| Edge
Edge --> API[Go API Service REST + Web UI]
API --> DB[(PostgreSQL)]
API --> GEO[Geocoding Adapter Proxy + Cache]
GEO -->|HTTPS| Provider[Geocoding Provider]
5. HTTP API (REST) — Vertrag (Draft)
5.1 Ziele
Single-Point ingest und Batch ingest.
Idempotenz über event_id (mind. unique pro device).
Klare Acks für Queue-Weiterdrehen.
Web UI benötigt Tagesaggregation und Tagesdetail.
Vorschläge/Stops müssen abfragbar sein.
5.2 Endpoints (Vorschlag)
Ingest:
POST /v1/trackpoints (single)
POST /v1/trackpoints:batch (batch)
GET /healthz
GET /readyz
Web/Query:
GET /v1/days?from=YYYY-MM-DD&to=YYYY-MM-DD
GET /v1/trackpoints?date=YYYY-MM-DD
GET /v1/stops?date=YYYY-MM-DD
GET /v1/suggestions?date=YYYY-MM-DD
GET /v1/tags (alle Tags des Nutzers mit Häufigkeit)
GET /v1/trackpoints?tag=restaurant (Filter nach Hashtag)
Web UI Routes (serverseitig gerendert):
GET /login
POST /login
POST /logout
GET /days
GET /days/{yyyy-mm-dd}
5.3 Datenmodell (Draft)
Trackpoint:
event_id (string, client-generated; UUID empfohlen)
device_id (string)
trip_id (string)
timestamp (RFC3339 oder epochMillis, offen)
lat, lon (float)
source: "gps" | "manual" (optional; Default: gps)
note (string, optional; nur bei manuellen Punkten)
tags (string[], optional; Hashtags ohne #-Präfix, z. B. ["restaurant", "aussicht"])
optional: accuracy_m, speed_mps, bearing_deg, altitude_m
Stop:
stop_id
device_id, trip_id
start_ts, end_ts
center_lat, center_lon
duration_s
place_label (optional, aus reverse-geocode)
place_details (optional JSON)
Suggestion:
suggestion_id
stop_id
type (z. B. "highlight", "name_place", "add_note")
title/text
created_at
dismissed_at (optional)
Batch response:
server_time
accepted_ids (string[])
rejected (array of {event_id, code, message})
Day summary:
date (YYYY-MM-DD)
count (int)
first_ts, last_ts (optional)
5.4 Idempotenz-Regel
Unique Key: (device_id, event_id)
Duplicate: Server antwortet erfolgreich (z. B. 200) und behandelt es als „already processed".
5.5 Auth (Draft)
Website-Zugriff MUSS Login erfordern (Session Cookie).
API-Calls für Web UI müssen Auth prüfen (Session).
Android Upload Auth ist separat zu entscheiden (API-Key vs Bearer/JWT).
6. Auth: Session Cookie vs JWT
Session Cookie (session-basiert, stateful)
Vorteile:
Browser sendet Cookies automatisch mit; serverseitige Sessions sind gut kontrollierbar.
Sofortiger Widerruf möglich (Logout = Session löschen).
Nachteile:
Server muss Session-State speichern und über Instanzen verfügbar machen (z. B. Postgres/Redis).
JWT (token-basiert, stateless)
Vorteile:
Stateless pro Request; skaliert oft leichter für reine APIs/mehrere Services.
Gut für API-first/SSO/Verteilung.
Nachteile:
Widerruf/Revocation, Rotation und Lebensdauer-Management erhöhen Komplexität.
Empfehlung für Pamietnik
Website: Session Cookie.
JWT optional später, falls API-first/SSO nötig wird.
7. Testing (Requirements)
7.1 Use-Case Coverage
Alle wichtigen Use Cases (R1R7, plus Duplicate/Retry und Validierungsfehler) MÜSSEN automatisiert getestet werden.
7.2 Android Unit Tests
REQ-TEST-A01: Lokale JVM-Unit-Tests für Domain/Queue/Serializer/Retry-Entscheidungen.
REQ-TEST-A02: Unit Tests für Validierungslogik manueller Punkte.
7.3 Android Integration/Instrumentation (WorkManager)
REQ-TEST-A03: Integrationstests für Worker/Constraints/Delays mit WorkManager-Testunterstützung.
7.4 Go Unit & HTTP Handler Tests
REQ-TEST-S01: Go Unit Tests via testing (go test ./...).
REQ-TEST-S02: REST Handler Tests (inkl. /v1/days, /v1/trackpoints?date=…, /v1/stops, /v1/suggestions) mit net/http/httptest.
7.5 System-/Integrationstests (App ↔ Server)
REQ-TEST-I01: Integrationstest: Pending Queue → Batch Upload → Ack → Mark sent.
REQ-TEST-I02: Offline→Online-Wechsel: zuerst Fehler, später Erfolg.
REQ-TEST-I03: Duplicate event_id: gleicher Batch zweimal → keine Duplikate.
REQ-TEST-I04: Manual point → Queue → Upload → Ack (End-to-End).
7.6 Web UI Tests
REQ-TEST-W01: Login-Flow muss getestet werden (gültig/ungültig, Session created, Zugriffsschutz).
REQ-TEST-W02: Tagesansicht muss getestet werden (korrekte Tage, korrekte Punkte/Stops/Vorschläge pro Tag, AuthZ).
7.7 Geocoding/RateLimit Tests
REQ-TEST-GEO-01: Tests müssen sicherstellen, dass Reverse-Geocoding gecached wird und keine Bulk/periodischen Calls entstehen.
REQ-TEST-GEO-02: Provider-Wechsel muss testbar sein (Config umstellen → anderer Endpoint, ohne App-Update).
8. Backlog (Tasks)
8.1 Reihenfolge (wichtig)
T000: Architektur in diesem Dokument finalisieren (Kontext, Bausteine, Laufzeit, Verteilung) und abnehmen, bevor Implementierung startet.
T000e: Architektur-Review/Abnahme-Checkpoint (Issue/PR), erst danach Implementierungs-Tasks starten.
8.2 Android (Client)
T001: Compose-Projekt anlegen (Kotlin, minSdk festlegen).
T001a: Kotlin-Standards festlegen (Coroutines-Usage, KTX/Extensions, Code Style).
T004: Permissions im Manifest + Runtime-Flow (COARSE/FINE + Background).
T006: Background-Tracking Architektur (Provider/Manager/Service falls nötig).
T033: Android Persistenz: Room-Setup (Entities/DAOs/Migrations) auf SQLite-Basis.
T008: Lokale DB + Upload-Queue (pending/sent/failed, retryCount).
T012: Upload-Worker (Constraints Network connected, Retry/Backoff).
T018: Export via SAF ACTION_CREATE_DOCUMENT + Schreiben in URI.
T060: App-Kartenansicht (Track/Stops lokal anzeigen), SDK nach DEC-MAP-01 (optional).
T080: UI Screen/Flow „Manuellen Punkt hinzufügen" (lat/lon, timestamp, note optional).
T081: Eingabevalidierung in Compose (as the user types) + Fehlermeldungen.
T082: Persistenz: Manual-Point als Trackpoint in Room speichern, inkl. source=manual.
T083: Upload: Manual-Points in Batch/Single Upload einbeziehen (idempotent über event_id).
T084: Tests: Unit Tests für Validierung + Mapping; Integrationstest: Manual point → Queue → Upload → Ack.
Hashtags (Android):
T085: Room-Schema erweitern: tags-Feld (String-Array) in Trackpoint-Entity + Migration.
T086: UI: Hashtag-Eingabe in Compose (manueller Punkt + GPS-Punkt nachträglich taggen), Vorschläge aus vorhandenen Tags.
T087: Upload: tags-Feld in Batch-Payload einbeziehen.
8.3 Server (Go, HTTP + Web UI)
API / Persistenz:
T024: REST API finalisieren (Single + Batch, Fehlerformat, Limits).
T027: Persistenz: Postgres Schema + Migrationen + Indizes + Retention.
T028: Server-Idempotenz (unique event_id pro device).
T029: Observability (Logs/Metrics), Health/Ready.
T030: E2E lokal: docker compose (API + Postgres) + Minimal-Client zum Senden.
Auth / Website:
T050: User-/Auth-Konzept festlegen (User, Devices, Ownership, Session-Lifetime).
T051: Passwort-Hashing implementieren (Argon2id bevorzugt).
T052: Session-Management implementieren (Session-Store in Postgres, Cookie setzen, Logout/Invalidate).
T053: Web UI: Login-Seite (GET/POST), Zugriffsschutz (Middleware).
T054: Web UI: Tagesübersicht (GET /days) + Tagesdetail (GET /days/{date}) inkl. Karte.
T055: API: GET /v1/days und GET /v1/trackpoints?date=YYYY-MM-DD (Auth required).
T061: Stop Detection implementieren (Parameter: minDuration, radiusMeters; konfigurierbar).
T062: Suggestions implementieren (aus Stops ableiten; Storage + API).
T063: Geocoding Adapter + Cache + RateLimit + Provider-Wechsel implementieren.
T064: Web UI: Stops/Vorschläge pro Tag anzeigen (Liste + Karte).
OpenAPI:
T070: OpenAPI-Dokument anlegen (openapi.yaml als OAS 3.1) und im Repo versionieren.
T071: OpenAPI vollständig halten: alle Endpoints/Schemas/Responses/Errors/Security abbilden, inkl. CookieAuth für Web-API.
T072: OpenAPI in CI validieren (Spec-Validation) und Änderungen nur via PR.
Hashtags (Server + Webapp):
T073: DB-Schema: tags-Spalte (text[]) in trackpoints-Tabelle + Migration + Index (GIN für Array-Suche).
T074: API: tags in Ingest-Endpoints annehmen und speichern; GET /v1/tags (Häufigkeit) und GET /v1/trackpoints?tag=... implementieren.
T075: Webapp: Tag-Filter in Tagesdetail; Tag-Übersicht (/tags); Tags bei Trackpoints anzeigen.
T076: OpenAPI: tags-Feld in Trackpoint-Schema + neue Endpoints dokumentieren.
8.4 Tests
T040: Use-Case-Matrix (Use Case → Testart).
T041: Android Unit Tests (Queue/Serializer/Retry/Validation).
T042: Android WorkManager Integrationstests.
T043: Go Unit Tests (testing).
T044: Go HTTP Handler Tests (httptest).
T045: Integrationstests (E2E ingest + Ack + Dedupe).
T057: Web Login Tests (happy path + invalid creds + session required).
T058: Web Tagesansicht Tests (korrekte Tage, korrekte Punkte pro Tag, AuthZ).
T065: Stop/Suggestion Tests (synthetische Trackpoints → erwartete Stops/Vorschläge).
T066: Geocoding Cache/RateLimit Tests (keine Bulk Calls; Provider switch).
9. Offene Entscheidungen (Checklist)
timestamp Format: epochMillis vs RFC3339.
Android Upload Auth: X-API-Key vs Bearer/JWT (Web bleibt Session Cookie).
Payload: JSON vs Protobuf über HTTP.
Batch limits (max items, max bytes).
Server Retention-Policy (wie lange Trackpoints gespeichert werden).
Stop-Detection Parameter (min Dauer, Radius).
Karten-Tile-Provider (konkreter Anbieter/Hosting; muss austauschbar bleiben).
Geocoding Provider (konkret: Nominatim public vs self-hosted Nominatim vs alternative freie Provider); Nutzung muss Policy-konform sein.