feat: Sprachnotizen übernehmen, melden und abschreiben (T7 L2 Tasks 8, 9, 11)
Backend Image / build-and-push (push) Successful in 6m51s
Frontend Image / build-and-push (push) Successful in 18m9s

Task 8: POST /inspections nimmt voiceCaptureId; die Notiz wird zuletzt
in derselben Transaktion bestätigt (jeder offene Status, Ruling 1),
Inhalt, Audio und Claim gelöscht; fremde oder geschlossene Notiz 409
VOICE_CAPTURE_GONE, anderes Volk 409 VOICE_CAPTURE_COLONY_MISMATCH;
Wiederholung mit gleichem Schlüssel idempotent.

Task 9: Ereignisse VoiceCaptureReady/VoiceCaptureFailed (nur IDs und
Endcodes), Meldungen „Sprachnotiz für … ist fertig“ bzw. Fehlerhinweis
mit nächstem Schritt, Betreiberhinweis bei abgeschalteter Auswertung;
Handler auch im Worker registriert (sonst gingen die Ereignisse
ungehört durch); keine Weiterleitung an Webhooks.

Task 11: Job voice-transcribe mit Phasen fetch (Audio nur im Speicher
entschlüsselt in ein RAM-Arbeitsverzeichnis 0700/0600) und ingest
(Ergebnis gegen Claim geprüft, Transkript versiegelt, Audio gelöscht,
Auswertung geweckt; Stille/zu lang enden FAILED); Ereignisse genau
einmal in derselben Transaktion. Aufbewahrung: Audio 24 h, Inhalt bis
contentExpiresAt, deaktivierte Besitzer, Zeilen 90 Tage; im täglichen
Cleanup inkl. leerer Job-Läufe (Ruling 10).

Gates: Backend lint, typecheck, 4471 Unit-Tests, build; e2e 103 Suites
(einziger Fehler: Wetter-Test gegen echte API).

Refs #27

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-10-16 10:38:14 +02:00
1 parent e9c6604e3b
commit 1dc39f7658
35 files changed
+2886 -27

No files matched your search

@@ -87,7 +87,7 @@ describe('WebhookEventHandlers', () => {
});
});
it('none of the five new events is forwarded to webhooks', async () => {
it('none of the herd and voice events is forwarded to webhooks', async () => {
const herdEvents = [
['ColonyCreated', { apiaryId: 'a1' }],
['ColonyMoved', { fromApiaryId: 'a1', toApiaryId: 'a2' }],
@@ -97,6 +97,8 @@ describe('WebhookEventHandlers', () => {
'HiveChanged',
{ colonyId: 'c1', version: 2, source: 'CARD', inspectionId: null },
],
['VoiceCaptureReady', { captureId: 'v1', colonyId: 'c1' }],
['VoiceCaptureFailed', { captureId: 'v1', code: 'NO_SPEECH' }],
] as const;
for (const [type, payload] of herdEvents) {
expect(Object.keys(DOMAIN_EVENT_WEBHOOKS)).not.toContain(type);