| R1 | Auto-OOO loops if property-service rejection event itself triggers re-creation of WO that re-emits block | 3 | 4 | 12 | Idempotent inbox dedupe; block_rejected handler clears causedRoomBlock and does NOT re-emit; integration/room_block_rejected.spec.ts | 4 | Tech lead |
| R2 | Vendor no-show with active reservation leaves room OOO indefinitely | 4 | 4 | 16 | Auto-escalation to GM after N reminders; manual override path; UI surfaces "guest waiting" badge | 6 | Product |
| R3 | Preventive scheduler stops firing silently due to worker crash loop | 3 | 5 | 15 | Liveness/readiness probes; mnt.preventive.due_pending_count alert > 50 for 5 min; second worker replica | 4 | SRE |
| R4 | Cross-tenant data leak through forgotten tenant_id filter | 2 | 5 | 10 | RLS as last-line defence; tenant-isolation.spec.ts mandatory; lint rule no-unscoped-repository-call; PR review checklist | 2 | Security |
| R5 | Cost-currency mismatch at scale (multi-currency tenants) leading to wrong cost rollups | 3 | 4 | 12 | Domain invariant #5 rejects mismatch; tenant base currency resolved per request and asserted | 3 | Domain owner |
| R6 | Outbox lag spike under burst load (e.g., mass preventive fan-out) blocks downstream services | 3 | 4 | 12 | Outbox relay scales; mnt.outbox.lag_seconds alert at 60 s; preventive scheduler batch-size cap | 6 | SRE |
| R7 | Lock-device alert storm floods us with WOs (e.g., entire BLE mesh dropping) | 3 | 4 | 12 | Per-device dedupe (deviceId, alertCode, dayBucket); per-property cap on auto-create per hour with overflow → single "mesh degraded" WO | 6 | Tech lead |
| R8 | AI model regression in severity-suggestion causes systematic over-OOO | 2 | 5 | 10 | Always HITL; provenance + replay; per-tenant budget; per-capability circuit breaker | 4 | AI/ML |
| R9 | Race between auto-create and manual create for the same housekeeping flag produces duplicate open WOs | 4 | 3 | 12 | Invariant #4 (one open per asset+category); UNIQUE partial index ux_work_orders_one_open_per_asset_category | 4 | Domain owner |
| R10 | Date-time bugs in cadence next-due across DST transitions in Asia/Kabul (UTC+04:30, no DST) and tenant tzs that do have DST | 2 | 4 | 8 | Use luxon with explicit timezone; unit tests for spring-forward/fall-back; integration test in Europe/Berlin tenant | 2 | Domain owner |
| R11 | PII leak via event payloads (description containing guest name) | 3 | 5 | 15 | PII redaction filter on description before emit; periodic sample audit; AI-orchestrator-side redactor | 6 | Security |
| R12 | Migration data corruption during legacy import | 2 | 5 | 10 | Dry-run mandatory; staging shadow import; idempotency by legacy_external_id; rollback by tenant | 4 | DBA |
| R13 | Sync push from compromised desktop issues commands as another user | 2 | 5 | 10 | Device JWT bound to user; user JWT short-lived; commands carry actor.userId validated against device's bound user; audit trail | 4 | Security |
| R14 | Generator run-hours regression wipes preventive cadence (next-due jumps far into future) | 3 | 4 | 12 | Invariant #9 + Asset max-of policy on runHours; explicit reset flow with audit | 4 | Domain owner |
| R15 | Vendor invoice posted twice (once by us, once by manual entry in billing) | 3 | 3 | 9 | vendor_invoice_posted_to_folio flag from billing.vendor_invoice.posted.v1; UI shows posted status; audit reconciliation | 6 | Finance |
| R16 | Notification fan-out fails for entire tenant (notification-service outage) | 2 | 4 | 8 | Notification dispatch is best-effort; events still emitted; UI shows "notification not delivered" badges from notification-service DLQ events | 4 | SRE |
| R17 | PartUsage atomic decrement race at desktop sync time produces negative on-hand | 3 | 4 | 12 | PartRepository.decrementOnHand is row-locked + CHECK on_hand >= 0; sync push surfaces failure to client | 4 | DBA |
| R18 | Vendor-message-draft AI generates inappropriate content in local language | 2 | 4 | 8 | Always HITL; staff edits before sending; tenant tone preset capped to whitelisted styles; audit of last 100 sends per tenant per month | 4 | AI/ML, Compliance |
| R19 | WhatsApp/SMS bridge cost spike from auto-reminders (e.g., vendor list full of bad numbers) | 3 | 3 | 9 | Per-vendor reminder cap (3); per-tenant daily reminder budget; alert on cost spike | 4 | Finance |
| R20 | Schedule deduplication false-negative (two schedules for same asset class fire simultaneously, both materialise drafts) | 3 | 3 | 9 | Invariant #4 catches at WO create; explicit "shadow schedule" detection in admin UI | 4 | Domain owner |
| R21 | Asset healthIndex drift from AI forecaster wrong way for too long | 3 | 3 | 9 | Bound on per-tick delta (auto-suspend if drop > 30); manual reset endpoint; daily report comparing against ground truth WO count | 4 | AI/ML |
| R22 | Reservation projection staleness causes us to miss relocation requirement | 3 | 4 | 12 | Projection refreshed on reservation.checked_in/modified/cancelled events; on miss, escalate via daily reconciliation job | 6 | Tech lead |
| R23 | Migration of mnt_* ULID prefix if we rename WorkOrder ⇄ MaintenanceTicket | 1 | 5 | 5 | Decision frozen; mnt_ is the canonical prefix forever; MaintenanceTicket is an alias in NAMING.md | 2 | Tech lead |
| R24 | Cloud SQL regional outage longer than RTO | 1 | 5 | 5 | DR drilled quarterly; cross-region replica; runbook tested | 3 | SRE |
| R25 | Bundle drift between docs and implementation (events declared but not emitted, or vice versa) | 4 | 3 | 12 | CI lint compares NestJS event emissions vs EVENT_SCHEMAS.md registry; quarterly audit using epic-spec-implementation-audit skill | 4 | Tech lead |