Zum Hauptinhalt springen
Version: 0.3.0

Datenmodell

Die Tabellen unten stammen aus den Server-Migrationen (server/internal/storage/sql/migrations/) und dem Spiegelschema des Clients (app/src/lib/local/schema.ts). Die Spaltennamen sind auf beiden Seiten identisch und sind die Schlüssel in den Sync-Payloads. Enum-Spalten speichern die Proto-Nummer; das Anzeigelabel ist das, was die App zeigt (app/src/lib/i18n/locales/en.json).

Jede synchronisierte Tabelle trägt drei Verwaltungsspalten, die unten nicht wiederholt werden: organization_id (Mandant), field_hlc (JSON-Feld-Uhr, siehe Sync-Protokoll) und deleted (Soft-Delete-Flag). Ids sind UUIDs, die auf dem Gerät erzeugt werden oder, bei Zeilen, die über die API angelegt werden, vom Server. Zeitstempel werden auf dem Client als ISO-8601-Strings und auf dem Server als TIMESTAMP gespeichert.

Hierarchie​

apiary
└── hive ── queen (one active, older ones kept with replaced_at set)
├── inspection
├── task (task.hive_id and task.apiary_id are both optional)
├── harvest
├── treatment
├── placement (which apiary the hive lived in, and when)
└── event (append-only history with frozen apiary/hive/queen)

Freigabe und Sync-Partitionierung nutzen scope_id: die eigene Id eines Standorts für den Standort und alles darunter. Nur event speichert scope_id als Spalte; bei den anderen Tabellen wird sie in der Change-Message mitgeführt.

apiary​

SpalteTypHinweise
idtext
nametextPflichtfeld
addresstextFreitext
lat, lngreal0, wenn nicht gesetzt
notetext
created_at, updated_attimestamp

hive​

SpalteTypHinweise
idtextauch im QR-Etikett kodiert
apiary_idtextaktueller Standort
nametext
typeintHiveType, siehe unten
statusintHiveStatus, siehe unten; neue Beuten starten mit 1
boxesintAnzahl der Zargen
colony_origintextz. B. "Schwarm 2024"
notetext
qr_codetextreserviert; der gedruckte Code wird von shortCode() in app/src/lib/qr.ts aus id abgeleitet
phototextData-URL oder Blob-Schlüssel
created_at, updated_attimestamp

HiveType: 0 Unbestimmt, 1 Zander, 2 Dadant, 3 Deutsch Normal, 4 Langstroth, 5 Warré, 6 Top-Bar, 99 Sonstige.

HiveStatus: 0 Unbestimmt, 1 Aktiv, 2 Ableger, 3 Weisellos, 4 Verloren, 5 Aufgelöst.

queen​

SpalteTypHinweise
idtext
hive_idtext
yearintdas Jahr der Königin; bestimmt die Standard-Markierungsfarbe
markingintMarkingColor: 1 weiß (Jahre auf 1/6), 2 gelb (2/7), 3 rot (3/8), 4 grün (4/9), 5 blau (5/0); Vorgabe aus year
origintext
breeder_numbertext
introduced_attimestampBeginn der Regentschaft
replaced_attimestampEnde der Regentschaft, null solange sie regiert
activebooltrue für die aktuelle Königin
notetext
created_at, updated_attimestamp

Ein Königinnenwechsel setzt active = 0 und replaced_at auf der alten Zeile und fügt eine neue ein; alte Königinnen werden nie gelöscht.

inspection​

SpalteTypHinweise
id, hive_idtext
datetimestamp
weathertext
queen_seen, eggs_seenbool
temperamentint1 Sehr sanft, 2 Sanft, 3 Normal, 4 Nervös, 5 Aggressiv
calmnessint1 Läuft ab, 2 Unruhig, 3 Ruhig, 4 Sehr ruhig
framesintbesetzte Waben
brood_framesint
storesint1 Gut, 2 Mittel, 3 Wenig, 4 Keines
queen_cellsintgezählte Schwarmzellen
youngest_larvaintAlter in Tagen der jüngsten gesehenen Larve
covered_larvaboolverdeckelte Brut gesehen
varroatext
honey_kg, fed_kg, weight_kgreal
frames_added, frames_removedint
drone_frame_cut, super_addedbool
temp_hive, temp_outsidereal°C, null wenn in der App nicht gemessen; CreateInspection speichert 0 für weggelassene Felder
humidity_hive, humidity_outsidereal%, gleiche Regel wie bei den Temperaturen
notetext
photo_keystextOR-Set-JSON, die einzige Mengenspalte
created_attimestamp

task​

SpalteTypHinweise
idtext
titletext
hive_id, apiary_idtextoptional
due_attimestamp
donebool
priorityintTaskPriority: 1 Niedrig, 2 Normal, 3 Hoch; die Server-Spalte hat Vorgabe 2, die App schreibt 0
note, recurrence, assigned_totextim Schema vorhanden; das Aufgabenformular füllt nur title und due_at
created_attimestamp

placement​

SpalteTypHinweise
id, hive_id, apiary_idtext
start_attimestamp
end_attimestampnull für das aktuelle Placement

Das Anlegen einer Beute eröffnet ein Placement; das Wandern schließt die offene Zeile zum Wanderzeitpunkt und eröffnet eine neue.

Eine Aufgabe ohne apiary_id synchronisiert unter dem persönlichen Scope user:<user id> statt unter einer Standort-Id.

harvest​

SpalteTypHinweise
idtext
apiary_id, hive_id, queen_idtextzum Erntezeitpunkt eingefroren
datetimestamp
varietytext
amount_kgreal
water_contentreal%
batch_numbertext
best_beforetimestamp
notetext

treatment​

SpalteTypHinweise
idtext
apiary_id, hive_id, queen_idtextzum Behandlungszeitpunkt eingefroren
datetimestamp
product, active_ingredienttext
dose, methodtext
batch_numbertext
withdrawal_untiltimestamp
reasontextVorgabe varroa
notetext

event​

SpalteTypHinweise
idtext
scope_idtextStandort-Id
typeintEventType, siehe unten
datetimestamp
apiary_id, hive_id, queen_idtextzum Event-Zeitpunkt eingefroren
ref_entity, ref_idtextdie Detailzeile, z. B. harvest / ihre Id
titletext
amount_kgrealaus der Ernte kopiert, damit Ertragsabfragen keinen Join brauchen
detailtextJSON
author_idtext

EventType: 1 Angelegt, 2 Königin eingesetzt, 3 Königin ersetzt, 4 Gewandert, 5 Durchsicht, 6 Behandlung, 7 Ernte, 8 Status, 9 Aufgelöst. Die App schreibt die Typen 1 bis 7 (app/src/lib/local/history.ts). Siehe Historie und Events.

Tabellen nur auf dem Server​

organization, users, member, invite, user_passkey, api_key, apiary_share, change_log und seq_counter existieren nur auf dem Server. member.role ist owner oder member; users.role ist admin oder user. apiary_share wird von der Sync-Scope-Prüfung gelesen, aber nichts in der App schreibt sie. Der Client ergänzt outbox und sync_meta für die Sync-Engine.

api_key​

Langlebige Schlüssel für Skripte und Integrationen (Migration 0014_api_keys.sql, server/internal/auth/apikey.go). Nicht synchronisiert.

SpalteTypHinweise
idtext
user_idvarchar(64)Besitzer; indiziert
organization_idvarchar(64)der Mandant, in dem der Schlüssel handelt, beim Erstellen festgelegt
nametextBezeichnung, die in den Einstellungen angezeigt wird
key_prefixtextdie ersten 12 Zeichen des Klartexts, für die Anzeige
key_hashvarchar(64)hex-SHA-256 des Klartext-Tokens obhk_..., eindeutig; der Klartext wird nie gespeichert
scopetextwrite (Vorgabe) oder read; ein read-Schlüssel darf nur Get*, List*, Pull und Subscribe aufrufen
created_attimestamp
expires_attimestampnull für Schlüssel, die nie ablaufen; ein Schlüssel nach diesem Zeitpunkt wird abgelehnt
last_used_attimestampbei jeder erfolgreich geprüften Verwendung aktualisiert, bis dahin null

Ein Schlüssel wird geprüft, indem das Bearer-Token gehasht und key_hash nachgeschlagen wird; beim Entfernen wird die Zeile gelöscht, und ein Schlüssel, dessen Besitzer kein member von organization_id mehr ist oder dessen expires_at verstrichen ist, wird abgelehnt, ohne gelöscht zu werden.