Skip to content

Domain Service Boundaries

Barbelic app code should depend on domain APIs instead of knowing Supabase table details directly.

App-Facing Facade

src/react/services/barbelicApi.ts is the typed facade consumed by React controllers and app shells.

It delegates to:

  • domains/authProfileDomain.ts: auth state, current profile, onboarding profile data.
  • domains/workoutDomain.ts: workout/session/plan/daily condition mutations.
  • domains/catalogDomain.ts: exercise catalog, archetypes, aliases, details, Wodup mappings.
  • domains/importDomain.ts: Wodup JSONL upload, import start, import polling.
  • domains/statsDomain.ts: screen RPC packages and materialized stats read models.
  • domains/adminDomain.ts: admin/debug/export operations.

Repository Boundary

barbelicRepository.ts is the strict adapter for the current Supabase contract. It must not accept retired request shapes, silently skip missing RPCs, or synthesize successful writes.

General app screens must not call it directly. They go through barbelicApi.ts, whose exports are typed aliases to domain APIs rather than runtime capability checks or compatibility wrappers.

Raw table access remains allowed only inside repository/debug/admin paths, not inside ordinary screen controllers.

Current-Contract Rule

The application supports one deployed request shape per operation. A contract change is a coordinated database migration plus frontend release, not a new fallback branch.

  • Controllers and domains pass explicit camelCase DTOs.
  • Repository adapters reject unknown or retired input fields before issuing an RPC.
  • Repository adapters translate the accepted DTO to the database's snake_case wire shape once.
  • Database row/RPC response adapters translate snake_case output to view models once.
  • External-provider normalization is confined to the import boundary and never becomes an app ID alias.

Server receipt idempotency, revision checks, owner-scoped draft caching, and explicit retry are the current reliability mechanisms. They must not be used to reinterpret an old schema or turn a missing RPC into a synthetic success.

Enforced Import Rules

tests/react/frontendImportBoundaries.test.mjs scans src/react and fails when these rules regress:

  • UI screens and controllers must not import services/barbelicRepository.ts directly.
  • UI files under src/react/ui must stay presentational: no services/*, controllers/*, app.tsx, or appController.tsx imports.
  • Normal app-facing paths must not reference raw loader names such as loadDebugSnapshotRows, loadAdminCatalogRows, loadCalendarRows, or loadSessionDetailRows.
  • Mobile and desktop UI are separate platforms. ui/mobile, mobileApp.tsx, and mobileRoot.tsx must not import desktop code; ui/desktop, desktopApp.tsx, and desktopRoot.tsx must not import mobile code.
  • Shared UI under ui/shared must not import either platform-specific UI tree.

Allowed flow:

UI/screen props -> app controllers -> barbelicApi.ts -> domain services -> barbelicRepository.ts/RPC adapters.

Admin, debug, export, and import internals may still use raw loaders through their domain service modules, but ordinary app screens must stay behind domain APIs.

Next Extraction Steps

The domain module boundary is stable. Future extraction may move implementation from barbelicRepository.ts into lower-level domain repositories without changing React screens:

  1. Move catalog table reads/writes into domains/catalogRepository.ts. Done (v0.18.0 A03, #1330): catalog reads/writes live in domains/repositories/catalogRepository.ts with pure validation/mapping in domains/catalogCodec.ts; profile/onboarding reads/writes live in domains/repositories/profileRepository.ts with domains/profileCodec.ts, the narrow avatar-signing helper domains/profileAvatarSigning.ts, and the shared input-contract checks services/currentInputContract.ts.
  2. Move Wodup import batch reads/writes into domains/importRepository.ts.
  3. Move workout save/delete RPC wrappers into domains/workoutRepository.ts.
  4. Keep screen data behind RPC functions in domains/statsDomain.ts.

A01 extraction boundary (v0.18.0)

The A01 production wiring now uses G03 feature ports, bounded legacy repository ports and nine real domain repository destinations. See RPC transport and domain extraction for the exact moved functions, retry responsibilities, temporary adapters and A02–A06 handoff.