ADR-0003: Isolate providers behind ports and deterministic mocks
- Status: Accepted
- Date: 2026-09-19
- Scope: External-service integration
Context
Meal analysis, nutrition lookup, identity, subscriptions, messaging, and health integrations have different contracts, outages, data practices, and commercial terms. Product and domain code must not depend directly on vendor payloads.
Decision
- Define provider-independent ports and normalized results in shared provider/domain packages.
- Implement each vendor as an adapter selected by validated configuration.
- Supply deterministic synthetic mocks for local tests and development.
- Encode mock meal-analysis jobs as recognizable signed deterministic IDs so status polling remains
reproducible after a worker restart without process-local state or duplicate submission.
- Treat every provider response, callback, and identifier as untrusted.
- Record source/provenance and preserve a provider-independent manual path.
- Prevent production configuration from silently selecting a mock.
- Send only minimum necessary data and require security/privacy approval before a real adapter is enabled.
M0 includes provider interfaces and synthetic mocks. Real LogMeal, Spoonacular, RevenueCat, Cognito, notification, and health adapters are deferred.
Consequences
- Local work is repeatable and does not require credentials or external calls.
- Vendors can be changed without rewriting core use cases.
- Normalization may omit vendor-specific capability; extensions must remain deliberate.
- Mocks can drift from reality and therefore require adapter contract tests.
- A seam limits technical coupling but does not remove vendor privacy or availability risk.
Follow-up
- Add timeout, retry, circuit-breaker, idempotency, quota, and redaction behavior per adapter.
- Review data processing, retention, regions, subprocessors, deletion, and training terms.
- Test provider outage and malformed-response scenarios before beta.