high priority low complexity testing pending testing specialist Tier 1

Acceptance Criteria

All public methods of `PeriodCalculatorService` are covered by at least one passing test
Week boundary test: the last day of the last ISO week of year N and the first day of the first ISO week of year N+1 are both correctly classified
Month boundary test: `getPeriodEnd` for January returns January 31 at 23:59:59.999, for a leap-year February returns February 29, for a non-leap February returns February 28
Quarter boundary test: Q4 end is December 31 and Q1 start is January 1 of the following year with no gap or overlap
Leap year test: `isDateInPeriod` correctly includes February 29 in the monthly period when the year is a leap year
`isDateInPeriod` returns true for a timestamp exactly equal to `period_start` (inclusive lower bound)
`isDateInPeriod` returns true for a timestamp exactly equal to `period_end` (inclusive upper bound)
`isDateInPeriod` returns false for a timestamp one millisecond before `period_start`
`isDateInPeriod` returns false for a timestamp one millisecond after `period_end`
flutter test `--coverage` report shows 100% branch coverage for `period_calculator_service.dart`
All tests are deterministic — no use of `DateTime.now()` inside test bodies (use fixed dates)

Technical Requirements

frameworks
flutter_test
Flutter
data models
PeriodType (enum: weekly, monthly, quarterly, yearly)
DateRange / PeriodBounds
performance requirements
Full test suite must complete in under 5 seconds (pure Dart, no I/O)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Structure the test file as `period_calculator_service_test.dart` alongside the service under `test/`. Use `const` or `final` fixed `DateTime` values at the top of each `group` block — this makes failures immediately reproducible. For ISO week year-rollover, remember that ISO week 1 is defined as the week containing the first Thursday of the year; use known reference dates (e.g. 2022-01-01 is ISO week 52 of 2021, 2023-01-02 is ISO week 1 of 2023) to anchor tests.

For leap year tests, use 2024-02-29 as the canonical date. Do not mock `PeriodCalculatorService` in these tests — test the real implementation directly. If the service has private helpers that contain branching logic, test them indirectly through the public API rather than exposing them. Add a comment block at the top of the file listing all ISO edge-case references used.

Testing Requirements

This task IS the testing task. Organise tests into `group()` blocks per method. Use fixed `DateTime` constants for all inputs — never `DateTime.now()`. Cover the following explicit scenarios: (1) weekly: Dec 28 – Jan 3 year boundary (ISO week 1 rules); (2) monthly: all 12 months including Feb in leap year (2024) and non-leap year (2023); (3) quarterly: Q1 start Jan 1, Q4 end Dec 31, Q3→Q4 transition; (4) isDateInPeriod: start-inclusive, end-inclusive, 1 ms before start, 1 ms after end, midpoint; (5) edge: period with same start and end (single-day period).

Use `lcov` or `flutter test --coverage` to verify 100% branch coverage and attach the report as a CI artifact.

Component
Period Calculator Service
service low
Epic Risks (3)
high impact medium prob security

Supabase RLS policies for aggregation views are more complex than single-table policies. A misconfigured policy could silently allow a coordinator in one organisation to see data from another, causing a data breach and breaking trust with participating organisations.

Mitigation & Contingency

Mitigation: Write automated RLS integration tests that create two separate organisations with distinct data, then assert that queries authenticated as org-A users return only org-A rows. Run these tests in CI on every PR touching the database layer.

Contingency: If an RLS bypass is discovered post-deployment, immediately disable the periodic summaries feature flag, revoke affected sessions, audit access logs, notify affected organisations, and patch the policy before re-enabling.

medium impact medium prob technical

Activity records may span multiple sessions types, proxy registrations, and coordinator bulk entries. Incorrect JOIN logic or missing filters in the aggregation query could double-count sessions or omit activity types, producing inaccurate summaries that erode user trust.

Mitigation & Contingency

Mitigation: Build a fixture dataset covering all activity registration paths (direct, proxy, bulk) and assert expected aggregated counts in integration tests before any UI consumes the repository.

Contingency: If inaccurate counts are reported post-launch, mark affected summaries as invalidated in the database and re-trigger generation once the query is corrected. Communicate transparently to affected users via an in-app banner.

low impact low prob integration

The local cache must be invalidated when a new summary arrives via push notification. If the push token is stale or the FCM/APNs delivery is delayed, the device may show an outdated summary for an extended period, confusing users who see different numbers online versus offline.

Mitigation & Contingency

Mitigation: Implement a TTL on cached summaries (max 48 hours) so stale data is auto-cleared even without a push notification. Also trigger cache refresh on app foreground if the current period's summary is older than 24 hours.

Contingency: Provide a manual pull-to-refresh on the summary card that bypasses the cache and fetches directly from Supabase when a network connection is available.