Implement org-level submission mode feature flag
epic-bufdir-report-export-api-integration-task-006 — Add a submission_mode configuration field (values: file_based, direct_api) to the org-level feature flag system. The bufdir-export-service reads this flag to route to either the file-based path (Phases 1–2) or the bufdir-api-client direct submission path (Phase 3) with zero changes to the orchestration layer. Include admin tooling to toggle the flag per organisation.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Handles integration between different epics or system components. Requires coordination across multiple development streams.
Implementation Notes
Add `bufdir_submission_mode TEXT NOT NULL DEFAULT 'file_based' CHECK (bufdir_submission_mode IN ('file_based', 'direct_api'))` to the organisations (or org_config) table via a migration. In BufdirExportService, fetch the flag via a lightweight repository method `getSubmissionMode(orgId)` that caches with a 5-minute TTL using a simple in-memory map. Use a BufdirSubmissionMode enum (`fileBased`, `directApi`) mapped from the string value — never compare raw strings. The switch/routing logic should be a single `switch (mode)` expression in `BufdirExportService.submit()`.
Provide an admin Supabase Edge Function `admin/set-bufdir-submission-mode` accepting `{org_id, mode}` that validates the caller has super-admin role from JWT claims before writing.
Testing Requirements
Unit tests for BufdirExportService using mocked BufdirApiClient and mocked file-generation service: (1) file_based mode calls file path and does not call API client, (2) direct_api mode calls API client and does not call file path, (3) null/missing flag defaults to file_based, (4) 'direct_api' → 'file_based' toggle mid-session respects updated value after cache expiry. Integration test verifying CHECK constraint rejects invalid values. No UI tests required for this task.
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.
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.