high priority low complexity backend pending backend specialist Tier 3

Acceptance Criteria

The `UnimplementedError` stub from task-005 is replaced with a real implementation that calls `PeriodConfigurationRepository.getSubmittedPeriodsForOrg(orgId)`.
Overlap is defined as inclusive-start / exclusive-end: two ranges `[A, B)` and `[C, D)` overlap if and only if `A < D && C < B`.
A candidate range that is adjacent to (but does not overlap) an existing period returns `ValidationSuccess`.
A candidate range that partially overlaps an existing period returns `ValidationFailure(error: overlapsExistingReport, conflictingPeriod: <the overlapping existing period>)`.
A candidate range fully contained within an existing period returns `ValidationFailure` with the containing period as `conflictingPeriod`.
A candidate range that contains an existing period entirely returns `ValidationFailure` with the contained period as `conflictingPeriod`.
If multiple existing periods overlap the candidate, only the first conflict found is returned (short-circuit).
If `getSubmittedPeriodsForOrg` throws, the exception propagates up — do not silently swallow repository errors.
Boundary and empty-range rules (task-005) still execute before the overlap check and short-circuit on failure.
The full `validate` method is now fully implemented with no stubs or `UnimplementedError` calls.

Technical Requirements

frameworks
Flutter
Dart
Riverpod
apis
PeriodConfigurationRepository.getSubmittedPeriodsForOrg(String orgId) -> Future<List<DateTimeRange>>
data models
DateTimeRange
ReportPeriod
Organisation
performance requirements
Repository call is made only after boundary and empty-range checks pass — avoid unnecessary async calls for obviously invalid input.
Overlap check must iterate in O(n) over the returned list — no secondary queries per existing period.
security requirements
orgId must be validated as non-empty before passing to the repository — return emptyRange or a dedicated error rather than querying with a blank tenant ID.
Repository results must not be cached in the validator — caching belongs in the repository layer.

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Overlap arithmetic in Dart: `bool overlaps(DateTimeRange a, DateTimeRange b) => a.start.isBefore(b.end) && b.start.isBefore(a.end)`. This implements inclusive-start/exclusive-end semantics correctly. If the project uses inclusive-end semantics (23:59:59), adjust to `a.start.isBefore(b.end.add(Duration(seconds:1))) && b.start.isBefore(a.end.add(Duration(seconds:1)))` — but prefer exclusive-end convention at the domain layer for clarity. Inject `PeriodConfigurationRepository` via constructor parameter (not via Riverpod ref directly) to keep the validator testable in isolation.

The Riverpod wiring is handled in task-007. Store the conflicting period in `ValidationFailure.conflictingPeriod` as a `DateTimeRange?` — it is null for non-overlap errors.

Testing Requirements

Unit tests are handled in task-008. Ensure the repository dependency is injected (not hardcoded) so it can be replaced with a mock in tests. The repository interface should be the dependency, not the concrete Supabase implementation, so the validator can be tested without network access.

Component
Report Period Validator
service low
Epic Risks (2)
medium impact high prob dependency

Detecting overlap with previously submitted reports requires querying a report history table that may not yet exist or may not have a reliable submitted_at / period_end field, making the validator dependent on an incomplete upstream feature (Bufdir Report History & Audit Log).

Mitigation & Contingency

Mitigation: Define the minimum interface (a single repository method: getSubmittedPeriods(orgId) → List<DateTimeRange>) as an abstract class in this epic. Implement a stub that returns an empty list until the history feature is available, so the validator compiles and passes tests without a real data source.

Contingency: If the history feature is delayed beyond this feature's delivery window, ship the validator with the stub returning an empty list (overlap check disabled) and surface a feature-flag-controlled warning banner explaining that overlap detection will be enabled in a future update.

medium impact medium prob scope

Bufdir's structural requirements for reporting periods (complete calendar months, grant-year span restrictions) may be ambiguous or subject to change, causing the validator to enforce rules that are incorrect or overly restrictive for some organisations.

Mitigation & Contingency

Mitigation: Document the specific Bufdir rules being enforced in the validator's source code as named constants with references to the relevant Bufdir guidelines. Review the rules with at least one coordinator representative before implementation is finalised.

Contingency: Expose a per-org configuration flag (strict_bufdir_validation: bool) in the period configuration repository so that rule enforcement can be relaxed for specific organisations without a code deployment.