critical priority medium complexity testing pending testing specialist Tier 1

Acceptance Criteria

Test file at test/resolvers/org_hierarchy_resolver_test.dart runs with flutter test
National scope test: resolveLeafIds('nhf-national') returns exactly 1400 distinct chapter IDs when given the NHF fixture hierarchy
Region scope test: resolveLeafIds('nhf-region-north') returns the correct subset of chapter IDs belonging to that region — verified by counting and spot-checking IDs
Single chapter scope test: resolveLeafIds('nhf-chapter-001') returns a list containing only 'nhf-chapter-001'
Circular reference test: fixture with node A → B → A is detected; OrgHierarchyResolver throws a typed CircularHierarchyException or returns a typed failure — it must not loop infinitely or stack overflow
Soft-deleted node test: nodes with deleted_at != null are excluded from the resolved leaf ID list
Soft-deleted node test: a soft-deleted intermediate node causes all its descendants to be excluded too
Cache hit test: calling resolveLeafIds twice with the same scope ID results in exactly one data source call (mock verify count == 1)
Cache invalidation test (if implemented): verify cache is cleared after a defined TTL or explicit invalidation call
Empty org test: resolveLeafIds for a region with no child chapters returns an empty list without exception
All tests run without real Supabase or network calls
Test suite completes in under 3 seconds

Technical Requirements

frameworks
Flutter
flutter_test
mockito or mocktail
apis
Supabase PostgREST client (mocked) for org hierarchy table
data models
OrgNode
OrgScope
CircularHierarchyException
performance requirements
Resolver must expand 1400-leaf NHF hierarchy in under 50 ms (tested with in-memory fixture)
Second call with same scope must return cached result in under 1 ms
security requirements
Resolver must never return IDs from outside the requested scope — verified by multi-tenant fixture test
Circular reference must not be exploitable to cause DoS (infinite loop guard required)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Implement hierarchy traversal as a depth-first or breadth-first recursive expansion over OrgNode objects. Guard against cycles with a visited Set tracking node IDs during traversal — if a node ID is already in the visited set, throw CircularHierarchyException immediately. For the cache, use a simple Map> keyed by scope ID; populate on first call and return cached value on subsequent calls. The 1400-node NHF fixture is the acceptance benchmark — build it once in a fixture helper file and reuse across tests.

Use a factory constructor or static builder method on OrgNode to make fixture construction readable. Soft-delete filtering should happen at the data source level (mock returns only non-deleted nodes) AND be defensively checked in the resolver — test both layers. The critical priority reflects that incorrect hierarchy expansion would corrupt Bufdir report scope.

Testing Requirements

Unit tests with flutter_test. Build the NHF 3-level fixture as a static const structure: 1 national node, ~9 regions, ~1400 chapters. Inject this fixture via a fake OrgDataSource. Group tests: scope expansion, circular reference handling, soft-delete filtering, caching behaviour.

For the circular reference test, build a minimal 3-node cycle fixture. Use verify(mockDataSource.fetchChildren(...)).called(1) to assert caching. Assert exception type and message for circular reference. Run with flutter test --coverage; confirm branch coverage ≥ 90% for the resolver class.

Component
Organisation Hierarchy Resolver
service medium
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.