Platform backbone (plan 2026-10-13-plattform-rueckgrat), reviewed tasks:
- run roles api/worker/job/all with shared startup checks (Task 1)
- schema and migration for DomainEvent, deliveries, JobRun, ThrottlerHit (Task 2)
- audit, notifications and domain events written in the same transaction (Task 3)
- dispatcher with SKIP LOCKED claims, retries and stale release (Task 4)
- worker building blocks: tick, LISTEN/NOTIFY wake-up, health (Task 5)
- worker process and entry points (Task 6)
- throttler counters in Postgres (Task 19)
- separate keys per purpose with key ring (Task 20)
- public origin page without exact location (Task 22)
- shop keys split into read and write (Task 23)
- Kustomize base, components, overlay encry, CI validation (Task 26)
Field capture T3 (plan 2026-10-13-t3-erfassung-am-stand), reviewed tasks:
- brood frames, read endpoints, apiary overview and offline pack
- network basics, offline queue v3, navigation sheets, form building blocks
- new inspection with last-time hints and weather, varroa per day,
treatment prefill, apiary page with round
- inspection photo (Task 10) is implemented, review pending
Not rolled out. Remaining tasks follow in later commits.
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]>
Letzte Phase des RBAC-Umbaus: die transitionale Rollen-Infrastruktur,
die seit Phase 1 parallel zum neuen Role/Permission-System mitlief,
ist jetzt komplett weg.
- Prisma-Migration: User.legacyRole-Spalte und LegacyRole-Enum
gedroppt (nichts liest die Spalte mehr, seit Phase 2 jeder Controller
auf @RequirePermission laeuft).
- roles.guard.ts, roles.guard.spec.ts, roles.decorator.ts geloescht;
RolesGuard aus den APP_GUARD-Providern entfernt.
- AuthenticatedUser/JWT-Payload verlieren das role-Feld (permissions
werden ohnehin frisch pro Request aus der DB aufgeloest, nicht aus
dem Claim).
- Users-API: CreateUserDto/UpdateUserDto akzeptieren jetzt roleId
(eine echte Role.id) statt der alten role-Enum-Werte; UsersService
validiert, dass die Rolle existiert und aktiv ist, bevor sie
zugewiesen wird.
- Alle 34 e2e-Fixtures und der Seed-Script folgen dem neuen Schema.
Verifiziert: tsc, lint, build, unit (220/220), volle e2e-Suite
159/159 gruen - keine uebersprungenen Tests.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Replaces the fixed 5-value Role enum with a database-driven Role/Permission
model: admins can create custom roles with a precise per-resource/action
permission set (83-key code-owned catalog), instead of being locked to
ADMIN/BEEKEEPER/STAFF/READONLY/API_CLIENT.
- New Role/Permission/RolePermission tables; legacy Role enum renamed to
LegacyRole and kept as User.legacyRole so all existing @Roles() call
sites keep working unchanged during the migration.
- New RolesController/RolesService (CRUD, permission-set editing,
deactivate/reactivate) with lockout-prevention invariants: system roles
(ADMIN) can't be edited or deactivated, and a role still assigned to
users can't be deactivated.
- New PermissionResolverService (30s-cached, DB-fresh per user) and
PermissionsGuard + @RequirePermission(), registered as an additional
APP_GUARD alongside the legacy RolesGuard so both systems run
side-by-side until controllers are migrated in Phase 2.
- PermissionCatalogSyncService seeds any new catalog entries into the DB
on boot, so future features only touch the TS catalog.
- New GET /auth/me returns the caller's role and effective permissions.
- Migration hand-written (destructive column rename) with grants derived
from a fresh grep of every existing @Roles() call site, verified
against 5 controllers read in full for STAFF's exact write boundary.
- test/roles.e2e-spec.ts covers the new endpoints and invariants end to
end; test/authorization-coverage.e2e-spec.ts added but skipped until
Phase 2 gives every controller a @RequirePermission.
Co-Authored-By: Claude Sonnet 5 <[email protected]>