> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reflections.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# ADR-0021: Mobile API contracts via shared Zod schemas

> Centralize mobile-facing DTO schemas in a shared package and validate API responses at the boundary in the mobile app.

<Info>**Status:** Superseded **Date:** 2026-02-10 **Deciders:** Core team</Info>

<Note>
  This ADR has been superseded. Mobile schemas are retained for API backward compatibility, but the
  React Native client was removed in favor of a native Swift iOS app.
</Note>

## Context

The mobile app consumes APIs implemented in `apps/api`. Zod schemas are already used across the monorepo (`@reflection/schemas`) to validate external inputs and define domain-level contracts.

Mobile-specific concerns:

* API response shapes can drift; TypeScript types alone do not protect runtime behavior.
* Mobile should fail fast and explicitly when the backend returns unexpected payloads, rather than crashing later in UI rendering.
* A single canonical place for schemas avoids parallel/duplicated contract definitions.

Constraints:

* Keep dependency flow consistent with monorepo rules: apps depend on packages; packages must not depend on apps.
* Avoid speculative complexity (0-user mode): no heavy codegen or schema frameworks unless needed.

## Decision

Centralize mobile-facing DTO schemas in `@reflection/schemas` and validate API responses at the boundary in the mobile app:

* Define mobile DTO schemas in a dedicated module and export them via a dedicated package export path: `@reflection/schemas/mobile`.
* In the mobile app, parse API responses using shared Zod schemas so failures are explicit and testable.
* Add schema-level tests to lock contract shape and avoid accidental breaking changes.

## Alternatives considered

### Alternative 1: TypeScript-only types (no runtime validation)

Keep response typing in TS but do not validate payloads at runtime.

Pros:

* Lowest overhead at runtime.
* No additional parsing step.

Cons:

* Does not protect against backend drift or unexpected data.
* Failures occur downstream in UI code and are harder to debug.

Not chosen because runtime safety at the boundary is worth the small parsing overhead for mobile.

### Alternative 2: Define schemas inside the mobile app only

Keep mobile DTO schemas local to the app.

Pros:

* Faster iteration without touching shared packages.
* No need to coordinate releases across packages.

Cons:

* Duplicates contract definitions across the repo.
* Encourages divergence between server expectations and client assumptions.

Not chosen to keep a single canonical contract definition shared across apps.

### Alternative 3: Generate types/schemas from an OpenAPI spec

Establish OpenAPI as the source of truth and generate client/server bindings.

Pros:

* Stronger tooling and automated drift detection.
* Potentially improved docs and API discoverability.

Cons:

* Adds tooling and workflow complexity.
* Requires more upfront investment and maintenance.

Not chosen because it is not justified in 0-user mode; can be revisited if API surface area grows materially.

## Consequences

**Benefits:**

* Runtime validation at the boundary reduces undefined behavior in UI.
* Shared schema package keeps contracts centralized and reviewable.
* Easier to test and evolve contracts with clear ownership.

**Costs:**

* Parsing overhead (generally small for payload sizes).
* Requires maintaining a stable exported schema surface.

**Risks:**

* Schema changes could become blocked by mobile release cadence. Mitigation: version contracts carefully; prefer additive evolution; keep DTOs small and explicit.

## Related ADRs

* [ADR-0001: Monorepo and package boundaries](/decisions/adr-0001)
* [ADR-0002: Runtime and build standards](/decisions/adr-0002)
