critical priority low complexity backend pending backend specialist Tier 0

Acceptance Criteria

ProxyActivityRecord is a final class extending Equatable with all required fields
All fields are final and non-nullable except notes (nullable String) and createdAt (nullable DateTime for pre-insert state)
fromJson correctly parses id (String), registeredBy (String), attributedTo (String), activityTypeId (String), date (DateTime from ISO 8601), durationMinutes (int), notes (String?), createdAt (DateTime?)
toJson produces a Map<String, dynamic> with snake_case keys matching Supabase column names
copyWith returns a new instance with only the specified fields changed, all other fields preserved
Equatable props list includes all fields so two instances with identical values are ==
Unit test: fromJson(toJson(record)) == record (round-trip identity)
Unit test: notes field handles null gracefully in both directions
Unit test: date field correctly serialises/deserialises timezone-aware ISO 8601 strings
Unit test: copyWith changes only the specified field
File placed at lib/features/proxy_activity/models/proxy_activity_record.dart

Technical Requirements

frameworks
Flutter
equatable
data models
ProxyActivityRecord
activities (Supabase table)
performance requirements
No async operations in the model — pure data class
toJson/fromJson must be synchronous and allocation-minimal
security requirements
Do not store sensitive PII beyond what Supabase already holds — model holds only UUIDs and metadata
notes field should be treated as potentially sensitive; never log its contents

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Use the equatable package (already in pubspec if BLoC is used). Declare the class as `final class ProxyActivityRecord extends Equatable`. For DateTime serialisation use `DateTime.parse(json['date'] as String)` and `.toIso8601String()` in toJson — do not use int epoch. For Supabase snake_case alignment: registeredBy → registered_by, attributedTo → attributed_to, activityTypeId → activity_type_id, durationMinutes → duration_minutes, createdAt → created_at.

Keep the model in the proxy_activity feature folder to maintain feature-first architecture. Do not add json_annotation/build_runner code generation unless the team already uses it — hand-written fromJson/toJson is simpler and sufficient for this model size.

Testing Requirements

Write flutter_test unit tests in test/features/proxy_activity/models/proxy_activity_record_test.dart. Cover: (1) full round-trip serialisation with all fields populated, (2) round-trip with notes=null, (3) round-trip with createdAt=null, (4) Equatable equality for identical instances, (5) Equatable inequality when any single field differs, (6) copyWith preserves unchanged fields, (7) copyWith changes target field. Minimum 7 test cases. No integration or widget tests required for this model.

Component
Proxy Activity Data Models
data low
Epic Risks (3)
high impact medium prob technical

The activities table migration adding registered_by and attributed_to columns may conflict with existing RLS policies or FK constraints if the user profile table structure differs from assumptions, blocking all subsequent epics.

Mitigation & Contingency

Mitigation: Review existing activities table schema and RLS policies before writing the migration. Run the migration against a staging database clone first. Write rollback scripts alongside the migration.

Contingency: If migration fails in staging, isolate the conflict with a targeted schema audit, adjust FK references or RLS policy scope, and re-run before touching production.

high impact medium prob security

The RLS policy must filter proxy inserts to the coordinator's chapter scope. If the chapter-scope resolver pattern differs between organisations (multi-chapter coordinators in NHF vs single-chapter in HLF), the policy may be too broad or too restrictive.

Mitigation & Contingency

Mitigation: Design the RLS policy to accept a coordinator's full set of assigned chapter IDs (array) rather than a single chapter_id. Validate the policy against NHF multi-chapter test fixtures during the integration test phase.

Contingency: If the policy is found to be incorrect after deployment, introduce a server-side validation edge function as a safety net while the RLS policy is corrected.

medium impact low prob technical

The bulk_register_activities RPC function may time out or cause lock contention when inserting large participant batches (e.g. 40+ peer mentors in a single group session), degrading the user experience.

Mitigation & Contingency

Mitigation: Benchmark the RPC function with 50-participant batches during development. Use unnest-based bulk insert rather than row-by-row PL/pgSQL loops. Set a reasonable statement_timeout.

Contingency: If performance is insufficient, split the client-side submission into chunks of 20 participants with progress feedback, rather than a single RPC call.