herbatrium/CLAUDE.md
Till JS 214b852f99
Some checks are pending
CI / validate (push) Waiting to run
η-0: Repo-Skelett
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>
2026-05-17 18:10:20 +02:00

9.2 KiB
Raw Permalink Blame History

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.

  1. Fail-closed Sensitivity. Jede Species startet is_sensitive=true bis ein erfolgreicher GBIF-IUCN/FFH-Lookup das Gegenteil belegt. Sensitive Specimens werden niemals mit 100 m-GPS public — nur als Region (admin_level=4, ~3050 km). Verhindert BNatSchG-§44-Risiko.
  2. Pl@ntNet-Outbound nur display-Layer. Niemals original/ mit GPS-EXIF an Drittdienste. Festgenagelt durch Compliance-Audit 2026-05-17.
  3. 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.
  4. 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.
  5. 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.
  6. Eigene Postgres-DB mana_herbatrium mit PostGIS (Image postgis/postgis:16-3.4, Port 5449). Schema-Isolation via pgSchema('herbatrium').
  7. Server-authoritative MVP. Keine Dexie. Frontend = HTTP-Client. Local-First nachrüstbar via mana-sync in Phase η-9.
  8. Web ist SvelteKit 2 + Svelte 5 (runes), API ist Hono+Bun+ Drizzle. Plattform-Standard.
  9. Tier-Gate: public lesen, beta schreiben. 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ür geometry(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=true bleibt 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-geocoding fü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