high priority medium complexity backend pending backend specialist Tier 0

Acceptance Criteria

An abstract Dart class IExportSubmissionClient is defined with at minimum: Future<BufdirSubmissionResult> submitReport(SubmitReportRequest request) and Future<void> cancel() methods
SubmitReportRequest model contains: organizationId (String), reportPeriodId (String), reportPayload (Map<String, dynamic>), submissionMode (enum: api / file), and metadata (Map<String, String>)
BufdirSubmissionResult model contains: referenceNumber (String?), status (BufdirSubmissionStatus enum), submittedAt (DateTime), errorMessage (String?), and rawResponse (Map<String, dynamic>?)
BufdirSubmissionStatus enum contains at minimum: success, pending, rejected, networkError, authenticationError, validationError
SubmitReportResponse is a sealed class or Result type wrapping either BufdirSubmissionResult (success) or a typed BufdirSubmissionError (failure)
A BufdirApiClientImpl class stub exists implementing IExportSubmissionClient (methods throw UnimplementedError — implementation deferred to subsequent tasks)
A BufdirFileExportClientImpl class stub exists implementing IExportSubmissionClient for the file-based path
The interface file includes Dart doc comments on each method explaining the contract, error conditions, and expected behavior for both implementations
No concrete Supabase or HTTP calls exist in the interface file — it is purely abstract types and interfaces
The interface compiles cleanly with dart analyze reporting zero errors or warnings
Interface types are exported from a single barrel file (bufdir_api_client.dart) for clean imports throughout the codebase

Technical Requirements

frameworks
Dart (sealed classes for Result type, abstract classes for interface)
apis
Bufdir Reporting API (interface shaped to match expected API contract from Norse Digital Products negotiation)
data models
bufdir_export_audit_log (BufdirSubmissionResult maps to audit log fields: status, reference number, submitted_at)
bufdir_column_schema (reportPayload structure informed by column schema)
performance requirements
Interface definition imposes no runtime overhead — purely compile-time contract
security requirements
SubmitReportRequest must not include authentication credentials — auth is handled by the authentication handler (task-002)
BufdirSubmissionResult must not expose raw API keys or tokens in rawResponse — sanitize before storage
Interface contract must specify that implementations must not log reportPayload contents at INFO level — only at DEBUG with PII masking

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Integration Task

Handles integration between different epics or system components. Requires coordination across multiple development streams.

Implementation Notes

Use Dart's sealed class pattern for SubmitReportResponse to get exhaustive pattern matching: sealed class SubmitReportResponse {} / class SubmitReportSuccess extends SubmitReportResponse { final BufdirSubmissionResult result; } / class SubmitReportFailure extends SubmitReportResponse { final BufdirSubmissionError error; }. This eliminates null checks in the orchestration layer. Define BufdirSubmissionError as an enum or sealed class covering the distinct failure modes. The interface design should anticipate that the Bufdir API negotiation is not complete — keep SubmitReportRequest flexible (Map for payload) so the schema can be updated without changing the interface.

Consider adding a validate() method to SubmitReportRequest that checks required fields before submission to provide early validation. Place all types in lib/features/bufdir/data/models/bufdir_submission_models.dart and the interface in lib/features/bufdir/domain/repositories/i_export_submission_client.dart following clean architecture conventions.

Testing Requirements

Unit tests for the model classes only (no integration tests at this stage): (1) BufdirSubmissionResult serialization — assert toJson/fromJson round-trip preserves all fields including null referenceNumber; (2) SubmitReportRequest serialization round-trip; (3) BufdirSubmissionStatus enum coverage — assert all enum values are handled in a switch expression (exhaustiveness check via Dart sealed class or explicit default throw); (4) compile-time test: a mock implementation of IExportSubmissionClient compiles without error. No network calls in any tests for this task.

Component
Bufdir API Client
service high
Epic Risks (2)
medium impact high prob dependency

Norse Digital Products has not yet completed API negotiations with Bufdir. If negotiations stall or Bufdir's API design diverges significantly from expectations, the API client may need substantial rework, or the epic may be blocked indefinitely.

Mitigation & Contingency

Mitigation: Implement the client against a locally defined stub of the expected Bufdir API schema. Isolate all Bufdir-specific schema mapping in a single adapter class so that changes to the actual API schema require changes in only one place. Keep the epic in 'interface-ready' status until real API credentials are available for integration testing.

Contingency: If API negotiations are not completed within the planned window, defer this epic without impact on any other epic — the PDF/CSV fallback path from Epics 1–4 delivers full standalone value. Mark the epic as blocked and resurface when negotiations conclude.

high impact low prob security

Bufdir API credentials stored in the application or edge function environment could be exposed through misconfigured secrets management, log leakage, or a compromised deployment pipeline, allowing unauthorised Bufdir submissions on behalf of the organisation.

Mitigation & Contingency

Mitigation: Store all Bufdir API credentials exclusively in Supabase Vault (or the integration credential vault component), never in client-side code or environment variables accessible to the Flutter app. Transmit credentials only from within the edge function, not from the Flutter client. Implement credential rotation support from the outset.

Contingency: If a credential leak is detected, immediately revoke and rotate the affected API credentials through Bufdir's credential management portal, audit submission logs for any unauthorised calls, and notify Bufdir's technical contact per the API agreement's security incident clause.