high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Unit tests cover all 7 rule types (required, minLength, maxLength, regex, numericMin, numericMax, selectOptions, dateRange — 8 if date-start and date-end are split) with at least one valid and one invalid test case each
Edge cases tested: null value on required field (invalid), null value on optional field (valid), empty string on required (invalid), whitespace-only string on required (invalid), boundary values for length and numeric range (both inclusive and exclusive), invalid regex pattern string in FieldConfig (validator returns error without throwing)
Multi-field validateAll test: creates a FieldConfig list of ≥ 10 fields with mixed valid/invalid values; asserts every field ID appears exactly once in the result map; asserts correct isValid states for each
Parallel validation test: wraps validateAll in `compute()` or uses `Future.wait` to confirm no shared mutable state causes data races (deterministic results on repeated runs)
Integration smoke test: annotated with `@Tags(['integration'])` so it is excluded from regular CI runs and only executed against a real Supabase test project
Integration smoke test — config load: OrgFieldConfigLoader fetches a pre-seeded org config from the test Supabase project and returns a non-empty FieldConfig list
Integration smoke test — cache: second call within TTL hits cache (assert via timing or call count); after invalidation, re-fetches
Integration smoke test — create and retrieve report: PostSessionReportRepository creates a draft report, retrieves it by activity_id, and the returned object matches the inserted data
Integration smoke test — way forward items: WayForwardItemRepository creates an item linked to the report, retrieves it, updates it, and deletes it; final retrieval returns null
Integration smoke test — RLS: connecting with a different user's JWT cannot read another user's report (returns null or PermissionException)
Integration test credentials loaded from environment variables (`SUPABASE_TEST_URL`, `SUPABASE_TEST_ANON_KEY`, `SUPABASE_TEST_USER_JWT`) — never hardcoded
Integration test leaves the test Supabase project clean: all created rows are deleted in a `tearDown` / `addTearDown` block

Technical Requirements

frameworks
flutter_test
mockito (unit tests only)
fake_async
supabase_flutter (integration test real client)
apis
Supabase REST API (integration test only)
Supabase Auth (integration test — test user JWT)
data models
FieldConfig
ValidationResult
PostSessionReport
WayForwardItem
OrgFieldConfig
performance requirements
Unit test suite completes in < 3 seconds
Integration smoke test completes in < 30 seconds against a warm Supabase instance
Integration test is skipped automatically if environment variables are absent (use `skipUnless` guard)
security requirements
Integration test environment variables must be stored in CI secrets, never in source control
Test Supabase project must use RLS policies mirroring production — do not disable RLS for tests
Test user accounts in the Supabase test project must have minimal permissions (only what the app role grants)

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

The integration smoke test is the safety net that catches contract mismatches between the data layer components — it is valuable precisely because it tests the real Supabase schema, RLS policies, and Dart serialisation together. Keep it lightweight (one happy-path per component + one RLS failure path) to avoid long CI times. Do NOT add business logic assertions here — those belong in unit tests. For the parallel validation edge case, the simplest implementation is to call `validateAll` 100 times with the same input on a `List.generate` and assert all results are identical — this catches any accidental static mutation.

If the project uses Riverpod, consider whether any integration test should exercise the provider layer; for this task, test the repository classes directly to keep scope narrow.

Testing Requirements

Split into two test files: `report_field_validator_test.dart` (pure unit, no network) and `data_layer_integration_test.dart` (tagged integration). For the unit tests, use a test table driven approach: define a list of `(FieldConfig, dynamic value, bool expectedValid, String? expectedErrorContains)` tuples and iterate with `for (final tc in cases) { test(...) }` to keep the file concise. For the integration test, use `setUpAll` to initialise the Supabase client from env vars and `tearDownAll` to close it.

Use `addTearDown` within each test to register cleanup immediately after creation, so cleanup runs even if the test fails mid-way.

Component
Report Field Validator
service low
Epic Risks (3)
high impact medium prob security

Supabase RLS policies for multi-org report access may be more complex than anticipated — coordinators need cross-peer-mentor access within their org but not across orgs, and draft reports should be invisible to coordinators until submitted. Misconfigured RLS could expose sensitive health data or block legitimate access.

Mitigation & Contingency

Mitigation: Define and test RLS policies in isolation before writing repository code. Create a dedicated SQL migration file with policy definitions and an automated integration test suite that verifies each role's access boundaries using real Supabase auth tokens.

Contingency: If RLS proves too complex to express declaratively, implement application-level access control in the repository layer with explicit org and role checks, and add a security audit task before the feature goes to production.

high impact medium prob integration

The org field config JSON stored in Supabase may lack a stable, versioned schema contract. If different organisations have drifted to different field-definition formats, org-field-config-loader will fail silently or crash, breaking form rendering for those orgs.

Mitigation & Contingency

Mitigation: Define a canonical JSON Schema for field config and validate all existing org configs against it before implementation begins. Store a schema version field in every config record and handle version migrations explicitly in the loader.

Contingency: If existing configs are too heterogeneous, implement a config normalisation pass in org-field-config-loader that coerces known variants to the canonical format, logging warnings for fields that cannot be normalised so operations can fix them in the admin console.

medium impact low prob technical

TTL-based schema cache invalidation may cause peer mentors to use stale field definitions for up to the TTL window after an admin updates the org config, potentially collecting data against outdated field structures.

Mitigation & Contingency

Mitigation: Set a conservative TTL (e.g. 15 minutes) and expose a manual cache-bust mechanism triggered on app foreground-resume. Document the maximum staleness window in the admin console so org admins know to plan config changes outside active reporting windows.

Contingency: If stale schema causes a data quality incident, add a Supabase Realtime subscription to the org config table that invalidates the cache immediately on any config update.