Busflow Docs

Internal documentation portal

Skip to content

EU Regulation (EC) 561/2006 โ€” Compliance Research โ€‹

Context: The L3 Dispatch Availability Engine implements a simplified 11h daily rest heuristic. This document prepares a proper research and brainstorming run for full 561/2006 compliance in Phase 2. Status: ๐ŸŸก RESEARCH NEEDED Date: 2026-04-10


1. Current State (Phase 1) โ€‹

The availability engine checks:

MAX(crew_duty_log.log_time WHERE event_type = 'DRIVING') + 11h < target_start

This covers only the regular daily rest requirement. If a driver drove at midnight and 11 hours have elapsed, they're marked AVAILABLE. This is correct for the simplest case but ignores most of the regulation.


2. Full EU-561/2006 Requirements โ€‹

The regulation defines six interlocking limits. The engine must evaluate all of them together.

2.1 Daily Driving Time โ€‹

  • Max 9 hours per day (defined as 24h after end of last daily/weekly rest).
  • The driver can extend this to 10 hours up to twice per week.
  • "Driving" = any time the vehicle is in motion, including slow traffic.

2.2 Continuous Driving โ€‹

  • Max 4 hours 30 minutes of continuous driving.
  • Followed by a mandatory 45 minutes break.
  • The break can be split: 15 min + 30 min (in that order, not reversed).

2.3 Daily Rest โ€‹

  • Regular: 11 consecutive hours within each 24h period.
  • Reduced: 9 consecutive hours, the driver may use this up to 3 times per week.
  • Split: 3h + 9h = 12h total (in that order). Counts as one regular rest.
  • Multi-manning: reduced to 9h if two drivers present.

2.4 Weekly Driving Time โ€‹

  • Max 56 hours in any single week.
  • Week = Monday 00:00 to Sunday 24:00.

2.5 Fortnightly Driving Time โ€‹

  • Max 90 hours in any two consecutive weeks.

2.6 Weekly Rest โ€‹

  • Regular: 45 consecutive hours, once per week.
  • Reduced: 24 consecutive hours, the driver may take this every other week.
  • Compensation: the driver must compensate a reduced weekly rest by an equivalent rest period attached to another rest of โ‰ฅ 9h, taken before the end of the third week following.

3. Research Questions โ€‹

The team must answer these before implementation:

3.1 Data Model โ€‹

  • [ ] Can the current crew_duty_logs model (single log_time + event_type) support all 6 rule evaluations, or do we need a duration-based model (start/end times)?
  • [ ] How do we model the "week" concept (Mon 00:00 โ€“ Sun 24:00) across time zones? Are tenants always in one TZ?
  • [ ] How do we track the "3 reduced rests per week" counter? Stateless (computed from logs) or stateful (a separate counter)?
  • [ ] Do we need a separate rest_period entity to track split rests (3h + 9h) and weekly rest compensation?

3.2 Cross-Tenant / Freelancer Problem โ€‹

  • [ ] EU-561 applies per driver, not per operator. A freelance driver working for multiple tenants has a single legal rest clock. Our multi-tenant model only sees one tenant's crew_duty_logs. How do we handle this?
    • Option A: Ignore (accept legal risk, document limitation)
    • Option B: Driver self-declaration of external hours (manual input)
    • Option C: Industry tachograph data exchange (SmartCard readout via digital tachograph API)

3.3 Tachograph Integration โ€‹

  • [ ] Digital tachographs (EU Regulation 165/2014) produce .ddd files with all driver activity. Is there a standard API/SDK for parsing these?
  • [ ] Can we ingest raw tachograph data via the existing telemetry pipeline or do we need a separate ingestion path?
  • [ ] Smart tachographs (V2, mandatory since August 2023) support real-time remote download. Is this feasible for Phase 2?

3.4 Enforcement Strategy โ€‹

  • [ ] Which checks should be hard blocks (๐Ÿ”ด BLOCKED) vs. warnings (๐ŸŸก WARNING)?
    • Continuous driving > 4.5h without break โ†’ BLOCKED?
    • Weekly driving > 56h โ†’ BLOCKED?
    • Missing reduced rest compensation โ†’ WARNING?
  • [ ] Should the system enforce compliance proactively (prevent scheduling violations) or reactively (flag violations post-hoc)?
  • [ ] What is the legal liability if the system allows a dispatcher to override a 561 warning and a violation occurs?

3.5 UX Design โ€‹

  • [ ] How does the dispatch board visualize the remaining daily driving budget (e.g., "4h 23m remaining today")?
  • [ ] How do we display the fortnightly rolling window without overwhelming the dispatcher?
  • [ ] Do we need a dedicated "Driver Compliance Dashboard" separate from the dispatch board?

4. Penalty Context (DACH) โ€‹

ViolationFine (Germany)Fine (Austria)Notes
Daily driving exceededโ‚ฌ60โ€“500/hโ‚ฌ72โ€“726/hPer excess hour
Missing breakโ‚ฌ250โ€“500โ‚ฌ300โ€“600Per missing break
Insufficient daily restโ‚ฌ500โ€“1,500โ‚ฌ726โ€“2,180Per violation
Insufficient weekly restโ‚ฌ500โ€“2,000โ‚ฌ726โ€“2,180Per violation
Weekly driving > 56hโ‚ฌ120โ€“500โ‚ฌ218โ€“1,000Per excess hour
Fortnightly > 90hโ‚ฌ250โ€“500โ‚ฌ218โ€“1,000Per excess hour
Employer liabilityUp to โ‚ฌ15,000Up to โ‚ฌ5,000If systematic

CAUTION

In Germany, both the driver (ยง 8a FPersV) and the employer (ยง 20 FPersV) are liable. The employer is specifically responsible for ensuring that work schedules make compliance possible. This gives Busflow operators a direct legal interest in automated compliance checks.


5. Next Steps โ€‹

  1. Deep-dive talk with a DACH bus operator to validate which rules they actually track vs. ignore in practice
  2. Technical spike on .ddd tachograph file parsing (available libraries: readesm, tacholib, or commercial SDKs)
  3. Data model proposal for duration-based activity logging that supports all 6 rule evaluations โ€” see ยง6 below for the DutyActivity extraction design intent
  4. Decision on cross-tenant freelancer handling (3.2)
  5. L3-level spec for Phase 2 EU-561 compliance module

6. Design Intent: DutyActivity Extraction (Phase 2) โ€‹

Status: ๐ŸŸก DESIGN INTENT โ€” not yet specified, captures architectural direction to prevent Phase 1 decisions from blocking Phase 2. Date: 2026-04-15 Source: Compliance Subdomain Analysis โ€” original agent artifact, not tracked in docs/.

6.1 Problem โ€‹

CrewDutyLog is structurally coupled to ServiceLeg โ†’ TourDeparture. EU-561 applies per driver, not per trip type. If a driver performs scheduled bus routes (Linienverkehr), chartering (Anmietverkehr), or external work for another operator, that driving time must count toward the same legal rest clock. The current model has no place to record non-tour driving.

This is the same structural problem as the cross-tenant freelancer issue (ยง3.2) โ€” whether the blind spot comes from a different tenant or a different business module, the result is identical: incomplete driving-hour visibility.

6.2 Proposed Entity: DutyActivity โ€‹

A business-area-agnostic replacement for CrewDutyLog in the compliance evaluation path.

ColumnTypeDescription
idUUIDPK
tenant_idUUIDSoft FK to backoffice.operators
crew_member_idUUIDSoft FK to backoffice.crew_members
activity_typeVARCHARDRIVING, REST, WORK, AVAILABILITY, BREAK
start_timeTIMESTAMPTZActivity start โ€” resolves the duration-based logging gap (ยง3.1)
end_timeTIMESTAMPTZActivity end
duration_minutesINTComputed or explicit duration
source_typeVARCHARTOUR_LEG, LINE_ROUTE, CHARTER, TACHOGRAPH_IMPORT, SELF_DECLARATION
source_ref_idUUIDPolymorphic soft FK to the originating record (e.g., service_leg_id, future line_route_id)
tachograph_dataJSONBRaw/parsed IoT payload (migrated from CrewDutyLog)

6.3 ComplianceEvaluator Domain Service โ€‹

Stateless service consuming DutyActivity records, evaluating all 6 EU-561 rules (ยง2), and producing:

  • ComplianceStatus per driver per day/week (remaining driving budget, rest deficit, violation flags)
  • DutyViolation / DutyBudgetLow domain events โ†’ Dispatch Board

Lives in Backoffice (aligns with existing boundary: "Operations records, Backoffice evaluates"). May be extracted to a standalone Shared Core if Linienverkehr becomes a first-class module.

6.4 Migration Path โ€‹

PhaseModelScope
Phase 1 (current)CrewDutyLog with single log_time11h daily rest heuristic only. Sufficient for tour-only operators.
Phase 2 transitionDutyActivity entity created. CrewDutyLog emits DutyActivityRecorded events on write.Backfills DutyActivity from existing logs. CrewDutyLog remains for operational correlation (which leg? which vehicle?).
Phase 2 steady stateComplianceEvaluator reads from DutyActivity only. Other modules (Linienverkehr, chartering, tachograph import) write directly to DutyActivity.Full 6-rule evaluation. CrewDutyLog becomes an operational detail, not a compliance source.

6.5 Phase 1 Guard Rails โ€‹

To avoid blocking this extraction, Phase 1 must not:

  1. Add hard business logic that assumes service_leg_id is always present on duty records
  2. Build compliance evaluation SQL that joins crew_duty_logs โ†’ service_legs โ†’ tour_departures
  3. Store compliance outcomes (violation flags, budgets) on CrewDutyLog rows

Internal documentation โ€” Busflow