high priority medium complexity backend pending backend specialist Tier 3

Acceptance Criteria

FieldMapping is an @immutable class with fields: sourceField (String), targetField (String), transformation (FieldMappingTransformation?), integrationType (IntegrationType)
FieldMappingTransformation is a sealed class with subtypes: NoTransformation, StringTrimTransformation, DateFormatTransformation(String format), CurrencyConversionTransformation(String fromCurrency, String toCurrency)
FieldMapping.fromJson() correctly parses a Map<String, dynamic> from the JSONB column
FieldMapping.toJson() produces a Map<String, dynamic> that encodes all fields including nested transformation
Round-trip test passes: FieldMapping.fromJson(mapping.toJson()) == mapping for all transformation subtypes
FieldMappingValidator.validate(List<FieldMapping> mappings, IntegrationType type) returns a List<FieldMappingValidationError> — an empty list means valid
Validation checks: targetField must be in IntegrationTypeRegistry.getMetadata(type).availableMappingTargets; sourceField must be non-empty; duplicate targetField entries within same integration type produce a validation error
FieldMappingMigrator.migrate(List<dynamic> rawJson, int fromVersion) handles schema evolution — currently supports migrating from v0 (no version field) to v1 (with version field)
fromJson handles unknown transformation type gracefully by defaulting to NoTransformation and logging a warning (no throw)
All utilities are pure Dart with no Flutter or Supabase dependencies — usable in isolation

Technical Requirements

frameworks
Dart
data models
FieldMapping
FieldMappingTransformation
FieldMappingValidationError
IntegrationTypeRegistry
performance requirements
Serialization/deserialization of 100 FieldMapping objects must complete in under 10ms
FieldMappingValidator.validate() must be synchronous
security requirements
fromJson must not throw on malformed input — catch FormatException and return a default/safe FieldMapping
Validate that sourceField and targetField do not contain SQL injection characters (semicolons, quotes) before persisting

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

Place in lib/domain/integrations/field_mapping/. Use a sealed class (Dart 3) for FieldMappingTransformation with pattern matching in fromJson/toJson. Add a 'version' field to the JSONB structure (default 1) so future schema changes can be detected by FieldMappingMigrator. The migrator is the single place where legacy formats are handled — keeps the main fromJson clean.

Register FieldMappingValidator as a dependency of the UI form that configures mappings, so validation feedback is immediate before save. Keep FieldMapping and its utilities in the domain layer (no Supabase imports) — the repository layer handles serialization to/from Supabase rows using these utilities.

Testing Requirements

Write unit tests using flutter_test. Test: (1) round-trip serialization for all 4 transformation subtypes; (2) fromJson with unknown transformation type defaults to NoTransformation without throwing; (3) fromJson with null/missing optional fields uses defaults; (4) FieldMappingValidator returns empty list for valid mappings; (5) validation error for targetField not in registry targets; (6) validation error for duplicate targetField; (7) validation error for empty sourceField; (8) FieldMappingMigrator.migrate() converts v0 schema to v1 correctly; (9) equality check — two FieldMappings with same values are equal. Use fixture JSON maps as test inputs.

Component
Organization Integration Repository
data medium
Epic Risks (3)
high impact medium prob technical

Supabase Vault API has limited documentation for Dart/Flutter clients; wrapping it correctly for credential rotation and secret reference management may require significant trial and error, delaying the vault component and blocking all downstream credential-dependent work.

Mitigation & Contingency

Mitigation: Spike the Vault integration in the first sprint using a minimal proof-of-concept (store, retrieve, rotate one secret). Document the API surface before building the full vault client. Identify any missing Dart SDK bindings early.

Contingency: If Supabase Vault is too complex, fall back to Supabase's encrypted column approach (pgcrypto) for credential storage as a temporary measure, with a planned migration path to Vault once the API is understood.

high impact low prob security

Incorrect RLS policy configuration on organization_integrations could allow org admins of one organization to read or modify another organization's integration credentials, creating a serious data breach and compliance violation.

Mitigation & Contingency

Mitigation: Write integration tests that explicitly attempt cross-org data access using different JWT tokens and assert 0 rows returned. Include RLS policy review in PR checklist. Use Supabase's local development stack for policy validation before deployment.

Contingency: If a breach is discovered post-deployment, immediately revoke all integration credentials, rotate vault secrets, notify affected organizations, and apply emergency RLS patches.

medium impact medium prob technical

JSONB columns for field_mappings and sync_schedule lack database-level schema enforcement; AI-generated or malformed JSON could silently corrupt integration configurations, causing export failures that are hard to diagnose.

Mitigation & Contingency

Mitigation: Define TypeScript/Dart model classes with strict deserialization and validation. Add database check constraints or triggers that validate JSONB structure at write time. Version the JSONB schema to enable forward-compatible migrations.

Contingency: Build a repair script that scans organization_integrations for invalid JSONB and resets corrupted records to a safe default state, alerting the admin of the affected organization.