Kamerplanter verwendet ArangoDB als primäre Datenbank — ein Multi-Modell-System, das Dokument- und Graphdatenbank kombiniert. Alle Entitäten sind als Dokument-Collections organisiert; Beziehungen werden als Kanten-Collections im Named Graph kamerplanter_graph abgebildet.
Das Objektarray-Feld propagation_configs ist das kanonische Modell für die Vermehrung einer Art. Jeder PropagationConfig-Eintrag beschreibt eine Vermehrungsmethode mit eigenem Timing, eigener Holzreife, Schwierigkeit und Notizen — und ersetzt damit die früheren Flatfelder propagation_methods/propagation_months/propagation_notes. Teilfelder:
months (list[int], Wertebereich 1–12) — Monate, in denen diese Methode am besten geeignet ist; serverseitig dedupliziert und aufsteigend sortiert, unabhängig von den anderen Configs. Die art-weiten Aussaatzeiträume für die generative Vermehrung bleiben in den separaten Feldern direct_sow_months, indoor_start_months und transplant_months.
wood_stage (WoodStage \| null) — softwood / semi_hardwood / hardwood / herbaceous; nur für Steckling-Methoden relevant.
notes (string \| null, max. 1000 Zeichen) — fachlicher Freitext zu dieser Methode: typische Fehlerquellen, artspezifische Substrat- oder Temperaturanforderungen, Akklimatisierungsschritte.
Das Array ist optional in SpeciesCreate (Standard: leere Liste) und in SpeciesResponse immer vorhanden (leere Liste, wenn nicht gepflegt). Es ist für die meisten Arten in den Seed-Daten gepflegt.
Hinweis (abgekündigte Flatfelder): Die Flatfelder propagation_methods/propagation_months/propagation_notes sind zugunsten von propagation_configsabgekündigt. Alte Flatwerte werden weiterhin akzeptiert und beim Import adaptiert — eine Config je Methode, alle mit den gemeinsamen propagation_months, wobei propagation_notes nur an die erste Methode angehängt wird. Neue Daten verwenden propagation_configs.
Das Objektfeld toxicity erfasst die Giftigkeit einer Art getrennt für Katzen, Hunde und Kinder (is_toxic_cats/is_toxic_dogs/is_toxic_children), die betroffenen Pflanzenteile (toxic_parts), die verantwortlichen Wirkstoffe (toxic_compounds) sowie den Schweregrad (severity: none/mild/moderate/severe). allergen_info ergänzt Kontakt- und Pollenallergen-Flags. Das flache Passthrough-Feld toxicity_severity (low/moderate/high) bleibt aus historischen Daten erhalten und wird nicht auf toxicity.severity gemappt. Alle Felder sind optional (null, wenn nicht gepflegt).
Das Objektfeld seed_profile bündelt echte Saatgut-/Keim-Metadaten für samenvermehrte Arten: Keimtemperatur-Bereich (germination_temp_min_c/_max_c), Saattiefe (sowing_depth_cm), Tage bis Keimung (days_to_germination), Keimfähigkeitsdauer (seed_viability_years), Licht-/Dunkelkeimung (light_germination: light/dark/indifferent), Vorbehandlung (pretreatment: cold_stratification/warm_stratification/scarification/presoak), Tausendkornmasse (thousand_seed_weight_g) und Aussaatdichte (sowing_density_per_m2). Alle Felder sind optional; rein vegetativ vermehrte Arten lassen das Objekt leer (null).
Kamerplanter legt beim Start automatisch folgende Indizes an:
Collection
Index-Feld
Typ
Eindeutig
species
scientific_name
Persistent
Ja
botanical_families
name
Persistent
Ja
slots
slot_id
Persistent
Ja
plant_instances
instance_id
Persistent
Ja
users
email
Persistent
Ja
tenants
slug
Persistent
Ja
memberships
user_key, tenant_key
Persistent
Ja
fertilizers
product_name, brand
Persistent
Ja
harvest_batches
batch_id
Persistent (sparse)
Ja
tanks
name
Persistent
Ja
refresh_tokens
token_hash
Persistent
Ja
calendar_feeds
token
Persistent
Ja
tasks
status, plant_key
Persistent
Nein
feeding_events
plant_key, timestamp
Persistent
Nein
Sparse-Indizes
Ein als sparse markierter Index berücksichtigt nur Dokumente, in denen das Feld tatsächlich gesetzt ist. Bei harvest_batches.batch_id ist das erforderlich, weil die Chargen-ID ein optionales Feld ist: Leere Eingaben werden auf null normalisiert, und beliebig viele Chargen dürfen gleichzeitig ohne Chargen-ID existieren, während gesetzte Kennungen weiterhin eindeutig bleiben müssen. Bestandsdaten werden von Migration v0030 angepasst (leere Zeichenketten → null, Index-Neuanlage als unique + sparse).
Alle mandantengebundenen Ressourcen tragen ein tenant_key-Feld. Der FastAPI-Dependency require_permission() prüft beim Zugriff automatisch, ob der anfragende Nutzer Mitglied des entsprechenden Mandanten ist.