Register all adapters in AdapterRegistry
epic-external-system-integration-configuration-core-services-task-009 — Complete the REST API Adapter Registry by registering all five adapters (Xledger, Dynamics, Cornerstone, Consio, Bufdir) with the registry. Implement factory methods, adapter lifecycle management, and the lookup API used by Edge Functions and Integration Config Service. Add adapter availability checks and graceful degradation when an adapter is unreachable.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Handles integration between different epics or system components. Requires coordination across multiple development streams.
Implementation Notes
Implement as a Deno TypeScript module (adapter_registry.ts) that can be imported by any Edge Function. Use a Map
For lifecycle management, since Edge Functions are stateless (invocation-scoped), the 'cache' only persists for the duration of one function invocation — document this clearly. The healthCheckAll() method should use Promise.allSettled() (not Promise.all()) to ensure one failing health check does not block results from others. The availability check should query the integration_configurations table (via the repository layer from task-002) to verify an active config exists for the org + type combination before attempting instantiation. This prevents wasteful adapter construction when no config is set up.
Graceful degradation: wrap each healthCheck() call in try/catch and return a HealthResult with status: 'unavailable' and the error message on failure — never propagate raw exceptions from health checks.
Testing Requirements
Unit tests (Deno test): getAdapter returns correct adapter class for each of the five integration types, AdapterNotFoundError thrown for unknown type, org isolation verified (same type different org returns different instance with different credentials), isAdapterAvailable returns false when no config exists, healthCheckAll() resolves concurrently and maps all five results correctly, graceful degradation when one healthCheck throws (others still resolve). Mock all five adapter constructors and credential vault to keep tests fast and dependency-free. Test coverage target: 95% on registry logic. Run in CI on every commit since this is a critical routing layer.
Each of the five external systems (Xledger, Dynamics, Cornerstone, Consio, Bufdir) has a different authentication flow, field schema, and error format. Forcing them into a uniform adapter interface may require compromises that result in leaky abstractions or make the adapter contract too complex to maintain.
Mitigation & Contingency
Mitigation: Design the IntegrationAdapter interface with a loose invoke() payload rather than a typed one, allowing each adapter to declare its own input/output schema. Use integration type metadata in the registry to document per-adapter quirks. Build Xledger first as the most documented API, then adapt the interface based on learnings.
Contingency: If the uniform interface cannot accommodate all five systems, split into two interface tiers: a simple polling/export adapter and a richer bidirectional adapter, with the registry declaring which tier each system implements.
Development and testing of the Cornerstone and Consio adapters depends on NHF providing sandbox API access. If credentials or documentation are delayed, these adapters cannot be validated, blocking the epic's acceptance criteria.
Mitigation & Contingency
Mitigation: Implement Xledger and Dynamics adapters first (better-documented, sandbox available). Create a mock adapter for Cornerstone/Consio using recorded API responses for CI testing. Proactively request sandbox access from NHF at project kickoff.
Contingency: Ship the epic with Cornerstone/Consio adapters in a 'stub' state (connectivity test returns a simulated success, invoke() is not production-wired) and gate the NHF integration behind a feature flag until real API access is obtained.
Real-world field mappings may include nested transformations, conditional logic, and data type coercions (e.g., Norwegian date formats, currency rounding rules) that the Field Mapping Resolver's initial design does not accommodate, requiring scope expansion mid-epic.
Mitigation & Contingency
Mitigation: Gather actual field mapping examples from Blindeforbundet (Xledger) and HLF (Dynamics) before designing the resolver. Identify the most complex transformation required and ensure the resolver design handles it. Limit Phase 1 to direct field renaming and format conversion only.
Contingency: If complex transformations are required, implement a simple expression evaluator (e.g., JSONata or a custom mini-DSL) as an extension point in the resolver, delivering basic mappings first and complex ones in a follow-up task.