Citizen-Science-App für botanische Beobachtungen — föderierte App des mana e.V.-Ökosystems. Erste Vereins-App mit 3-Schicht-Datenmodell (Species/Specimen/Observation), 3-Stufen-GPS (exact/rounded_100m/ region_only) und fail-closed Sensitivity-Schutz für FFH-Anhang-IV- Arten. Stand η-0 (Plan v0.2 + Detail-Pass, Architect+Compliance-Audit 2026-05-17): - Workspace: pnpm/turbo/tsconfig/prettier - apps/api: Hono+Bun mit /healthz, /readyz, /healthz/details, /.well-known/mana-app.json. Smoke alle vier Endpoints grün. - apps/web: SvelteKit 2 + Svelte 5 + Tailwind v4, Herbarium-Theme, Landing-Page mit Phasen-Plan. svelte-check 0 errors / 0 warnings. - docker-compose: postgis/postgis:16-3.4 auf 5449, init-postgis.sql - app-manifest.json: validiert gegen @mana/shared-share-protocol@0.4.0 (2 shares, 2 accepts, 3 tools) - Doku: CLAUDE.md, README.md, STATUS.md Cross-Repo: @mana/shared-share-protocol@0.4.0 published mit 4 neuen Share-Types (mana/photo, mana/geo-point, mana/plant-observation, mana/plant-specimen). Plan: mana/docs/playbooks/HERBATRIUM_GREENFIELD.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9.2 KiB
CLAUDE.md — Herbatrium
Guidance für Claude Code in diesem Repo.
Wenn du gerade neu bist: lies zuerst
STATUS.md— dort steht der aktuelle Phasen-Stand. Dieses CLAUDE.md ist nur die Konventions- und Architektur-Referenz. Der vollständige Plan lebt in../mana/docs/playbooks/HERBATRIUM_GREENFIELD.md.
Was dieses Repo ist
Herbatrium — Citizen-Science-App für botanische Beobachtungen in
freier Natur. Föderierte App des mana e.V.-Ökosystems. Erste
Vereins-App mit 3-Schicht-Datenmodell (Species/Specimen/Observation),
3-Stufen-GPS-Sichtbarkeit (exact/rounded_100m/region_only)
und fail-closed Sensitivity-Schutz für FFH-Anhang-IV-Arten.
HTTPS ┌──────────────────┐
mana e.V. ◄─────────────── │ herbatrium/ │ Postgres + PostGIS
Plattform │ (this repo) │ herbatrium.mana.how
• mana-auth (JWKS) │ SvelteKit-Web │
• mana-llm (primär ID) │ + Hono-API │
• mana-media (Photos) └──────────────────┘
• mana-geocoding (Reverse) ▲
• mana-share/links/events │ HTTPS
• mana-mcp (Tools) │
┌─────────┴────────┐
│ Pl@ntNet API │
│ (AGPV / EU) │
│ Sekundär-Verifier│
└──────────────────┘
┌──────────────────┐
│ GBIF / IUCN / │
│ FFH-Listen │
│ (Sensitivity) │
└──────────────────┘
Status
Phase η-0 — Repo-Skelett (2026-05-17). Manifest + API/Web-
Boilerplate stehen, DB-Schema und Klassifikations-Pipeline noch nicht
implementiert. Roadmap siehe STATUS.md. Vollständiger
Plan in
../mana/docs/playbooks/HERBATRIUM_GREENFIELD.md.
Architektonische Invarianten
Beschlossen. Nicht ohne explizite Diskussion antasten.
- Fail-closed Sensitivity. Jede Species startet
is_sensitive=truebis ein erfolgreicher GBIF-IUCN/FFH-Lookup das Gegenteil belegt. Sensitive Specimens werden niemals mit 100 m-GPS public — nur als Region (admin_level=4, ~30–50 km). Verhindert BNatSchG-§44-Risiko. - Pl@ntNet-Outbound nur
display-Layer. Niemalsoriginal/mit GPS-EXIF an Drittdienste. Festgenagelt durch Compliance-Audit 2026-05-17. - mana-llm primär, Pl@ntNet sekundär (Verifier). Reihenfolge- Entscheidung 2026-05-17: LLM-Vision liefert Top-3 + Phenology in einem Pass; Pl@ntNet wird zugeschaltet bei niedrigem Confidence oder Sensitivity-Verdacht. Spart Quota.
- 3-Layer-Foto-Storage (original/display/thumb). Original
verlustfrei mit EXIF, Display EXIF-stripped 2048px, Thumb 512px.
Jeder Original-Access loggt in
photo_original_access_log. - Lizenz-Picker beim Publish, kein stiller Default. Default
license=null, beim Publish-Step explizit CC-BY-SA / CC-BY-NC / ARR wählen. Daten-Souveränität-Prinzip. - Eigene Postgres-DB
mana_herbatriummit PostGIS (Imagepostgis/postgis:16-3.4, Port 5449). Schema-Isolation viapgSchema('herbatrium'). - Server-authoritative MVP. Keine Dexie. Frontend = HTTP-Client. Local-First nachrüstbar via mana-sync in Phase η-9.
- Web ist SvelteKit 2 + Svelte 5 (runes), API ist Hono+Bun+ Drizzle. Plattform-Standard.
- Tier-Gate:
publiclesen,betaschreiben. Beta+alpha+founder dürfen Observations anlegen.
Stack
| Layer | Wahl |
|---|---|
| Web | SvelteKit 2 + Svelte 5 (runes) + Tailwind v4 |
| API | Hono + Bun |
| Datenbank | PostgreSQL + PostGIS + Drizzle ORM |
| Auth | JWKS aus mana-auth, ab η-1 |
| Föderation | @mana/shared-app-tpl ab η-5 |
| Klassifikation | mana-llm (primär) + Pl@ntNet (Verifier) |
| Geo | mana-geocoding, PostGIS ST_DWithin |
| Storage | mana-media (3-Layer: original/display/thumb) |
| Map | MapLibre + Cloudflare-Pull-through-OSM |
Ports: API 3101, Web 3102, Postgres 5449 (siehe
../mana/docs/PORTS.md).
Repo-Struktur
herbatrium/
├── apps/
│ ├── api/ Hono+Bun-Backend (Port 3101)
│ │ └── src/
│ │ ├── index.ts App-Boot
│ │ ├── routes/
│ │ │ ├── health.ts /healthz, /readyz, /healthz/details
│ │ │ └── manifest.ts /.well-known/mana-app.json
│ │ ├── db/schema/ Drizzle, pgSchema('herbatrium'), folgt η-1
│ │ ├── lib/ plantnet, gbif, photo-pipeline, …
│ │ ├── share-handlers/ save_photo_as_observation, …
│ │ └── middleware/ JWT, service-key
│ └── web/ SvelteKit-Frontend (Port 3102)
│ └── src/
│ ├── app.html, app.css (Herbarium-Theme)
│ ├── routes/
│ │ ├── +layout.svelte
│ │ └── +page.svelte Landing-Stub mit Phasen-Anzeige
│ └── lib/ api-clients, stores, components
├── packages/ leer, app-eigene Pakete später
├── infrastructure/
│ └── init-postgis.sql CREATE EXTENSION postgis (Container-Init)
├── docs/ repo-eigene Doks (PHOTO_PIPELINE, GPS_PRIVACY, …)
├── app-manifest.json Föderations-Manifest
├── docker-compose.yml lokales PostGIS :5449
├── STATUS.md aktueller Phasen-Stand
└── .github/workflows/ ci.yml
Föderations-Vertrag
Pflicht-Endpoints (alle ab η-5 via @mana/shared-app-tpl):
| Method | Path | Phase |
|---|---|---|
GET |
/healthz, /readyz, /healthz/details |
η-0 (jetzt) |
GET |
/.well-known/mana-app.json |
η-0 (jetzt) |
POST |
/api/v1/photos |
η-1 |
POST |
/api/v1/observations |
η-1 |
POST |
/api/v1/identify |
η-2 |
GET |
/api/v1/specimens?near=… |
η-3 |
GET |
/api/v1/public/feed |
η-4 |
POST |
/api/v1/share/receive |
η-5 |
POST |
/api/v1/tools/:name |
η-5 |
GET |
/api/v1/dsgvo/export |
η-5 |
POST |
/api/v1/takedown |
η-7 |
Konventionen
- pnpm 9.15.x, Node 20+, Turborepo 2.x, Bun für API-Runtime
- Tabs für Indent, single quotes, 100-col Prettier
- Drizzle 0.38 / drizzle-kit 0.30 (Plattform-Einklang)
- JWT-Validation lokal über JWKS-Cache (5 min), kein Live-Call
- Service-to-Service via
X-Service-Key(MANA_SERVICE_KEY) - Tests: Vitest
- PostGIS-Geometry-Felder: Drizzle
customType<{ data: string }>fürgeometry(Point, 4326)-Spalten
Sensitivity-Disziplin (Pflicht ab η-1)
Jeder species-Insert muss durch lib/gbif.ts (folgt η-2) gehen:
- GBIF-Match auf scientific_name → IUCN-Category (
CR/EN/VU/...) - FFH-Anhang-IV-Liste querchecken (statische Liste,
lib/ffh-list.ts) - Setzt
is_sensitive,iucn_category,ffh_annex_iv,sensitivity_source,sensitivity_resolved_at - Bei Fehler oder Timeout:
is_sensitive=truebleibt stehen (fail-closed)
Sensitive Specimens dürfen NIE mit GPS-Marker public sein — nur als Region-Cluster. Compliance-Audit hängt von dieser Disziplin ab.
Lokal entwickeln
pnpm install # @mana/* aus pkg.mana.how
docker compose up -d # PostGIS :5449
pnpm --filter ./apps/api dev # API :3101
pnpm --filter ./apps/web dev # Web :3102
Voraussetzungen:
- mana-Plattform-Stack lokal laufend (mindestens
mana-auth:3001;mana-llm,mana-media,mana-geocodingfür Klassifikation + Foto-Pipeline + Reverse-Geocode) - Verdaccio-Token in
~/.npmrc(npm login --registry=https://pkg.mana.how) - Pl@ntNet-API-Key in
.env.local(Sekundär-Verifier; ohne läuft die App, nur LLM-Klassifikation; siehe Playbook „Operative Helfer")
Wichtige Cross-Repo-Doks
../mana/docs/playbooks/HERBATRIUM_GREENFIELD.md— vollständiger Plan v0.2../mana/docs/FEDERATION.md— Architektur-Grundlage../mana/docs/PORTS.md— Port-Allokation../mana/docs/COMPLIANCE.md— DSGVO, BNatSchG, DSA../mana/docs/AGGREGATOR_POLICY.md— Drittdienst-Disziplin (Pl@ntNet-Geist)../mana/services/mana-llm/CLAUDE.md— primärer Klassifikator../mana/services/mana-media/CLAUDE.md— Foto-Storage../mana/services/mana-geocoding/CLAUDE.md— Reverse-Geocode