medium priority low complexity testing pending testing specialist Tier 6

Acceptance Criteria

A dedicated integration test file exists at `integration_test/features/bufdir/report_period/services_integration_test.dart`.
Tests connect to a local Supabase instance (via `supabase_flutter` configured with a test project URL and anon key from environment variables, not hardcoded).
Test setup seeds the test database with at least one submitted report period for a test organisation before each test run.
Smoke test 1 — PeriodPresetService: a known preset ID resolves to a `DateTimeRange` where `start.day == 1` and `end.day == lastDayOfMonth(end.month)`, confirming the preset produces valid Bufdir-aligned boundaries.
Smoke test 2 — PeriodRecordCountService: querying the count for the test organisation and the seeded period returns a non-negative integer (>= 0) without throwing.
Smoke test 3 — ReportPeriodValidator: submitting a range that overlaps the seeded submitted period returns `ValidationFailure(overlapsExistingReport)` with a non-null `conflictingPeriod`.
Smoke test 4 — ReportPeriodValidator: submitting a valid non-overlapping future period returns `ValidationSuccess`.
All three Riverpod providers (`periodPresetServiceProvider`, `periodRecordCountServiceProvider`, `reportPeriodValidatorProvider`) initialise inside a `ProviderContainer` with real repository implementations without throwing during initialisation.
Test teardown removes all seeded data so the test database is clean after each run.
Tests are tagged with `@Tags(['integration'])` and are excluded from the standard `flutter test` run — they are only run explicitly or in CI with a live Supabase test project.

Technical Requirements

frameworks
Flutter
flutter_test
integration_test
Supabase
Riverpod
apis
Supabase REST API
Supabase Auth (test user)
PeriodConfigurationRepository (real implementation)
data models
DateTimeRange
ReportPeriod
Organisation
PeriodPreset
performance requirements
Each smoke test must complete within 10 seconds — if Supabase latency is too high, the test environment configuration should be investigated.
Tests must not depend on external network beyond the local or CI Supabase instance.
security requirements
Supabase test URL and anon key must be read from environment variables (`SUPABASE_TEST_URL`, `SUPABASE_TEST_ANON_KEY`) — never hardcoded in source.
Test organisation IDs and user accounts must be dedicated test fixtures — never use production org IDs.
Seeded test data must be cleaned up in `tearDown` to prevent data leakage between test runs.

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Supabase initialisation in integration tests: call `await Supabase.initialize(url: env['SUPABASE_TEST_URL']!, anonKey: env['SUPABASE_TEST_ANON_KEY']!)` in `setUpAll`. Use `Supabase.instance.client` as the client — do not create a second client. Seed data pattern: in `setUp`, insert a submitted period row for `orgId = 'integration-test-org'` with a fixed past range (e.g., January 2025). In `tearDown`, delete all rows where `org_id = 'integration-test-org'`.

If the local Supabase Docker setup is used in CI, add a `supabase start` step in the GitHub Actions workflow before running integration tests. These are smoke tests — they verify wiring, not exhaustive business logic. Exhaustive logic is covered by unit tests in task-008.

Testing Requirements

Use the `integration_test` package for Flutter integration tests. Configure a dedicated Supabase project for CI (separate from staging/production). Use a test helper `SupabaseTestFixtures` class to seed and clean data via the Supabase admin API or direct SQL. Tag all tests with `@Tags(['integration'])` and add a `dart_test.yaml` exclusion so they do not run during `flutter test` (unit test only).

In CI, add a separate job `integration-tests` that sets the required environment variables and runs `flutter test integration_test/`. Document the required Supabase table setup (which rows to seed) in a comment at the top of the test file.

Component
Period Preset Service
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.