high priority medium complexity backend pending backend specialist Tier 3

Acceptance Criteria

Transformer converts internal Activity and Assignment records to Xledger REST API payload format including correct field mappings and JSON structure
Transformer converts internal expense claim records to Microsoft Dynamics 365 REST API payload format with correct OData annotations
Date fields are normalized to ISO 8601 (YYYY-MM-DDTHH:mm:ssZ) for outbound requests and parsed back to UTC epoch for internal storage
Currency amounts are rounded to 2 decimal places using banker's rounding (round-half-to-even) before serialization
CSV payloads for Bufdir export use semicolon delimiter, UTF-8 BOM encoding, and column order matching bufdir_column_schema.column_mappings
External API responses are normalized into a shared IntegrationResult schema: { success: boolean, externalId: string | null, errorCode: string | null, rawResponse: unknown }
Transformation functions are pure (no side effects) and export a typed interface consumable by other Edge Function modules
Null/undefined internal fields are mapped to explicit null in outbound payloads rather than being omitted, unless the target API rejects null for that field
Transformation errors (missing required field, type mismatch) throw a typed TransformationError with field path and expected type
Unit tests cover: date boundary cases (DST transitions, leap seconds), currency precision (1/3 kr rounds correctly), CSV special characters (semicolons, newlines in text fields)

Technical Requirements

frameworks
Supabase Edge Functions (Deno runtime)
Deno standard library (std/encoding/csv, std/datetime)
apis
Xledger REST API β€” target payload schema from adapter spec
Microsoft Dynamics 365 REST API β€” OData v4 JSON format
Bufdir Reporting API β€” CSV column schema from bufdir_column_schema table
data models
activity
assignment
bufdir_column_schema
annual_summary
performance requirements
Single-record transformation completes in under 5ms CPU time
Batch transformation of 500 records completes in under 200ms
No heap allocations retained after transformation completes (avoid memory leaks in long-running Edge Functions)
security requirements
PII fields (personnummer, full name, email) must be excluded from transformation debug logs
Currency amounts must not be logged at INFO level β€” only at DEBUG with verbose flag
Outbound payloads must never include internal UUIDs that could expose database structure to external systems
CSV files containing personal data must not be written to disk β€” kept in memory buffer only

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Integration Task

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

Implementation Notes

Implement as a dedicated transformers/ directory inside the Edge Function with one file per adapter (xledger-transformer.ts, dynamics-transformer.ts, bufdir-transformer.ts) plus a shared types.ts. Use discriminated union types for IntegrationResult to make error handling exhaustive at compile time. For date handling, always convert to UTC before serialization β€” do not assume server timezone. For Bufdir CSV, read column order dynamically from bufdir_column_schema at runtime rather than hardcoding, since schema versions can change.

Currency: use integer arithmetic (store as ΓΈre/cents internally) to avoid floating-point drift, only convert to decimal at serialization boundary. Keep transformers stateless and free of I/O so they can be tested without Supabase dependencies.

Testing Requirements

Write unit tests in Deno test framework covering: (1) Xledger transformer β€” valid activity record produces correct JSON structure; (2) Dynamics transformer β€” expense claim maps OData type annotations correctly; (3) Bufdir CSV transformer β€” column_mappings from bufdir_column_schema drive column order; (4) Date normalizer β€” input in Norway timezone (Europe/Oslo) serializes to correct UTC ISO string; (5) Currency precision β€” 0.005 rounds to 0.01, 0.015 rounds to 0.02 (banker's rounding); (6) TransformationError thrown for missing required field. Integration tests: invoke Edge Function locally with Supabase CLI and assert output payload matches snapshot. Target 90% line coverage on transformer module.

Component
Integration Edge Functions
infrastructure high
Epic Risks (3)
medium impact medium prob technical

Supabase Edge Functions have cold start latency that can cause the first sync invocation after idle periods to fail or timeout when the external API has a short connection window, leading to missed scheduled syncs that go undetected.

Mitigation & Contingency

Mitigation: Configure Edge Function memory and implement a warm-up ping mechanism before heavy sync invocations. Set generous timeout values on the external API calls. Log all cold-start incidents for monitoring.

Contingency: If cold starts cause consistent sync failures, migrate the sync scheduler to a persistent Supabase cron job that pre-warms the function 30 seconds before the scheduled sync time.

high impact low prob technical

The sync scheduler must execute jobs at predictable times for financial reporting accuracy. Drift in cron execution timing (due to Supabase infrastructure delays) could cause syncs to run at wrong times, leading to missing data in accounting exports or duplicate exports across reporting periods.

Mitigation & Contingency

Mitigation: Implement idempotency keys based on integration ID + scheduled period, so re-runs of a delayed sync cannot create duplicate exports. Log actual execution timestamps vs scheduled timestamps and alert on drift exceeding 5 minutes.

Contingency: If scheduler reliability is insufficient, integrate with a dedicated cron service (e.g., pg_cron on Supabase) for millisecond-precise scheduling, replacing the application-level scheduler.

high impact medium prob integration

Aggressive health monitoring ping frequency could trigger rate limiting on external APIs (especially Xledger and Dynamics), causing legitimate export calls to fail after the monitor exhausts the API's request quota.

Mitigation & Contingency

Mitigation: Use lightweight health check endpoints (HEAD requests or vendor-specific ping/status endpoints) rather than data requests. Set health check frequency to once per 15 minutes minimum. Implement exponential backoff after consecutive failures.

Contingency: If rate limiting occurs, disable active health monitoring for the affected integration type and switch to passive health detection (mark unhealthy only when a scheduled sync fails).