The repository is an npm workspace with three applications. They share a lockfile, not source code. Their only runtime contract is HTTP.
apps/
├── api/
│ ├── src/core/ # reusable API runtime
│ ├── src/modules/ # bounded business/technical areas
│ ├── src/providers/ # provider behaviour and wire vocabulary
│ ├── src/infrastructure/database/
│ ├── scripts/ # seed, scenario compiler, contract import
│ └── test/ # unit, property, conformance, integration
├── console/
│ ├── app/core/ # console gateway/table/format runtime
│ ├── app/modules/ # operator-facing feature definitions
│ ├── app/pages/ # thin routed pages
│ └── server/ # Nitro BFF and sealed console session
└── checkout/
├── app/core/ # checkout gateway and kit resolution
├── app/components/ # provider-neutral checkout shell
├── app/pages/ # provider-shaped buyer URLs
├── providers/ # provider-specific visual kits
└── server/ # Nitro BFF and separate buyer session
contracts/ # official provider contract imports
scenarios/ # editable canonical JSON scenarios
scripts/ # whole-stack acceptance smoke
docs/
├── README.md # bilingual documentation entry
├── en/ # English guides, fidelity and history
└── es/ # Spanish guides, fidelity and history
.agents/ # binding architecture rules
graphify-out/ # generated, historical discovery snapshot
#apps/api/src/core
Responsibility: behaviour that must be identical for every provider or every control-plane module.
| Directory | Owns |
|---|---|
core/providers/ |
ProviderPlugin, registry, canonical errors and static conformance |
core/idempotency/ |
request fingerprint, PostgreSQL advisory lock, replay/conflict |
core/money/ |
decimal/minor-unit conversion and fee arithmetic |
core/http/ |
app setup, list contract, pagination, provider exception shaping |
core/security/ |
access-token hashing, callers, roles and redaction |
Put code here only when it is genuinely shared runtime behaviour. A helper used by one module belongs to that module.
#apps/api/src/modules
Each directory owns one bounded area end to end. Important modules are:
| Module | Responsibility |
|---|---|
gateway |
provider request orchestration in the mandated order |
payments |
canonical intent lifecycle and the only payment write path |
ledger |
payment accounting, entries/postings and settlement |
applications |
tenants, one-time credentials, expiry and row scope |
users |
people, passwords, sessions and roles |
gateways |
installation-level enablement and accounting overrides |
checkout |
public buyer view and optional customer identity |
scenarios |
built-in/custom scenario matching and version resolution |
webhooks |
transactional outbox records and control-plane inspection |
traces |
redacted request timeline |
banking |
synthetic wallet funding and transfers |
banks |
the catalogue of institutions: prefix, digits, currencies |
bank-accounts |
external counterparties owned by users, each at a bank |
health |
unauthenticated health probe |
Controllers declare routes and DTOs; services perform multi-step work and use
MikroORM's EntityManager directly. Do not add repository interfaces,
aggregates, domain events or an application/domain/infrastructure split: this
project explicitly does not use DDD.
#Known layout deferral
The architecture binding describes future per-module models/, dto/,
services/ and controllers/ folders. The current tree still keeps all entities
centrally in src/infrastructure/database/entities/ and several modules are
flat. This is recorded in .agents/README.md. Match the
current owning module when adding behaviour; do not start a one-module folder
migration as part of an unrelated feature.
#apps/api/src/providers
Provider-specific HTTP truth belongs here: routes, contract validation, credentials, state/error vocabulary, webhook format and the two canonical/wire translations. Plugins are plain objects with no database, ledger or queue dependency.
mercadopago/andstripe/are routed implementations.paypal/routes OAuth, Orders v2 and selected Payments v2 operations.
Adding a provider also requires a registry row, conformance coverage, a fidelity document and—when it has a buyer surface—a checkout kit. Follow Adding a provider.
#Database files
- Entities:
apps/api/src/infrastructure/database/entities/ - Ordered migrations:
apps/api/src/infrastructure/database/migrations/ - Configuration:
apps/api/src/infrastructure/database/mikro-orm.config.ts - CLI entrypoint:
apps/api/src/cli/migrate.ts
Entities are the source model; migrations are explicit schema history. Never edit an already-applied migration to represent a new change.
#Nuxt console
apps/console/app/core/ is the console's reusable runtime. Pages and module
components use createRestGateway, useEntityCollection and RTable instead of
assembling API requests independently. Nitro routes under server/api/ are the
only browser-to-API path and forward the signed-in person's sealed session.
Place a new operator feature in the closest app/modules/<area>/; add a thin page
only when it needs a route, and expose the smallest matching Nitro endpoint. What
each piece of core/ owns — and the accessibility traps it exists to avoid — is
in the console.
#Nuxt checkout
Provider-neutral layout belongs in apps/checkout/app/components/. Provider
identity and flow belong in apps/checkout/providers/<id>/. The route pages map
provider URL shapes to a kit through app/core/kits.ts.
The checkout has its own Nitro session and secret. Do not import from the console or backend, and do not add PrimeVue here. See the checkout.
#Generated and historical files
apps/api/src/modules/scenarios/default-scenarios.tsis generated fromscenarios/**/*.json; edit the JSON and runnpm run scenario:compile.dist/,.nuxt/,.output/, coverage output andnode_modules/are build artifacts, not source.graphify-out/is generated discovery output from an older tree. Do not copy itssrc/...paths into current documentation without verifying them.- Root
src/contains only an old empty migration directory and is not the API source tree; active backend code is underapps/api/src/.