critical priority medium complexity testing pending testing specialist Tier 1

Acceptance Criteria

Integration test suite runs against a Supabase test database instance (separate from production) seeded with at least 5000 activity records across multiple NHF-like chapters and regions
A region-level scope query returns exactly the expected activity count matching the seed data for that region (no over-fetching from sibling regions, no under-fetching from child chapters)
BufdirCategoryMapper transformations are verified: every activity category in the seed data maps to the correct Bufdir category code without null or unmapped entries
Query for a 12-month period with 5000 activities completes in under 3 seconds measured with Dart Stopwatch from query initiation to result set materialisation
All slow query patterns (>500ms) are identified, documented in a findings report, and EXPLAIN ANALYZE output is captured for each
Index recommendations are documented based on slow query findings with estimated improvement percentages
Tests pass in CI environment (not only locally) with a stable test database connection
Edge case: query with zero activities in the selected scope returns an empty list without throwing exceptions
Edge case: query spanning a leap-year February correctly includes Feb 29 activities
Test report artifact is generated listing each test case, execution time, row count, and pass/fail status

Technical Requirements

frameworks
flutter_test
Supabase Flutter client SDK
Dart integration_test package
apis
Supabase REST API (PostgREST)
Supabase direct PostgreSQL connection for seed setup
data models
Activity
OrgUnit
Chapter
Region
BufdirCategory
ActivityCategoryMapping
performance requirements
Full 12-month region-level query must complete in under 3 seconds for 5000 activities
Individual query segments must not exceed 500ms individually
Database connection pool must handle concurrent test queries without timeout
security requirements
Test database must be isolated from production — use a dedicated Supabase test project or schema
Seed data must not contain real personal information — use generated/anonymised data only
Test credentials must be stored in environment variables, never hardcoded in test files

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use a dedicated Supabase test project (different URL/anon key than dev/prod) to avoid polluting real data. Write a Dart seed script that can be run before the test suite and torn down after. Structure the hierarchy to mirror NHF: national → 9 regions → ~156 chapters per region subset. When measuring performance, run each query 3 times and use the median time to avoid cold-start skew.

Use EXPLAIN ANALYZE via a raw SQL call or Supabase RPC to capture query plans for slow paths. Document findings in a `docs/query-performance-findings.md` file. Pay attention to JOIN strategy: if ExportDataQueryBuilder uses recursive CTEs for hierarchy traversal, these are common bottlenecks — consider materialised paths or ltree extension if available on the Supabase plan.

Testing Requirements

This task IS the testing task. Write integration tests using flutter_test with the integration_test package targeting a live Supabase test database. Seed script should insert: (a) 5000 activities distributed across 3 regions, 12 chapters each; (b) activity categories covering all Bufdir category codes. Test cases must include: correct region isolation, correct category mapping, performance under 3s, empty-scope edge case, leap-year boundary, and multi-chapter aggregation.

Capture timing with Dart Stopwatch and fail the test if any query exceeds the 3s SLA. Generate a structured test report (JSON or Markdown) as a CI artifact. Aim for 100% coverage of ExportDataQueryBuilder public methods.

Component
Export Data Query Builder
data high
Dependencies (3)
Implement the query builder service that encapsulates all complex join logic needed for Bufdir export data. Queries must join activities, activity_type_configuration, org_hierarchy, user_roles, and contact tables for a given org scope and date range. Expose buildExportQuery(orgIds, periodStart, periodEnd) returning a structured ExportDataSet. This is the single source of truth for what data enters every export — correctness here is critical for Bufdir compliance. epic-bufdir-report-export-foundation-task-005 Build the organisation hierarchy resolver that, given a coordinator's scope ID (chapter, region, or national level), expands it to the complete set of all constituent child entity IDs required for accurate aggregation. NHF has 1,400 local chapters across 3 levels — any missing child invalidates the Bufdir submission. Implement resolveScope(scopeId) returning List<String> of all leaf org IDs, with recursive traversal and caching. Must handle circular references and deleted nodes gracefully. epic-bufdir-report-export-foundation-task-006 Build the category mapper service that translates internal activity types to the official Bufdir category codes, reading mappings from the activity_type_configuration table rather than hard-coded values. Implement mapActivityToBuffirCategory(activityTypeId) and batchMap(List<Activity>) methods. Include validation to warn when unmapped activity types are encountered and log them to the audit trail. This prevents data-quality bugs from reaching the Bufdir submission portal. epic-bufdir-report-export-foundation-task-007
Epic Risks (3)
high impact medium prob technical

NHF's three-level hierarchy (national / region / chapter) with 1,400 chapters may have edge cases such as chapters belonging to multiple regions, orphaned nodes, or missing parent links in the database. Incorrect scope expansion would silently under- or over-report activities, which could invalidate a Bufdir submission.

Mitigation & Contingency

Mitigation: Obtain a full hierarchy fixture export from NHF before implementation begins. Write exhaustive unit tests covering boundary cases: single chapter, full national roll-up, chapters with no activities, and chapters assigned to multiple regions. Validate resolver output against a known-good manual count.

Contingency: If hierarchy data quality is too poor for automated resolution at launch, implement a manual scope override in the coordinator UI that allows the coordinator to explicitly select org units from a tree picker, bypassing the resolver.

medium impact high prob dependency

The activity_type_configuration table may not cover all activity types currently in use, leaving a subset unmapped at launch. Bufdir submissions with unmapped categories will be incomplete and may be rejected by Bufdir.

Mitigation & Contingency

Mitigation: Run a query against production activity data before implementation to enumerate all distinct activity type IDs. Cross-reference with Bufdir's published category schema (request from Norse Digital Products). Flag every gap as a known issue and build the warning surface into the preview panel.

Contingency: Implement a fallback 'Other' category bucket for unmapped types and surface a prominent warning in the export preview requiring coordinator acknowledgement before proceeding. Log unmapped types for post-launch cleanup.

high impact low prob security

Supabase RLS policies on generated_reports and the storage bucket must enforce strict org isolation. A misconfigured policy could allow a coordinator from one organisation to read another organisation's export files, creating a serious data breach with GDPR implications.

Mitigation & Contingency

Mitigation: Write RLS integration tests that attempt cross-org reads with explicitly different JWT tokens and assert that all attempts return empty sets or 403 errors. Include RLS policy review in the pull request checklist. Use Supabase's built-in policy tester during development.

Contingency: If a policy gap is discovered post-deployment, immediately revoke all signed URLs for affected exports, audit the access log for unauthorised reads, and issue a coordinated disclosure to affected organisations per GDPR breach notification requirements.