critical priority medium complexity integration pending backend specialist Tier 1

Acceptance Criteria

The post-session report screen route requires activity_id as a non-nullable route argument; attempting to navigate without it throws an assertion error in debug mode and shows an error screen in release mode.
When activity_id is null or absent, the screen renders a clear error state widget with a human-readable message ('Could not open report — activity reference is missing') and a back button; no crash occurs.
The report form orchestrator's submit method includes activity_id in the Supabase insert/upsert payload as a non-null UUID field.
The persisted activity record in Supabase has a valid foreign key reference to the activities table; inserting a report with a non-existent activity_id results in a caught error surfaced to the user, not a silent failure.
After successful submission, querying Supabase for the report record by activity_id returns the submitted report with matching activity_id, peer_mentor_id, and organization_id.
Unit tests for the orchestrator verify that missing activity_id is caught before any Supabase call is made.
Route navigation tests confirm that the correct activity_id is passed end-to-end from the calling screen (activity detail) into the report screen's BLoC/state.

Technical Requirements

frameworks
Flutter
BLoC
apis
Supabase PostgreSQL 15 — activities and post_session_reports tables
data models
activity
activity_type
performance requirements
activity_id validation must complete synchronously before any async Supabase call — zero added latency on the happy path
security requirements
activity_id must be validated against the user's organization_id via RLS to prevent cross-tenant report injection
Never expose raw Supabase error codes containing table structure to the UI — map to user-friendly messages
JWT claims must be verified server-side before the report insert is accepted by Supabase RLS policy
ui components
ErrorStateWidget — displays missing activity_id error with back navigation
ReportFormOrchestratorBloc — updated to carry activity_id in its state and emit it in submission events

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Extract activity_id from GoRouter's extra or pathParameters at the top of the screen's build method — use a dedicated RouteArgs data class to avoid stringly-typed extraction. The BLoC/Cubit should store activity_id in its initial state (passed via constructor injection), not derived inside the submit handler, so it is immutable for the lifetime of the form. For the Supabase insert, activity_id must be included as a literal column in the insert map — do not rely on a database trigger or default. If the foreign key check fails (PGRST301 or 23503), catch the PostgrestException and emit a user-friendly error event.

Avoid any logic that silently drops activity_id if it is unexpectedly null — prefer an explicit assert in debug builds.

Testing Requirements

Unit tests (flutter_test): ReportFormOrchestratorBloc emits error state when activity_id is null; submit method includes activity_id in payload when non-null. Widget tests: screen renders ErrorStateWidget when navigated to without activity_id argument; screen renders form scaffold when valid activity_id is provided. Integration test against Supabase test instance: submit with valid activity_id succeeds and record is retrievable; submit with non-existent activity_id surfaces a caught foreign key violation error. Minimum 90% branch coverage on route argument extraction and orchestrator submission path.

Component
Post-Session Report Screen
ui high
Epic Risks (2)
medium impact high prob technical

End-to-end integration tests that span Flutter UI → Supabase → RLS → storage are inherently flaky in CI due to network timing, test database state, and Supabase cold-start latency. Flaky tests erode confidence and slow the release pipeline.

Mitigation & Contingency

Mitigation: Use a dedicated Supabase test project with seeded org and user fixtures. Wrap all E2E tests in retry logic with a fixed seed and tear-down hooks. Keep E2E tests in a separate test suite that runs on-demand rather than on every PR, with unit and widget tests as the primary CI gate.

Contingency: If E2E tests remain unreliable, replace the Supabase calls in integration tests with a verified fake (in-memory repository implementations) and promote the real Supabase tests to a nightly scheduled run rather than blocking PR merges.

high impact medium prob security

Health status, course interest, and assistive device fields contain personal health data. If any logger, analytics event, or crash reporter captures field values — through automated error serialisation or developer-added debug logs — the feature could violate GDPR and Blindeforbundet's data processor agreement.

Mitigation & Contingency

Mitigation: Audit all log statements in the report feature's code paths before the epic is marked done. Apply a PII-safe logging wrapper that strips field values from any serialised form state before it reaches the logger. Add a CI lint rule that flags direct logger calls within report-related files.

Contingency: If PII is found in logs post-launch, immediately disable the affected logging call and rotate any credentials that were exposed. Notify the data protection officer and document the incident per GDPR Article 33 requirements.