Document data foundation API and RLS policy contracts
epic-bufdir-report-history-foundation-task-010 — Write developer documentation covering: the bufdir_report_history table schema with column descriptions and constraints, the RLS policy rules with examples of allowed and denied operations per role, the Supabase Storage bucket configuration including retention policy and path convention, and the public API surface of ReportHistoryRepository and ReportFileStorageClient (method signatures, return types, error types). Store as inline Dart doc comments and a ARCHITECTURE.md section.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Write Dart doc comments directly above each class and public method in `report_history_repository.dart` and `report_file_storage_client.dart`. Use `@throws` convention in the description (Dart does not have a formal `@throws` tag, but document thrown exceptions in the comment body: 'Throws [RepositoryException] if the Supabase query fails.'). For the ARCHITECTURE.md section, place it in the feature directory (e.g., `lib/features/bufdir_report_history/ARCHITECTURE.md`) rather than the project root to keep it co-located with the code. Use a Markdown table for the RLS policy matrix — it renders well in both GitHub and IDEs.
Derive the documentation from the actual migration SQL and repository source — do not document intended behavior, only implemented behavior. If any discrepancy is found between implementation and intent during documentation, raise it as a separate issue rather than documenting the wrong behavior.
Testing Requirements
No automated tests required for this documentation task. Manual review checklist: (1) run `dart doc` and verify zero warnings on the documented files; (2) have a second developer read the ARCHITECTURE.md section and confirm they can correctly answer: what columns exist, who can read/write, what the storage path looks like, and what exceptions to handle — without looking at source code.
Incorrectly authored RLS policies could silently allow cross-organization data reads, exposing sensitive report history of one organization to coordinators of another in a multi-tenant environment.
Mitigation & Contingency
Mitigation: Write integration tests that explicitly authenticate as a user from organization A and assert zero rows are returned for organization B's history records. Use Supabase's built-in RLS testing utilities and review policies with a second developer.
Contingency: If a cross-tenant leak is discovered post-deployment, immediately revoke all active sessions for affected organizations, audit query logs for unauthorized access, and patch the RLS policy in a hotfix migration before re-enabling access.
The 5-year retention policy for report files may conflict with Supabase Storage's lack of native lifecycle rules, requiring a custom pg_cron job that could fail silently and either delete files prematurely or never clean up.
Mitigation & Contingency
Mitigation: Implement the retention cleanup as a documented pg_cron job with explicit logging to a separate audit_jobs table. Add a Supabase Edge Function health check that verifies the cron job ran within the last 25 hours.
Contingency: If the cron job fails, files accumulate in storage (non-critical for compliance — over-retention is safer than under-retention). Alert the ops team via monitoring and manually trigger the cleanup function once the cron issue is resolved.
Signed URL generation depends on the requesting user's Supabase session being valid at the time of the call. If sessions expire during a long screen interaction, URL generation will fail with an authorization error and confuse the coordinator.
Mitigation & Contingency
Mitigation: Wrap signed URL generation in the service layer with a session-refresh check before calling Supabase Storage. Generate URLs on demand (tap-to-download) rather than pre-generating them for all list items on screen load.
Contingency: If a URL generation fails due to session expiry, surface a clear error message prompting the coordinator to re-authenticate, then automatically retry URL generation after session refresh completes.