Backend
- Backup covers every Prisma model (bundle v3); a guard test fails for any
new model that is neither backed up nor explicitly excluded. Unsealed
bundles may only add rows to 27 legacy master/field tables and never
overwrite; counters, ledgers, settings, roles etc. need a sealed file.
Shared import limit BACKUP_MAX_IMPORT_BYTES (default 50 MB, max 256 MB)
with warnings in log and UI; replaced document files are removed after
commit.
- Post-commit side effects (automation, calendar sync, webhooks) run via
runAfterCommit and never turn a committed write into a 500, so retries
with the same Idempotency-Key no longer create duplicates.
- Calendar outbox is multi-replica safe: per-entry claims with stale
takeover, revision-based settle, new Graph event only on 404/410,
transactionId on create, 30 s Graph timeout, URL-encoded ids, GUID
validation for groupId, "run now" in background and resets FAILED.
- Automation tasks are deduplicated under a row lock on the rule.
- Update DTOs follow one null rule: omitted = unchanged, null clears a
nullable field, null on a required field is a 400.
- Varroa mites/day is recomputed on correction; withdrawal status is
checked against the harvest date (?at=), bounded colonyIds; inspection
create is audited; updates re-enqueue calendar entries.
- Dashboard, statistics and apiary/colony guards treat WEAK, CONSPICUOUS
and QUEENLESS colonies as living.
- Prisma errors and body-parser errors are logged without query values or
request bodies.
- Migration 20261012100000_calendar_sync_claims; schema index name aligned
with the existing database object.
Frontend
- Sticky save bar sticks again (no scroll container ancestors, card uses
overflow-clip), safe-area insets, scroll-padding, FAB hidden on forms,
sticky desktop sidebar.
- Inspections record yes / no / not checked instead of silent defaults.
- All living colonies are selectable; shared RecordSelect, EnumSelect,
ChoiceGroup and TriStateField replace per-page copies; selects show
names instead of ids; labels point at real controls.
- Emptied optional fields are sent as null (emptyToNull) so every field
can be cleared; dates default to the local day and are sent via
toApiDate.
- Harvest withdrawal warning uses the harvest date; backup page warns when
a backup outgrows the import limit and lists skipped tables.
Build and docs
- Docker builds fail unless lint, typecheck and unit tests pass.
- ARCHITECTURE.md updated (assumptions 9-12, 19-21, section 8) and spec
docs/superpowers/specs/2026-10-12-plattform-rueckgrat-und-fahrplan-design.md
for the backbone (api/worker/job roles, domain event outbox) and the
feature roadmap T3-T7.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
With {ART} in the raw material number format (default {ART}-{YYYY}-{SEQ:4}),
beeswax and propolis each count on their own: WA-2026-0001, PR-2026-0001.
Counters live in the new AutomationSequence table (one row per rule and
scope). Without {ART} the rule keeps its single shared counter, since
separate counters behind one prefix would hand out duplicate numbers.
Resetting a rule clears all of its counters.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
- RAW_MATERIAL_LOT_NUMBER_FORMAT / PRODUCTION_BATCH_NUMBER_FORMAT fill in the
lot number when it is left empty, like honey batches and bottlings.
- RAW_MATERIAL_LOW: task when the total of a raw material kind drops below
config.minGrams after consumption, withdrawal or inventory count.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Two new rules, "Kontrolle nach Behandlung" and "Kontrolle nach
Fütterung", create a check task when a treatment or feeding is recorded.
The due date counts from the measure itself (end of treatment, else its
date; feeding date) plus the configured number of days, and the task
names the product and date. At most one open check per colony and rule.
Both rules ship switched off and without an interval: the right timing
depends on the product (package leaflet) and season, so the beekeeper
sets it. Every task-creating rule can now carry a "due after N days"
setting in the automation page.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Data-integrity fixes found in a systematic review of ApiCore:
- Bottling booked the honey batch amount from a value read outside the
transaction and wrote an absolute result back, so two concurrent
bottlings (double tap, two devices) could both pass the check and one
deduction was lost. Bookings now use a conditional UPDATE inside the
transaction; corrections and deletions give amounts back atomically.
- Outgoing stock movements could drive stock below zero; the removal is
now a conditional decrement that refuses when stock is insufficient.
- Weak, conspicuous and queenless colonies were treated as "not active"
and could not be moved, split or merged - uniting a queenless colony
is the textbook merge. Only terminal statuses lock a colony now; merging
a colony into itself and dissolving twice are rejected.
- Moving a queen to another colony failed on the unique currentQueenId
because the old colony kept pointing at her. The old colony now releases
her (and becomes QUEENLESS); a queenless colony receiving a queen becomes
ACTIVE; dissolved colonies cannot receive a queen.
- Completing a task twice moved completedAt and re-sent the webhook;
reopening a task kept completedAt. Recurring templates created tasks
without a due date and caught up missed weeks one stale task at a time.
- Automation rules created a new task and warning on every trigger (every
stock removal below minimum). Tasks now record their source trigger and
at most one open task per rule and object exists. The varroa threshold
(mites per day) is only compared with natural-mite-fall rates, not with
sample-based counts in another unit.
- New opt-in Idempotency-Key support for record-creating endpoints, so
the offline queue can retry after a lost response without duplicates.
- Permission catalog sync crashed replicas booting concurrently on a
fresh database (unique violation); it now uses createMany/skipDuplicates.
- Server-side validation for inspection rating scales (1-5), unique
colony/harvest lists and net weight <= gross weight.
- Stale e2e expectations updated (permission count, trigger list, real PNG
fixture for the file-signature check).
Migration is additive only (nullable Task column, new table).
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
- SiteSettings gains websiteUrl (e.g. online shop link) alongside the
existing social links, editable in Verwaltung > Automatisierung.
- /herkunft/[lot] now shows the apiary's Standort instead of its internal
Name (so multiple apiaries at one location read as one origin), adds
small icons per social link, and surfaces previously-fetched-but-unused
data (Honigsorte, Abfülldatum, stat cards) to make the page a richer
customer-facing info page.
- Backup schedule (path/cron/retention) is now also configurable via the
GUI (Verwaltung > Backup), stored in a new BackupSettings singleton;
an env var always wins over the GUI value per field, and the scheduler
reloads its cron job live when GUI settings change.
- New Automatisierung rules let an admin define a format (e.g.
"WH-{YYYY}-{SEQ:4}") that auto-generates HoneyBatch.batchNumber and
BottlingBatch.lotNumber on creation, with an atomic per-rule sequence
counter and a manual reset. Manual entry still works when the rule is
inactive.
Neues AutomationModule mit AutomationRule-Modell (ein Row je Trigger-Typ,
per Unique Constraint erzwungen). Drei fest im Code hinterlegte Trigger,
die Admins nur aktivieren/deaktivieren bzw. deren Konfiguration/Aufgaben-
text anpassen können:
- QUEENLESS_NO_EGGS: Königin nicht gesehen UND keine Stifte vorhanden
(bei Durchsicht) → Kontrollaufgabe
- VARROA_THRESHOLD: Varroa-Schwellenwert überschritten (konfigurierbar,
Standard 10 Milben/Tag) → Behandlungsprüfung
- FEED_STATUS_CRITICAL: Futterstatus "kritisch" (bei Durchsicht) →
Fütterungsaufgabe
Jeder ausgelöste Trigger erzeugt eine Task UND eine Notification sowie
einen Audit-Log-Eintrag; Tasks lösen zusätzlich das bestehende
task.created-Webhook aus. InspectionsService und VarroaService rufen
die Auswertung direkt nach dem jeweiligen Erstellen auf.
Neue Endpunkte (nur Administrator): GET/PATCH /automation-rules.
Unit-Tests für AutomationService (alle drei Trigger, Deaktivierung,
Update mit Audit-Log) sowie E2E-Tests (Rollen-Check, alle drei Trigger
end-to-end über echte Inspection-/Varroa-Endpunkte, Deaktivierung
verhindert weitere Trigger). E2E-Suite zweimal hintereinander grün
verifiziert (Idempotenz der globalen Regel-Zeilen sichergestellt).
Migration auf Dev- und Test-Datenbank angewendet.