ADR-007: Subcontracting Strategy โ LegAssignment Nullability โ
Status: โ Accepted Date: 2026-04-09 Triggered by: Level 2 Audit โ Crew & Fleet Management (Finding S1)
Context โ
Bus tour operators in the DACH region regularly outsource individual service legs to partner bus companies (Fremdanmietung) during capacity bottlenecks or for specialized routes. The leg_assignments table in the Operations schema links a ServiceLeg to an internal Vehicle and CrewMember. Both fields are currently Not Null, which prevents modeling subcontracted legs.
PRODUCT_schema-feature-gaps.md ยง4 proposes adding supplier_id and making the internal asset fields nullable. Two options were evaluated:
- Option A โ Nullable FKs + supplier_id: Minimal schema change. A CHECK constraint enforces mutual exclusivity:
(supplier_id IS NOT NULL) OR (vehicle_id IS NOT NULL AND crew_member_id IS NOT NULL). - Option B โ Separate SubcontractedLeg entity: Cleaner domain separation but duplicates assignment structure and complicates dispatch board queries.
Decision โ
Option A โ nullable FKs with CHECK constraint on leg_assignments.
Rationale: Subcontracting is a Phase 2 feature with medium priority. Option A keeps the schema simple and avoids a parallel entity that the dispatch board would need to union-query. If subcontracting becomes a primary workflow (e.g., marketplace model), migration to Option B can be done without breaking the existing assignment structure.
Consequences โ
leg_assignments.vehicle_idandcrew_member_idbecome nullable.leg_assignments.supplier_idadded as soft FK tobackoffice.suppliers.- CHECK constraint:
(supplier_id IS NOT NULL) OR (vehicle_id IS NOT NULL AND crew_member_id IS NOT NULL). - Dispatch board renders subcontracted legs as "Outsourced" rows with distinct styling.
- Operations API must validate the mutual exclusivity on write (in addition to the DB constraint).
- No cross-context event needed โ
supplier_idis a soft FK read at query time.