high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

A valid criteria JSON string (e.g., {"type":"honorar-threshold","threshold":3}) is deserialised into the correct typed BadgeCriteria subclass with all fields populated
A criteria JSON string with an unknown type field deserialises without throwing — the repository returns an UnknownBadgeCriteria fallback model or null criteria
A null or empty criteria column value is handled gracefully — fetchBadgeDefinitions returns the definition with a null or empty criteria field, not an exception
Malformed JSON (e.g., unclosed brace) in the criteria column is caught and logged; the definition is returned with a null criteria field rather than crashing
fetchBadgeDefinitions returns only definitions belonging to the calling user's organisation_id — definitions from other organisations are excluded
createBadgeDefinition with threshold criteria (threshold: 3) serialises and persists the correct JSON to the Supabase mock
createBadgeDefinition with threshold criteria (threshold: 15) serialises and persists the correct JSON to the Supabase mock
After createBadgeDefinition, a subsequent fetchBadgeDefinitions call (using mock data) returns a definition whose criteria deserialises back to the same typed model with the correct threshold value
Test suite achieves at least 80% line coverage on BadgeDefinitionRepository

Technical Requirements

frameworks
Flutter
flutter_test
apis
Supabase REST API
data models
BadgeDefinition
BadgeCriteria
HonorarThresholdCriteria
performance requirements
All unit tests complete in under 200 ms each
security requirements
Organisation scoping tests must verify that no cross-organisation definitions are returned — treat this as a security boundary

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

The honorar-threshold values (3 and 15) are not arbitrary — they map to specific business rules for Blindeforbundet (kontorhonorar triggers at 3rd assignment, higher rate at 15th). Make sure BadgeCriteria models expose these threshold values as named fields so the business logic layer can compare them without parsing JSON again. For malformed JSON handling, use a try/catch around jsonDecode inside the repository and log with a structured logger rather than print() — follow the project's existing logging pattern. Ensure that the mock setup for createBadgeDefinition verifies the exact JSON payload sent to Supabase (use mocktail's verify() / captured arguments) so the test catches any serialisation regressions.

Testing Requirements

Use flutter_test and mocktail. Organise tests in group() blocks: 'criteria deserialisation', 'organisation scoping', 'createBadgeDefinition'. For deserialisation tests, construct mock Supabase responses directly as Map objects — this avoids coupling tests to network behaviour. Test the honorar-threshold boundary values (3 and 15) explicitly in separate test cases since these correspond to business rules (kontorhonorar thresholds) documented in the requirements.

Include a test for criteria JSON with extra unknown fields to verify the deserialiser ignores unknown keys rather than throwing. Run flutter test --coverage and confirm 80% line coverage.

Component
Badge Definition Repository
data low
Epic Risks (2)
high impact medium prob scope

Badge criteria are stored as structured JSON in badge_definitions. If the JSON schema for criteria (threshold counts, streak lengths, training completion flags) is not well-defined upfront, the evaluation service will be built against a moving target, requiring costly migrations and refactors.

Mitigation & Contingency

Mitigation: Define and document the criteria JSON schema in a shared type file before any repository code is written. Review the schema with all three organisations' badge requirements — especially Blindeforbundet's honorar thresholds — and version the JSON schema using a 'criteria_version' field from day one.

Contingency: If the criteria schema must change after services are built, write a Supabase migration to backfill existing rows and add a migration version column. Keep the evaluation service criteria parser isolated behind an interface so only one function needs updating.

medium impact medium prob dependency

Badge icon assets may not yet exist or may fail WCAG 2.2 AA contrast validation (minimum 3:1 for graphical objects) when rendered over design-token backgrounds. Missing or non-compliant icons could block UI epic delivery for Blindeforbundet, for whom screen reader and visual accessibility is non-negotiable.

Mitigation & Contingency

Mitigation: During this epic, implement the contrast-ratio validator in badge-icon-asset-manager and run it as a Flutter test against all candidate icon assets early. Coordinate with the design team to provide WCAG-compliant SVG icons in both locked and unlocked variants before the UI epic begins.

Contingency: If assets are late or fail contrast checks, ship placeholder icons that are guaranteed compliant (solid design-token colour fills with text labels) and swap in final assets post-QA without requiring a code change.