# TCN payments integration plan

## Decision
- Treat the current `/admin/payments` QR generator as an operator test harness, not the final production payment UX for vending machines.
- Production vending flow should integrate with the TCN machine protocol and let the machine render the buyer-facing QR on its own screen.

## Why
- TCN protocol `2.5V` states: `to scan QR codes additional hardware devices are necessary.`
- That wording applies to **machine-side QR scanning**, not to the machine displaying a QR on its screen for the buyer to scan with a phone.
- The payment section (`2.1.5 Integral exchange`, `FunCode=8000`) already defines a dynamic payment flow:
  - machine sends `MachineID`, `TradeNo`, `SlotNo`, `Price`, `NotityUrl`
  - server returns `CodeUrl`, `TradeNo`
- `CodeUrl` is described as the returned value used to generate the QR code.
- That is enough to proceed with integration planning without assuming extra scanner hardware.

## Intended production flow
1. Buyer selects product on TCN machine.
2. TCN machine requests Ballbox payment session using the TCN payment contract.
3. Ballbox creates a Mercado Pago QR order.
4. Ballbox maps the Mercado Pago output into the TCN response shape and returns `CodeUrl`.
5. TCN machine renders the QR on its screen.
6. Buyer scans with Mercado Pago app on phone.
7. Payment provider notifies Ballbox webhook.
8. Ballbox validates/persists approved payment.
9. TCN machine receives the success signal through the TCN-side notify/result path and dispenses product.

## Ballbox work now
### 1. Lock the machine-facing contract
- Define a Ballbox route for TCN `8000` payment-init requests.
- Define exact request/response mapping for:
  - `MachineID` -> Ballbox `vendingMachineId` or external machine identifier
  - `TradeNo` -> machine transaction id / canonical `externalReference`
  - `SlotNo`
  - `Price`
  - `NotityUrl`
  - response `CodeUrl`
- Confirm whether TCN expects raw payment URL, QR payload string, or a specific provider deep link in `CodeUrl`.

### 2. Define result/dispense handshake
- Map how Ballbox should signal payment success back into the TCN flow.
- Verify whether Ballbox must call `NotityUrl`, expose a callback endpoint, or rely on a polling/result interface in the broader TCN protocol set.
- Confirm how TCN links approved payment to dispense using `TradeNo` and/or `SlotNo`.

### 3. Normalize machine identity
- Decide the canonical mapping between TCN `MachineID` and Ballbox `VendingMachine`.
- Add any missing external-id field only if needed for clean lookup.

### 4. Keep admin QR page as a test tool
- `/admin/payments` remains useful for:
  - Mercado Pago config checks
  - live QR creation smoke tests
  - webhook validation
  - manual provider debugging
- Do not frame it as the final vending-machine payment UX.

## Unknowns still to close
- Exact payload expected inside TCN `CodeUrl`.
- Exact success callback / notify shape between Ballbox and TCN after payment approval.
- Whether machine-side polling (`4000`) participates in payment completion or only app-driven vend/load flows.
- Whether TCN needs additional payment-status endpoints beyond `8000` for a full dispense flow.

## Recommendation
- Next implementation slice should be a TCN adapter spec + stub endpoints, not more work on the standalone admin QR page.
- Keep Mercado Pago-native Ballbox routes as the provider layer underneath that adapter.

## Evidence
- `test-results/tcn-payment-protocol/Protocol 2.5V English version.pdf`
- `test-results/tcn-payment-protocol/findings-2026-04-23.md`


# Payments Implemented State

## Current Split
- Ballbox owns the admin surface, native MercadoPago webhook intake, and native QR order creation.
- `/notification/mercadopago` is the first-party MercadoPago QR webhook route that fetches the upstream order, ignores unsupported merchant-order topics, and persists approved orders.
- `/api/integrations/payments/orders` is the first-party QR order creation route.
- `/api/integrations/payments/sessions` lists Ballbox-local approved payment records plus native MercadoPago config status.
- `/admin/payments` now manages local approved payment sessions directly for reconciliation/correction and also generates live MercadoPago QR orders for arbitrary amounts or product-priced orders.
- The admin QR generator should now be treated as an operator test/debug harness for Mercado Pago and webhook validation, not as the final buyer-facing vending-machine payment UX.
- The QR generator accepts money values in major units with decimals (for example `15.00` or `1000.00`) and converts them to Mercado Pago minor units before submission.

## APIs
- `/api/admin/payments/operations`
- `/api/admin/payments/sessions`
- `/api/admin/payments/sessions/[sessionId]`
- `/api/integrations/payments/health`
- `/api/integrations/payments/sessions`
- `/api/integrations/payments/orders`
- `/notification/mercadopago`

## Persistence
- Ballbox persists approved payment records as `PaymentSession` rows in Ballbox Postgres.
- Native MercadoPago webhook intake fetches the upstream order, maps approved orders into the canonical Ballbox payment shape, and persists them locally.
- QR Code notifications use the upstream order fetch plus canonical-reference mapping as the acceptance gate.
- Admin operators can now create, update, and delete local `PaymentSession` rows for reconciliation.
- Post-`pnpm db:push` plus `pnpm db:seed` verification confirms Ballbox Postgres keeps canonical `PaymentSession.vendingMachineId` and does not expose a `PaymentSessionRef` table or `machineId` compatibility column.
- Payments admin session routes now share Prisma error classification through `lib/prisma-errors.ts` instead of importing those helpers from `lib/ballbox-store.ts`.
- Playwright now covers local `/admin/payments` create, edit, and delete flows with deterministic cleanup of E2E `PaymentSession` rows.

## Integration Contract
- Ballbox native MercadoPago webhook path is `/notification/mercadopago`.
- Ballbox native QR order creation path is `/api/integrations/payments/orders`.
- That route now also attaches a public `notification_url` so Mercado Pago sends QR order updates back to `/notification/mercadopago`.
- That route accepts an explicit amount for arbitrary charges or falls back to the Ballbox `Product.priceMinor` when the amount is omitted, which powers per-product QR generation in the admin UI.
- The order route rejects values below Mercado Pago's minimum charge (`15.00 ARS`) before calling the provider.
- QR webhook persistence now depends on the upstream order fetch plus canonical-reference mapping; merchant-order topic events are ignored.
- Legacy approved-callback path `/api/integrations/payments/approved` is removed as an operational integration and now returns `410 PAYMENTS_APPROVED_CALLBACK_REMOVED`.
- Native payment correlation requires canonical `externalReference` values shaped as `payment-vm_{vendingMachineId}-txn_{machineTxnId}`.
- `NEXT_PUBLIC_SITE_URL` is required if Ballbox should expose a concrete `recommendedMercadoPagoWebhookUrl`.

## Validation Status
- Host app now owns the native MercadoPago order creation + webhook persistence path inside Ballbox.
- Remaining gap is operational/manual: one real public webhook + one real approved payment persisted and visible in `/admin/payments`.
- Club revenue share is currently handled through scheduled manual settlements/bookkeeping; no provider-native split payout path is live.
- The admin surface includes a live QR generator preview for provider-level scan-and-pay validation, but production vending flow should move behind the TCN machine protocol instead of relying on that admin page.
- The webhook route is fetch-first: the webhook is just the trigger, and Ballbox verifies the order state by fetching Mercado Pago before persisting.
- TCN protocol review indicates the `additional hardware devices` warning applies to machine-side QR scanning, while the payment flow (`FunCode=8000`) returns `CodeUrl` for machine-screen QR display; see `docs/tcn-payments-integration-plan.md` and `test-results/tcn-payment-protocol/findings-2026-04-23.md`.
- Recent replay validation against two older live `ORD...` ids returned `MERCADOPAGO_ORDER_NOT_APPROVED_expired`; see `docs/mercadopago-webhook-replay-notes-2026-04-23.md` when resuming webhook persistence checks.

## Manual E2E Still Pending
- End-to-end payment validation now depends on Ballbox native MercadoPago webhook configuration, not just local admin CRUD.
- Before running the check, set:
  - Ballbox `BALLBOX_MERCADOPAGO_ACCESS_TOKEN`
  - Ballbox `BALLBOX_MERCADOPAGO_WEBHOOK_SECRET`
  - Ballbox `BALLBOX_MERCADOPAGO_EXTERNAL_POS_ID` (or enviar `externalPosId` por request)
  - public HTTPS exposure for Ballbox webhook endpoint `/notification/mercadopago`
- Acceptance for the manual check:
  - one real payment is approved upstream
  - MercadoPago reaches Ballbox webhook publicly
  - Ballbox fetches order details and records the approved payment locally
  - a `PaymentSession` row is persisted locally
  - the session is visible in `/admin/payments`
  - the exact public webhook URL and observed payload quirks are documented after the run


Updated #3 (pending → completed)

Review TCN 3rd-party payments manual from laptop

Copy the PDF from laptop into repo investigation artifacts near test-results, inspect contents, and answer whether QR can be displayed in-app, needs sticker, needs extra hardware, or blocks the approach.

Restructure payments plan around TCN integration and external questions

Add ordered plan steps in PLAN.md with links to supporting docs, including non-code tasks like questions for TCN sales/engineers and Mercado Pago webhook validation.

Review today's commits for payments/onboarding decisions

Inspect today's git commits to extract decisions made in parallel about payment model, TCN integration, and onboarding, then ask only remaining clarifying questions.


Leí los commits.

Lo que quedó decidido ahí
- **No split ahora.**
- Default actual: **Ballbox cobra** con flujo QR nativo de MP.
- **Liquidación a clubes manual/programada** por ahora.
- `PAY-4` queda como futuro: split nativo de MP recién después, si se justifica.
- El webhook quedó conceptualmente más simple:
  - trigger entra a Ballbox
  - Ballbox fetches order en MP
  - Ballbox persiste si está aprobada
- TCN sigue siendo:
  - QR en pantalla de la máquina
  - adapter propio por delante del provider layer de MP

Eso invalida bastante de la línea “una cuenta MP por club ahora”.
Hoy el plan repo dice otra cosa:
- **una cuenta cobradora central por ahora**
- settlements manuales
- split/payments automation después

Entonces mis dudas restantes son pocas, pero importantes:

## Dudas que me quedan

1. **¿Esto ya es decisión real de negocio o solo decisión técnica temporal del repo?**
   - O sea: ¿ya aceptaron internamente “Ballbox cobra y liquida manual” para las primeras 5?
   - ¿O sigue abierta la discusión y el repo quedó adelantado?

2. **Cuando dijiste “única por club”, eso quedó descartado para la primera etapa?**
   - porque los commits de hoy empujan lo contrario

3. **Las 5 máquinas iniciales son todas del mismo modelo comercial?**
   - todas con Ballbox cobrando y rindiendo al club
   - o algunas son “alquiler tipo Adidas” y otras revenue-share normal

4. **Qué tan formal tiene que ser la liquidación manual desde día 1?**
   - simple planilla + transferencia
   - o necesitan algo más serio:
     - cierre por período
     - comprobante por club
     - panel/export
     - aprobación interna

5. **La prioridad ahora es cuál de estas dos?**
   - A. cerrar bien el flujo técnico `TCN -> MP -> webhook -> persistencia`
   - B. diseñar el onboarding maestro club+máquina+pagos+settlement
   Mi sospecha: hay que hacer B en docs ya, aunque A siga siendo primer build.

6. **Querés que el “master plan” cubra solo la etapa inicial manual, o también la migración futura a split MP?**
   - mi recomendación: sí cubrir ambas, pero separadas en fases
   - si no, después se mezcla todo de nuevo

7. **Hay alguna promesa ya hecha a clubes sobre quién cobra?**
   - esto cambia mucho el plan social/onboarding
   - si no se prometió nada, el camino manual-centralizado gana mucho

## Mi lectura actual
El mejor camino ahora probablemente sea:

### Fase 1
- Ballbox cobra
- webhook a Ballbox
- TCN adapter
- settlement manual por club
- onboarding operativo simple

### Fase 2
- mejorar ledger/liquidación/reportes

### Fase 3
- evaluar split nativo MP si volumen/ops lo justifican

Si me confirmás esas 7 dudas, armo el RFC/master plan bien.
Y lo haría separado en 4 tracks:
- pagos técnicos
- TCN adapter
- onboarding club/máquina
- settlement/operación interna

Eso evita mezclar “cómo cobra” con “cómo dispensa la máquina”.


1. lo aceptamos como inicio, si
2. las maquinas siguen teniendo club. solo que cobramos nosotros
3. 3 si. 2 se alquilan a un cliente (Adidas) y ahi hay que guiar a ellos a cobrar a sus cuentas. Supongo que sabran manejar MP, pero no se cuanto maquinas chinas. No se como es la relacion/expectativas ahi, si nosotros solo alquilamos o tenemos que ayudarlos a configurar
4. informal
5. a
6. todo. entendiendo que por ahi no se haga split
7. no hay promesa. solo les interesa ganas igual o mas, sin facturar mas. el resto no es importante

me gusta el plan


**Considering response strategy**

I realize that I need to provide a concise answer. It might be helpful for me to propose some next steps for the user. Also, I think it’s important to ask any remaining questions they have about Adidas, just to ensure I cover everything. I want to make sure the user feels satisfied with the information I provide! Let's keep it clear and straightforward.

Perfecto. Ya quedó bastante claro.

Diagnóstico actualizado
- **Inicio aceptado:** Ballbox cobra para las primeras máquinas de clubes.
- **Relación club-máquina:** cada máquina sigue asociada a un club, aunque cobre Ballbox.
- **Excepción real:** 2 máquinas de Adidas/alquiler pueden necesitar **cuenta MP del cliente**, no Ballbox.
- **Liquidación inicial:** informal/manual está bien.
- **Prioridad inmediata:** flujo técnico `TCN -> MP -> webhook -> persistencia`.
- **No hay promesa** de “cobro directo del club”; solo importa que ganen igual o más sin complicar facturación.

Mi lectura
- Esto pide un plan con **dos modos operativos**, no uno:
  1. `ballbox_central_collection`
  2. `tenant_direct_collection` para alquiler/clientes tipo Adidas

Eso cambia bastante para mejor, porque evita forzar “cuenta por club” en todos los casos.
La complejidad per-account queda acotada al caso alquiler/enterprise.

## Recomendación fuerte
El master plan/RFC debería dejar explícito que Ballbox payments soporta **modos de cobro por máquina o por contrato**, no un solo modelo global.

Modelo inicial recomendado:

### Modo A — Ballbox cobra
Para clubes del piloto.
- Ballbox crea orden MP
- Ballbox recibe webhook
- Ballbox persiste venta
- Ballbox liquida al club manualmente

### Modo B — Cliente cobra directo
Para Adidas/alquiler/enterprise.
- la máquina sigue integrada vía Ballbox/TCN
- pero Ballbox crea la orden usando credenciales/config del cliente
- webhook igual puede llegar a Ballbox
- Ballbox persiste venta y reporta
- Ballbox no liquida revenue share del club porque no cobra ese dinero

Eso te deja:
- rollout rápido para 5 clubes
- camino enterprise para alquiler
- sin casarte hoy con split MP
- sin tener que diseñar “una cuenta por club” como regla general

## Lo único que todavía necesito aclarar
Solo quedan dudas del caso Adidas/alquiler:

1. **Las 2 máquinas de Adidas salen en esta primera ola o después?**
2. **En ese caso ustedes quieren ofrecer solo alquiler técnico, o también onboarding/config de pagos?**
   - mi recomendación: ofrecer al menos onboarding guiado, aunque no full soporte permanente
3. **Quieren que Ballbox reciba también webhook de esas cuentas cliente en el mismo endpoint?**
   - yo diría que sí, mismo endpoint, multi-config después
4. **Esas 2 máquinas necesitan el mismo flujo TCN/QR que las otras, o podrían tener alguna variante?**

## Qué haría ahora
Siguiente movimiento útil:
1. convertir esto en **RFC/master plan**
2. separar fases y modos operativos
3. dejar clarísimo:
   - qué hacemos ahora
   - qué no hacemos ahora
   - qué queda preparado para después

## Estructura sugerida del RFC
- contexto y decisión
- objetivos / no objetivos
- modos de cobro soportados
  - `ballbox_central_collection`
  - `tenant_direct_collection`
  - `future_marketplace_split`
- fase 1: piloto clubes
- fase 1b: alquiler/enterprise
- arquitectura técnica de pagos
- adapter TCN
- webhook model
- settlement manual
- onboarding social/operativo
- riesgos
- triggers para pasar a split MP

Si querés, lo armo ya.
Solo respondeme esas 4 dudas de Adidas y te lo dejo redondo.


modo b no nos importa controlarlo. si nos importa facilitarle instalacion a Adidas. sigue conveniendo hacerlo a traves de ballbox?

1. salen en la primera ola las 5
2. al menos guiado. no creo que hagamos mucho soporte
3. mismo todo
4. podrian ser como Adidas quiera, pero ellos y nos vamos a querer lo mas facil de hacer


**Considering user needs**

I think we need to provide a clear recommendation and possibly ask if the user has any additional requests. It might be effective to suggest a "yes" response through a ballot box format and outline the next steps. There’s a consideration to create documentation as well. The user is asking for something more conceptual, so I could offer to draft a Request for Comments (RFC) to streamline the discussion. Keeping it concise will be key!

Sí. Sigue conviniendo hacerlo a través de Ballbox.

Pero con una precisión clave:

- **TCN / vending flow / webhook / observabilidad**: sí, centralizado en Ballbox
- **control operativo de la cuenta MP del cliente**: no hace falta controlarlo ustedes

O sea, para Adidas el mejor modelo no es “Ballbox controla su cobro”.
Es:

- Ballbox integra la máquina
- Ballbox expone el mismo adapter TCN
- Ballbox recibe el mismo webhook
- Ballbox persiste eventos/pagos
- Adidas usa **sus propias credenciales/config de MP**
- ustedes los ayudan a dejarlo andando
- después el soporte de su cuenta MP es mostly problema de ellos

## Recomendación
Sí, mismo stack Ballbox para todos.

### Modo A — Ballbox cobra
- 3 clubes
- Ballbox token/POS/webhook
- liquidación manual a club

### Modo B — Tenant direct collection
- 2 máquinas Adidas
- mismo flujo técnico vía Ballbox
- pero Ballbox usa config MP de Adidas para esas máquinas
- webhook llega igual a Ballbox
- ustedes facilitan setup inicial
- no toman responsabilidad fuerte por operar su cuenta MP día a día

Eso es mejor que separar flows porque:
- un solo adapter TCN
- un solo webhook endpoint
- una sola capa de persistencia/reporting
- menos ramas raras en producto y soporte
- deja lista la arquitectura multi-merchant donde haga falta

## Lo importante a diseñar bien
No “una cuenta por club”.
Eso hoy no.

Lo correcto es:
- **payment owner mode por máquina o por contrato**
  - `BALLBOX`
  - `TENANT`

Y por cada máquina resolver:
- qué cuenta MP usar
- qué credenciales
- qué POS/external POS
- qué webhook secret/config aplica
- quién recibe liquidación fuera de Ballbox

## Por qué no conviene hacer Adidas por afuera de Ballbox
Si lo sacan de Ballbox:
- duplican setup
- pierden trazabilidad central
- complica soporte TCN
- complica saber si el pago aprobó pero no vendió
- complica analytics y auditoría
- complica migrar después

Si pasa por Ballbox:
- ustedes siguen siendo el cerebro de integración
- Adidas solo pone “la cuenta que cobra”

Ese es el punto correcto.

## Entonces el plan queda así
### Fase inicial
- mismo flujo Ballbox para las 5 máquinas
- 3 con `paymentOwner = BALLBOX`
- 2 con `paymentOwner = TENANT`

### Settlement
- solo aplica a las 3 de Ballbox-cobra
- informal/manual

### Adidas onboarding
- ustedes guían:
  - credenciales/token
  - webhook a Ballbox
  - POS/external POS
  - prueba real
- no prometen soporte continuo fuerte de MP

## Decisión importante
Sí conviene que el mismo webhook endpoint reciba todo.
Pero Ballbox va a necesitar identificar por máquina/orden:
- qué credenciales usar para fetch de la orden
- y quién era el owner de ese cobro

Eso hay que dejarlo en el RFC.

## Mi recomendación final
Master plan/RFC debe asumir:
- **un solo flujo técnico**
- **dos modos de owner de cobro**
- **split marketplace no ahora**
- **liquidación manual solo para máquinas Ballbox-owned**
- **tenant direct collection para alquiler/clientes enterprise**

Con esto ya no me quedan dudas fuertes.

Si querés, siguiente paso lo hago yo:
- armo el RFC/master plan en docs
- actualizo `PLAN.md`
- dejo fases, modos, onboarding y riesgos bien ordenados.


dale segui


todo

Write payments master plan RFC and align repo plan/docs

Create a master RFC covering Ballbox-central and tenant-direct collection modes, TCN adapter, onboarding, settlements, and rollout phases; update PLAN.md and related docs to align.


Created #4: Write payments master plan RFC and align repo plan/docs (pending)


# Docs Index

## How To Navigate
- `PLAN.md`: current repo execution state and next implementation steps
- `docs/next-steps-queue.md`: prioritized backlog with dependency states
- `docs/repo-map.md`: fast file-level entrypoint for each domain
- `docs/implemented-*.md`: shipped behavior only
- `docs/*-rfc.md`: proposed implementation slices
- `docs/*-plan.md`: route/product planning
- `docs/*-discovery*.md`: validation and research framing
- `docs/*-gap-analysis.md`: what Ballbox still needs to build
- `docs/maintainability-priorities-2026-03.md`: prioritized frontend/backend maintainability work for the next refactor cycle
- `docs/demo-iteration-mode.md`: rapid demo delivery model with anti-debt guardrails

## Operator Priority Path
1. `PLAN.md`
2. `docs/next-steps-queue.md`
3. `docs/repo-map.md`
4. `docs/demo-iteration-mode.md`
5. relevant `docs/implemented-*.md` for the touched domain

## Current Refactor Input
- `docs/maintainability-priorities-2026-03.md`

## Execution And Coordination
- `docs/next-steps-queue.md`
- `docs/repo-map.md`
- `docs/demo-iteration-mode.md`

## Implemented State
- `docs/implemented-host-app.md`
- `docs/implemented-network.md`
- `docs/implemented-payments.md`
- `docs/implemented-players.md`
- `docs/implemented-sports.md`
- `docs/implemented-tvs.md`

## Discovery And Strategy
- `docs/coaches-discovery-stage.md`
- `docs/coaches-form-current.md`
- `docs/atc-integration-discovery.md`
- `docs/coaches-opportunity-brief.md`
- `docs/coaches-research-repository.md`
- `docs/coaches-validation-checklist-2-weeks.md`
- `docs/coaches-solution-thesis.md`

## Current Build Docs
- `docs/classes-subroute-plan.md`
- `docs/classes-mvp-rfc.md`
- `docs/coaches-coordination-gap-analysis.md`
- `docs/atc-mock-integration-plan.md`
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`
- `docs/payments-club-settlement-strategy.md`


# Club settlement strategy

## Decision
- Use scheduled settlements and manual bookkeeping for now.
- Do not force Mercado Pago split payments into the current vending QR flow.
- Treat Mercado Pago native split as a future option, not the default operating model.

## Why this is the default
- Current Ballbox payments flow is QR/order-based at `/v1/orders`.
- Mercado Pago split docs point to marketplace / checkout flows, OAuth, and seller onboarding.
- That is a poor fit for a small pilot set of clubs and adds operational drag before the machine flow is stable.
- For the current stage, speed and correctness matter more than perfect payout automation.

## Current operating model
- Each vending machine belongs to one club/venue.
- Ballbox records gross sales as it already does.
- Club share is tracked off-platform for now.
- Payouts are settled on a fixed cadence:
  - weekly if volume is active
  - monthly if volume is low
- For the current pilot phase, manual bookkeeping is acceptable because we expect at most 5 clients.

## Minimal bookkeeping fields
Keep one settlement record per club per period.

Recommended fields:
- clubId
- venueId
- vendingMachineId
- periodStart
- periodEnd
- grossSalesMinor
- refundsMinor
- adjustmentsMinor
- clubShareBps
- clubShareMinor
- payoutMethod
- payoutReference
- paidAt
- notes
- approvedBy

Recommended rules:
- store percentages as basis points, not floats
- round once, at settlement time
- keep refunds and adjustments explicit
- never let manual edits overwrite raw sales totals

## Future option if we later automate

### Mercado Pago native split
Best if Ballbox later changes the buyer flow to a supported Mercado Pago checkout path.

Pros:
- native platform split
- less manual payout work
- one provider for collection and distribution

Cons:
- current QR vending flow does not map cleanly
- likely needs OAuth / seller onboarding
- adds commercial-team dependency
- more support burden around account linking, disputes, and credential rotation

Fit:
- only if we replatform the buyer payment flow to something MP split supports

## Decision triggers to revisit automation
Re-open automation when one or more is true:
- more than 5 clubs need payouts
- manual settlement becomes error-prone
- payout timing becomes a sales blocker
- club trust requires automated reconciliation
- a future buyer flow changes to a checkout model MP split actually supports

## Recommendation
- Keep manual scheduled settlements now.
- Build a clean settlement ledger and export path first.
- Revisit Mercado Pago native split only after machine payments are stable and the club count justifies it.


**Updating plan and documentation**

I'm thinking about creating an RFC and updating some plans and documents. It seems like a good step to clarify next steps and improve everything. Maybe I should also mention different modes in the documentation to keep things comprehensive. There’s a lot to consider, but I want to make sure I’m clear on everything before moving ahead. Let's take it step by step to ensure everything is well organized!

write

# Payments + machine rollout RFC

## Status
- Proposed operating plan for the first vending rollout.
- Use this as the master document for payment ownership modes, TCN integration, onboarding, and rollout sequencing.

## Decision summary
- Use one Ballbox-controlled technical flow for all vending machines.
- Support two payment-owner modes in that flow:
  - `BALLBOX`: Ballbox owns the Mercado Pago account that collects funds.
  - `TENANT`: the client/tenant owns the Mercado Pago account that collects funds.
- Default first rollout:
  - 3 club machines use `BALLBOX` collection.
  - 2 Adidas rental machines use `TENANT` collection.
- For `BALLBOX` collection, club revenue share is handled by informal/manual settlement at first.
- Do not block rollout on Mercado Pago native split or marketplace approval.
- Keep future split automation as an optional later track, not a prerequisite.

## Why this is the right first plan
- The immediate risk is not payout automation. The immediate risk is getting the machine payment path working end to end.
- TCN machine integration and Mercado Pago webhook persistence are still the highest-risk technical pieces.
- The first wave is small: 5 machines total.
- Manual settlement is acceptable for the 3 Ballbox-collected club machines.
- Adidas-style rental machines need easy setup more than Ballbox ownership of the funds.
- Running all machines through Ballbox keeps one integration surface, one webhook surface, and one observability path.

## Scope
### In scope
- TCN machine payment adapter
- Mercado Pago provider integration through Ballbox
- machine-level payment-owner mode selection
- Ballbox-collected club machines
- tenant-collected Adidas/client machines
- webhook handling through Ballbox
- manual settlement guidance for Ballbox-collected club machines
- onboarding steps that include non-code work

### Out of scope for this phase
- Mercado Pago marketplace/split as a requirement for launch
- fully automated club settlements
- self-serve onboarding for tenants/clubs
- long-term tenant MP support beyond guided setup

## Operating modes

### Mode A: `BALLBOX`
Use for the first 3 club machines.

Flow:
1. machine belongs to a club/venue
2. Ballbox creates the Mercado Pago order with Ballbox credentials
3. buyer pays by scanning the QR shown by the machine
4. Mercado Pago notifies Ballbox webhook
5. Ballbox fetches order details, verifies approval, persists payment
6. Ballbox later settles the club share manually

Properties:
- simplest first rollout
- Ballbox controls setup and debugging
- informal manual settlement is enough at this stage

### Mode B: `TENANT`
Use for the first 2 Adidas rental machines.

Flow:
1. machine belongs to a client/tenant contract
2. Ballbox creates the Mercado Pago order using tenant credentials/config
3. buyer pays by scanning the QR shown by the machine
4. Mercado Pago notifies the same Ballbox webhook endpoint
5. Ballbox fetches order details with the tenant-specific credentials, verifies approval, persists payment
6. tenant owns funds; Ballbox is not doing revenue-share settlement for those payments

Properties:
- Ballbox still owns the technical integration path
- tenant owns the collecting account
- Ballbox should provide guided setup, not heavy day-to-day support

## Why tenant-direct collection should still run through Ballbox
If Adidas/client collection is done outside Ballbox, Ballbox loses:
- unified TCN adapter behavior
- unified webhook and persistence behavior
- centralized debugging for payment-approved-but-no-vend cases
- shared analytics/reporting across machines
- cleaner future migration paths

The better boundary is:
- Ballbox owns the payment orchestration path
- tenant owns the payment account

## Architecture direction

### Core rule
Payment ownership should be resolved per machine or per contract, not globally.

### Required model concept
Each machine should resolve to something like:
- `paymentOwnerMode = BALLBOX | TENANT`
- payment config reference for Mercado Pago
- vending machine identity
- owning club/venue or tenant/customer relationship

### Provider-layer implication
Ballbox needs to choose the right Mercado Pago credentials/config before creating the order and before fetching webhook-triggered order details.

### Webhook implication
Keep one Ballbox webhook endpoint:
- `/notification/mercadopago`

But Ballbox must be able to determine which payment config applies when an event arrives.
That likely means preserving enough correlation to map:
- provider order / external reference -> vending machine -> payment owner mode -> MP config

## TCN integration direction
- TCN remains the machine-facing protocol.
- The machine should render the buyer-facing QR.
- Ballbox should implement the TCN payment adapter over the native Mercado Pago provider layer.
- The Ballbox admin QR page remains a test/debug harness, not the production machine UX.

Related docs:
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`

## Rollout phases

### Phase 0. Provider proof
Goal:
- prove Ballbox native Mercado Pago order + webhook persistence works publicly

Output:
- one real approved payment persisted locally

Related work:
- `OPS-1`
- `docs/mercadopago-webhook-replay-notes-2026-04-23.md`

### Phase 1. TCN contract closure
Goal:
- confirm TCN `CodeUrl` and approval/dispense handshake details with sales/engineering

Output:
- precise adapter contract

Related work:
- `PAY-3`
- `docs/tcn-payments-open-questions.md`

### Phase 2. Single technical path with two payment-owner modes
Goal:
- support the same machine flow for both Ballbox-collected and tenant-collected machines

Output:
- machine-level payment owner resolution
- machine-facing TCN adapter over provider layer
- webhook handling that can resolve the correct config

### Phase 3. Guided onboarding for first five machines
Goal:
- launch 3 club machines and 2 Adidas rental machines

Outputs:
- 3 machines on `BALLBOX`
- 2 machines on `TENANT`
- setup checklist followed per machine
- real payment test per machine/account context

### Phase 4. Informal settlement ops for Ballbox-collected clubs
Goal:
- settle club share simply without blocking rollout

Output:
- lightweight manual ledger/export/notes process

### Phase 5. Re-evaluate automation later
Goal:
- only after machine flow is stable, volume increases, or settlement pain becomes real

Possible future paths:
- better internal settlement tooling
- Mercado Pago split / marketplace if it fits the later buyer flow

## Onboarding plan

### Shared machine onboarding
For every machine:
1. identify machine owner mode: `BALLBOX` or `TENANT`
2. map machine to club/venue or tenant contract
3. map machine identifier between TCN and Ballbox
4. confirm product/pricing setup
5. confirm public webhook reachability from Ballbox
6. run one real payment test
7. confirm approval persistence and vend outcome once hardware exists

### Club-machine onboarding (`BALLBOX`)
Needed now for the first 3 machines:
- confirm machine belongs to one club/venue
- confirm commercial revenue-share terms outside code
- confirm Ballbox account is the collecting account
- note settlement percentage/rule outside the provider path
- after launch, settle informally on a fixed cadence

### Adidas/client onboarding (`TENANT`)
Needed now for the first 2 machines:
- confirm they want to collect in their own Mercado Pago account
- guide them through MP setup only enough to make the machine flow work
- confirm they configure Ballbox webhook endpoint in their MP account if required by the final provider setup
- confirm any required token/POS/external POS values
- run one real payment test with their account
- do not promise heavy ongoing support for their Mercado Pago operations

## Operational expectations
- Manual settlement is acceptable for Ballbox-collected club machines in the first wave.
- For tenant-collected machines, Ballbox is facilitating setup, not owning their payout operations.
- No promise exists that clubs must collect directly in their own account.
- Clubs mainly care about net outcome and avoiding extra invoicing burden, not about ownership of the payment rails themselves.

## Risks
### Technical
- TCN approval/dispense handshake still needs confirmation
- tenant-specific webhook/config resolution may require extra correlation fields
- real webhook validation is not fully closed yet

### Operational
- guided Adidas setup may still stall on account/POS/webhook details
- manual club settlements can become messy if volume rises fast
- support boundaries for tenant-owned MP accounts must stay explicit

## Non-goals to enforce
- do not build split-marketplace complexity into the first machine rollout
- do not treat per-club direct collection as the universal default
- do not overbuild settlement tooling before real machine payments work

## Success criteria
- one Ballbox-collected machine completes payment flow end to end
- one tenant-collected machine completes payment flow end to end
- Ballbox persists approved payments for both owner modes
- TCN machine-facing contract is documented and implemented without guessing
- first five machines have an onboarding checklist that can be repeated

## Related docs
- `PLAN.md`
- `docs/implemented-payments.md`
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`
- `docs/payments-club-settlement-strategy.md`
- `docs/mercadopago-webhook-replay-notes-2026-04-23.md`


Successfully wrote 9553 bytes to docs/payments-machine-rollout-rfc.md


edit

## Ordered Payments Track
1. Finish provider-level Mercado Pago proof without TCN hardware.
   - backlog: `OPS-1` in `docs/next-steps-queue.md`
   - docs: `docs/implemented-payments.md`, `docs/mercadopago-webhook-replay-notes-2026-04-23.md`
2. Ask TCN sales to confirm the remaining machine-contract questions with their engineers.
   - docs: `docs/tcn-payments-open-questions.md`, `docs/tcn-payments-integration-plan.md`
   - note: this is required because the machines are not here yet
3. Freeze the Ballbox <-> TCN adapter contract once those answers come back.
   - docs: `docs/tcn-payments-integration-plan.md`, `docs/tcn-payments-execution-plan.md`
4. Implement the TCN-facing adapter over the existing native Mercado Pago layer.
   - backlog: `PAY-3` in `docs/next-steps-queue.md`
   - docs: `docs/tcn-payments-execution-plan.md`
5. Validate on real TCN hardware once machines arrive.
   - docs: `docs/tcn-payments-execution-plan.md`
6. Revisit settlement automation only after the machine-facing payment flow is stable.
   - backlog: `PAY-4` in `docs/next-steps-queue.md`
   - doc: `docs/payments-club-settlement-strategy.md`

### Payments Track Docs
- Implemented provider layer: `docs/implemented-payments.md`
- TCN direction and target flow: `docs/tcn-payments-integration-plan.md`
- Open external questions: `docs/tcn-payments-open-questions.md`
- Ordered execution sequence: `docs/tcn-payments-execution-plan.md`
- Current Mercado Pago webhook blocker/evidence: `docs/mercadopago-webhook-replay-notes-2026-04-23.md`
- TCN protocol evidence artifact: `test-results/tcn-payment-protocol/findings-2026-04-23.md`

## Ordered Payments Track
1. Finish provider-level Mercado Pago proof without TCN hardware.
   - backlog: `OPS-1` in `docs/next-steps-queue.md`
   - docs: `docs/implemented-payments.md`, `docs/mercadopago-webhook-replay-notes-2026-04-23.md`
2. Ask TCN sales to confirm the remaining machine-contract questions with their engineers.
   - docs: `docs/tcn-payments-open-questions.md`, `docs/tcn-payments-integration-plan.md`
   - note: this is required because the machines are not here yet
3. Freeze the Ballbox <-> TCN adapter contract once those answers come back.
   - docs: `docs/tcn-payments-integration-plan.md`, `docs/tcn-payments-execution-plan.md`
4. Implement one machine payment flow with two owner modes.
   - `BALLBOX`: Ballbox-collected club machines
   - `TENANT`: tenant/client-collected machines such as Adidas rentals
   - backlog: `PAY-3` in `docs/next-steps-queue.md`
   - doc: `docs/payments-machine-rollout-rfc.md`
5. Use guided onboarding for the first wave of 5 machines.
   - first wave target: 3 `BALLBOX` machines + 2 `TENANT` machines
   - docs: `docs/payments-machine-rollout-rfc.md`, `docs/tcn-payments-execution-plan.md`
6. Keep club settlements informal/manual for Ballbox-collected machines until the machine path is stable and settlement pain is real.
   - backlog: `PAY-4` in `docs/next-steps-queue.md`
   - doc: `docs/payments-club-settlement-strategy.md`
7. Revisit automation later only if volume or ops pain justify it.
   - current future candidate: Mercado Pago split / marketplace

### Payments Track Docs
- Master rollout RFC: `docs/payments-machine-rollout-rfc.md`
- Implemented provider layer: `docs/implemented-payments.md`
- TCN direction and target flow: `docs/tcn-payments-integration-plan.md`
- Open external questions: `docs/tcn-payments-open-questions.md`
- Ordered execution sequence: `docs/tcn-payments-execution-plan.md`
- Club settlement strategy: `docs/payments-club-settlement-strategy.md`
- Current Mercado Pago webhook blocker/evidence: `docs/mercadopago-webhook-replay-notes-2026-04-23.md`
- TCN protocol evidence artifact: `test-results/tcn-payment-protocol/findings-2026-04-23.md`


Successfully replaced 1 block(s) in PLAN.md.

     ...
 210    - docs: `docs/tcn-payments-open-questions.md`, `docs/tcn-payments-integration-plan.md`
 211    - note: this is required because the machines are not here yet
 212 3. Freeze the Ballbox <-> TCN adapter contract once those answers come back.
 213    - docs: `docs/tcn-payments-integration-plan.md`, `docs/tcn-payments-execution-plan.md`
-214 4. Implement the TCN-facing adapter over the existing native Mercado Pago layer.
+214 4. Implement one machine payment flow with two owner modes.
+215    - `BALLBOX`: Ballbox-collected club machines
+216    - `TENANT`: tenant/client-collected machines such as Adidas rentals
 215    - backlog: `PAY-3` in `docs/next-steps-queue.md`
-216    - docs: `docs/tcn-payments-execution-plan.md`
-217 5. Validate on real TCN hardware once machines arrive.
-218    - docs: `docs/tcn-payments-execution-plan.md`
-219 6. Revisit settlement automation only after the machine-facing payment flow is stable.
+218    - doc: `docs/payments-machine-rollout-rfc.md`
+219 5. Use guided onboarding for the first wave of 5 machines.
+220    - first wave target: 3 `BALLBOX` machines + 2 `TENANT` machines
+221    - docs: `docs/payments-machine-rollout-rfc.md`, `docs/tcn-payments-execution-plan.md`
+222 6. Keep club settlements informal/manual for Ballbox-collected machines until the machine path is stable and settlement pain is real.
 220    - backlog: `PAY-4` in `docs/next-steps-queue.md`
 221    - doc: `docs/payments-club-settlement-strategy.md`
+225 7. Revisit automation later only if volume or ops pain justify it.
+226    - current future candidate: Mercado Pago split / marketplace
 222
 223 ### Payments Track Docs
+229 - Master rollout RFC: `docs/payments-machine-rollout-rfc.md`
 224 - Implemented provider layer: `docs/implemented-payments.md`
 225 - TCN direction and target flow: `docs/tcn-payments-integration-plan.md`
 226 - Open external questions: `docs/tcn-payments-open-questions.md`
 227 - Ordered execution sequence: `docs/tcn-payments-execution-plan.md`
+234 - Club settlement strategy: `docs/payments-club-settlement-strategy.md`
 228 - Current Mercado Pago webhook blocker/evidence: `docs/mercadopago-webhook-replay-notes-2026-04-23.md`
 229 - TCN protocol evidence artifact: `test-results/tcn-payment-protocol/findings-2026-04-23.md`
 230
 231 ### Product Continuation Constraints
     ...


## Current Build Docs
- `docs/classes-subroute-plan.md`
- `docs/classes-mvp-rfc.md`
- `docs/coaches-coordination-gap-analysis.md`
- `docs/atc-mock-integration-plan.md`
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`
- `docs/payments-club-settlement-strategy.md`

## Current Build Docs
- `docs/classes-subroute-plan.md`
- `docs/classes-mvp-rfc.md`
- `docs/coaches-coordination-gap-analysis.md`
- `docs/atc-mock-integration-plan.md`
- `docs/payments-machine-rollout-rfc.md`
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`
- `docs/payments-club-settlement-strategy.md`


Successfully replaced 1 block(s) in docs/index.md.

    ...
 48 - `docs/classes-subroute-plan.md`
 49 - `docs/classes-mvp-rfc.md`
 50 - `docs/coaches-coordination-gap-analysis.md`
 51 - `docs/atc-mock-integration-plan.md`
+52 - `docs/payments-machine-rollout-rfc.md`
 52 - `docs/tcn-payments-integration-plan.md`
 53 - `docs/tcn-payments-open-questions.md`
 54 - `docs/tcn-payments-execution-plan.md`
 55 - `docs/payments-club-settlement-strategy.md`


## Current operating model
- Each vending machine belongs to one club/venue.
- Ballbox records gross sales as it already does.
- Club share is tracked off-platform for now.
- Payouts are settled on a fixed cadence:
  - weekly if volume is active
  - monthly if volume is low
- For the current pilot phase, manual bookkeeping is acceptable because we expect at most 5 clients.

## Current operating model
- Each vending machine belongs to one club/venue or tenant contract.
- The first rollout uses two payment-owner modes documented in `docs/payments-machine-rollout-rfc.md`:
  - `BALLBOX`: Ballbox collects and later settles the club share manually.
  - `TENANT`: the tenant/client collects directly in their own Mercado Pago account; no Ballbox settlement is needed for those payments.
- Ballbox records gross sales as it already does.
- For `BALLBOX` machines, club share is tracked off-platform for now.
- Payouts for `BALLBOX` machines are settled on a fixed cadence:
  - weekly if volume is active
  - monthly if volume is low
- For the current pilot phase, manual bookkeeping is acceptable because we expect at most 5 machines in the first wave.

## Recommendation
- Keep manual scheduled settlements now.
- Build a clean settlement ledger and export path first.
- Revisit Mercado Pago native split only after machine payments are stable and the club count justifies it.

## Recommendation
- Keep manual scheduled settlements now for `BALLBOX` machines.
- Do not build settlement automation for `TENANT` machines because Ballbox is not the collector there.
- Build a clean settlement ledger and export path first.
- Revisit Mercado Pago native split only after machine payments are stable and the club count justifies it.


Successfully replaced 2 block(s) in docs/payments-club-settlement-strategy.md.

    ...
 11 - That is a poor fit for a small pilot set of clubs and adds operational drag before the machine flow is stable.
 12 - For the current stage, speed and correctness matter more than perfect payout automation.
 13
 14 ## Current operating model
-15 - Each vending machine belongs to one club/venue.
+15 - Each vending machine belongs to one club/venue or tenant contract.
+16 - The first rollout uses two payment-owner modes documented in `docs/payments-machine-rollout-rfc.md`:
+17   - `BALLBOX`: Ballbox collects and later settles the club share manually.
+18   - `TENANT`: the tenant/client collects directly in their own Mercado Pago account; no Ballbox settlement is needed for those payments.
 16 - Ballbox records gross sales as it already does.
-17 - Club share is tracked off-platform for now.
-18 - Payouts are settled on a fixed cadence:
+20 - For `BALLBOX` machines, club share is tracked off-platform for now.
+21 - Payouts for `BALLBOX` machines are settled on a fixed cadence:
 19   - weekly if volume is active
 20   - monthly if volume is low
-21 - For the current pilot phase, manual bookkeeping is acceptable because we expect at most 5 clients.
+24 - For the current pilot phase, manual bookkeeping is acceptable because we expect at most 5 machines in the first wave.
 22
 23 ## Minimal bookkeeping fields
 24 Keep one settlement record per club per period.
 25
    ...
 73 - club trust requires automated reconciliation
 74 - a future buyer flow changes to a checkout model MP split actually supports
 75
 76 ## Recommendation
-77 - Keep manual scheduled settlements now.
+80 - Keep manual scheduled settlements now for `BALLBOX` machines.
+81 - Do not build settlement automation for `TENANT` machines because Ballbox is not the collector there.
 78 - Build a clean settlement ledger and export path first.
 79 - Revisit Mercado Pago native split only after machine payments are stable and the club count justifies it.


## Validation Status
- Host app now owns the native MercadoPago order creation + webhook persistence path inside Ballbox.
- Remaining gap is operational/manual: one real public webhook + one real approved payment persisted and visible in `/admin/payments`.
- Club revenue share is currently handled through scheduled manual settlements/bookkeeping; no provider-native split payout path is live.
- The admin surface includes a live QR generator preview for provider-level scan-and-pay validation, but production vending flow should move behind the TCN machine protocol instead of relying on that admin page.
- The webhook route is fetch-first: the webhook is just the trigger, and Ballbox verifies the order state by fetching Mercado Pago before persisting.
- TCN protocol review indicates the `additional hardware devices` warning applies to machine-side QR scanning, while the payment flow (`FunCode=8000`) returns `CodeUrl` for machine-screen QR display; see `docs/tcn-payments-integration-plan.md` and `test-results/tcn-payment-protocol/findings-2026-04-23.md`.
- Recent replay validation against two older live `ORD...` ids returned `MERCADOPAGO_ORDER_NOT_APPROVED_expired`; see `docs/mercadopago-webhook-replay-notes-2026-04-23.md` when resuming webhook persistence checks.

## Validation Status
- Host app now owns the native MercadoPago order creation + webhook persistence path inside Ballbox.
- Remaining gap is operational/manual: one real public webhook + one real approved payment persisted and visible in `/admin/payments`.
- Club revenue share is currently handled through scheduled manual settlements/bookkeeping for Ballbox-collected machines; no provider-native split payout path is live.
- First rollout planning now assumes one shared technical flow with two payment-owner modes: `BALLBOX` for club machines Ballbox collects on, and `TENANT` for client-owned collection setups such as Adidas rental machines; see `docs/payments-machine-rollout-rfc.md`.
- The admin surface includes a live QR generator preview for provider-level scan-and-pay validation, but production vending flow should move behind the TCN machine protocol instead of relying on that admin page.
- The webhook route is fetch-first: the webhook is just the trigger, and Ballbox verifies the order state by fetching Mercado Pago before persisting.
- TCN protocol review indicates the `additional hardware devices` warning applies to machine-side QR scanning, while the payment flow (`FunCode=8000`) returns `CodeUrl` for machine-screen QR display; see `docs/tcn-payments-integration-plan.md` and `test-results/tcn-payment-protocol/findings-2026-04-23.md`.
- Recent replay validation against two older live `ORD...` ids returned `MERCADOPAGO_ORDER_NOT_APPROVED_expired`; see `docs/mercadopago-webhook-replay-notes-2026-04-23.md` when resuming webhook persistence checks.


Successfully replaced 1 block(s) in docs/implemented-payments.md.

    ...
 40
 41 ## Validation Status
 42 - Host app now owns the native MercadoPago order creation + webhook persistence path inside Ballbox.
 43 - Remaining gap is operational/manual: one real public webhook + one real approved payment persisted and visible in `/admin/payments`.
-44 - Club revenue share is currently handled through scheduled manual settlements/bookkeeping; no provider-native split payout path is live.
+44 - Club revenue share is currently handled through scheduled manual settlements/bookkeeping for Ballbox-collected machines; no provider-native split payout path is live.
+45 - First rollout planning now assumes one shared technical flow with two payment-owner modes: `BALLBOX` for club machines Ballbox collects on, and `TENANT` for client-owned collection setups such as Adidas rental machines; see `docs/payments-machine-rollout-rfc.md`.
 45 - The admin surface includes a live QR generator preview for provider-level scan-and-pay validation, but production vending flow should move behind the TCN machine protocol instead of relying on that admin page.
 46 - The webhook route is fetch-first: the webhook is just the trigger, and Ballbox verifies the order state by fetching Mercado Pago before persisting.
 47 - TCN protocol review indicates the `additional hardware devices` warning applies to machine-side QR scanning, while the payment flow (`FunCode=8000`) returns `CodeUrl` for machine-screen QR display; see `docs/tcn-payments-integration-plan.md` and `test-results/tcn-payment-protocol/findings-2026-04-23.md`.
 48 - Recent replay validation against two older live `ORD...` ids returned `MERCADOPAGO_ORDER_NOT_APPROVED_expired`; see `docs/mercadopago-webhook-replay-notes-2026-04-23.md` when resuming webhook persistence checks.
    ...


### PAY-3 TCN vending-machine adapter over native MercadoPago
- Priority: P1
- Status: ready
- Depends on: OPS-1, PAY-2
- Scope:
- define the Ballbox machine-facing adapter for TCN payment init (`FunCode=8000`) over the existing MercadoPago order-create route
- map TCN `MachineID`, `TradeNo`, `SlotNo`, `Price`, `NotityUrl`, and response `CodeUrl` to Ballbox-native payment fields
- define the payment-success handshake back to TCN so approved payments can unlock dispense
- keep `/admin/payments` positioned as an operator test/debug harness rather than the production vending UX
- document the exact adapter contract and remaining TCN unknowns before implementation
- Notes:
- TCN protocol evidence is documented in `docs/tcn-payments-integration-plan.md`
- do not assume extra scanner hardware for the buyer flow; the open question is adapter contract detail, not QR display feasibility
- club settlement automation can be revisited after the machine-facing flow is stable; manual bookkeeping is the current default
- Expected payoff: closes the actual machine integration path instead of overinvesting in the standalone admin QR surface

### PAY-3 TCN vending-machine adapter over native MercadoPago
- Priority: P1
- Status: ready
- Depends on: OPS-1, PAY-2
- Scope:
  - define the Ballbox machine-facing adapter for TCN payment init (`FunCode=8000`) over the existing MercadoPago order-create route
  - map TCN `MachineID`, `TradeNo`, `SlotNo`, `Price`, `NotityUrl`, and response `CodeUrl` to Ballbox-native payment fields
  - define the payment-success handshake back to TCN so approved payments can unlock dispense
  - support one shared machine payment flow with two payment-owner modes:
    - `BALLBOX` for club machines that Ballbox collects on
    - `TENANT` for customer-owned collection setups such as Adidas rental machines
  - keep `/admin/payments` positioned as an operator test/debug harness rather than the production vending UX
  - document the exact adapter contract and remaining TCN unknowns before implementation
- Notes:
  - TCN protocol evidence is documented in `docs/tcn-payments-integration-plan.md`
  - master rollout direction is documented in `docs/payments-machine-rollout-rfc.md`
  - do not assume extra scanner hardware for the buyer flow; the open question is adapter contract detail, not QR display feasibility
  - club settlement automation can be revisited after the machine-facing flow is stable; manual bookkeeping is the current default
- Expected payoff: closes the actual machine integration path without fragmenting Ballbox collection vs tenant-direct collection into separate technical stacks

### PAY-4 Mercado Pago native split for club revenue share
- Priority: P2
- Status: blocked
- Depends on: OPS-1, PAY-2, PAY-3
- Scope:
  - keep scheduled manual settlements as the current operating default for club revenue share
  - document Mercado Pago native split as the only future automation path under consideration for club payouts
  - if automation is ever chosen, define onboarding, credential storage, rotation, and support rules before implementation
  - capture the trigger conditions that justify leaving manual bookkeeping behind
- Notes:
  - Ballbox currently runs QR vending payments through the native Mercado Pago order/webhook flow, so split automation is a separate future decision
  - keep this behind real-world payments validation first (`OPS-1`) and machine-facing TCN adapter definition (`PAY-3`)
- Expected payoff: a clear path from manual settlements to a future Mercado Pago split if the machine flow and business volume justify it

### PAY-4 Mercado Pago native split for club revenue share
- Priority: P2
- Status: blocked
- Depends on: OPS-1, PAY-2, PAY-3
- Scope:
  - keep scheduled manual settlements as the current operating default for Ballbox-collected club machines
  - document Mercado Pago native split as the only future automation path under consideration for club payouts
  - if automation is ever chosen, define onboarding, credential storage, rotation, and support rules before implementation
  - capture the trigger conditions that justify leaving manual bookkeeping behind
- Notes:
  - Ballbox currently runs QR vending payments through the native Mercado Pago order/webhook flow, so split automation is a separate future decision
  - first-wave rollout uses mixed owner modes (`BALLBOX` + `TENANT`), and settlement work only applies to the `BALLBOX` side
  - keep this behind real-world payments validation first (`OPS-1`) and machine-facing TCN adapter definition (`PAY-3`)
- Expected payoff: a clear path from manual settlements to a future Mercado Pago split if the machine flow and business volume justify it


Could not find edits[0] in docs/next-steps-queue.md. The oldText must match exactly including all whitespace and newlines.


  - keep `lib/ballbox-store.ts` as minimal compatibility facade only
- Progress (2026-04-14): sports route/page callers and sports UI/test types now import direct sports backend modules; players route/page callers now import `lib/players-backend.ts` directly (plus `lib/network-backend-clubs.ts` for admin club list hydration); payments admin session routes now consume Prisma error helpers from `lib/prisma-errors.ts`; and network route/page callers now import direct network backend modules (`clubs`, `club-mutations`, `venues`, `vending-machines`) plus `lib/prisma-errors.ts`. Remaining scope continues with the same migration pattern for TVs and classes surfaces still reading via `lib/ballbox-store.ts`.
- Expected payoff: less coupling and better module discoverability

### ARCH-3 Test taxonomy split
- Priority: P1
- Status: ready
- Depends on: DOC-1 (done)
- Scope:
  - separate tests by intent: `contracts`, `unit`, `integration`
  - align `vitest.config.ts` includes with those layers
- Progress (2026-04-14): `vitest` include patterns now cover `tests/contracts`, `tests/unit`, and `tests/integration`; dedicated scripts now exist for each layer, and first unit moves landed (`network/route-helpers`, sports client config/state tests).
- Expected payoff: faster debugging and more intentional coverage growth

### PERF-1 TTFB focused pass
- Priority: P1
- Status: ready
- Depends on: OPS-1
- Scope:
  - measure `/classes` and `/admin` server timings
  - add only the cache/instrumentation changes justified by measurement
- Expected payoff: better responsiveness without blind cache complexity

### PAY-2 Full payments migration into Ballbox host app
- Priority: P1
- Status: completed
- Depends on: OPS-1
- Scope shipped:
  - native MercadoPago webhook + QR order lifecycle is now owned in Ballbox routes/lib
  - bridge-oriented operational status copy removed from health/docs/admin summary
  - legacy approved-callback route reduced to transitional compatibility only; native path is now the documented operational flow
- Evidence:
  - `/notification/mercadopago`
  - `/api/integrations/payments/orders`
  - `app/api/integrations/payments/health/route.ts`
  - `app/api/integrations/payments/sessions/route.ts`
  - `docs/implemented-payments.md`
- Expected payoff: one-repo payments ownership, simpler operations, faster debugging

### PAY-3 TCN vending-machine adapter over native MercadoPago
- Priority: P1
- Status: ready
- Depends on: OPS-1, PAY-2
- Scope:
  - define the Ballbox machine-facing adapter for TCN payment init (`FunCode=8000`) over the existing MercadoPago order-create route
  - map TCN `MachineID`, `TradeNo`, `SlotNo`, `Price`, `NotityUrl`, and response `CodeUrl` to Ballbox-native payment fields
  - define the payment-success handshake back to TCN so approved payments can unlock dispense
  - keep `/admin/payments` positioned as an operator test/debug harness rather than the production vending UX
  - document the exact adapter contract and remaining TCN unknowns before implementation
- Notes:
  - TCN protocol evidence is documented in `docs/tcn-payments-integration-plan.md`
  - do not assume extra scanner hardware for the buyer flow; the open question is adapter contract detail, not QR display feasibility
  - club settlement automation can be revisited after the machine-facing flow is stable; manual bookkeeping is the current default
- Expected payoff: closes the actual machine integration path instead of overinvesting in the standalone admin QR surface

## P2 Sequenced Refactors

### PAY-4 Mercado Pago native split for club revenue share
- Priority: P2
- Status: blocked
- Depends on: OPS-1, PAY-2, PAY-3
- Scope:
  - keep scheduled manual settlements as the current operating default for club revenue share
  - document Mercado Pago native split as the only future automation path under consideration for club payouts
  - if automation is ever chosen, define onboarding, credential storage, rotation, and support rules before implementation
  - capture the trigger conditions that justify leaving manual bookkeeping behind
- Notes:
  - Ballbox currently runs QR vending payments through the native Mercado Pago order/webhook flow, so split automation is a separate future decision
  - keep this behind real-world payments validation first (`OPS-1`) and machine-facing TCN adapter definition (`PAY-3`)
- Expected payoff: a clear path from manual settlements to a future Mercado Pago split if the machine flow and business volume justify it

### ARCH-4 Domain folder architecture
- Priority: P2
- Status: blocked
- Depends on: ARCH-2, ARCH-3
- Scope:
  - move flat prefix-based modules into domain folders in `lib/` and `components/`
  - preserve behavior; focus on discoverability and ownership boundaries
- Expected payoff: major readability improvement for future work

### ARCH-5 Route IA normalization (`/classes*` + `/coaches*`)
- Priority: P2
- Status: blocked
- Depends on: DOC-1
- Scope:
  - align route grouping and naming with real auth/surface behavior
  - keep redirects/aliases explicit during transition
- Expected payoff: lower confusion in feature placement and routing maintenance

### ARCH-6 Naming conventions and metadata cleanup

[8 more lines in file. Use offset=190 to continue.]


### PAY-3 TCN vending-machine adapter over native MercadoPago
- Priority: P1
- Status: ready
- Depends on: OPS-1, PAY-2
- Scope:
  - define the Ballbox machine-facing adapter for TCN payment init (`FunCode=8000`) over the existing MercadoPago order-create route
  - map TCN `MachineID`, `TradeNo`, `SlotNo`, `Price`, `NotityUrl`, and response `CodeUrl` to Ballbox-native payment fields
  - define the payment-success handshake back to TCN so approved payments can unlock dispense
  - keep `/admin/payments` positioned as an operator test/debug harness rather than the production vending UX
  - document the exact adapter contract and remaining TCN unknowns before implementation
- Notes:
  - TCN protocol evidence is documented in `docs/tcn-payments-integration-plan.md`
  - do not assume extra scanner hardware for the buyer flow; the open question is adapter contract detail, not QR display feasibility
  - club settlement automation can be revisited after the machine-facing flow is stable; manual bookkeeping is the current default
- Expected payoff: closes the actual machine integration path instead of overinvesting in the standalone admin QR surface


Successfully replaced 2 block(s) in docs/next-steps-queue.md.

     ...
 143 - Scope:
 144   - define the Ballbox machine-facing adapter for TCN payment init (`FunCode=8000`) over the existing MercadoPago order-create route
 145   - map TCN `MachineID`, `TradeNo`, `SlotNo`, `Price`, `NotityUrl`, and response `CodeUrl` to Ballbox-native payment fields
 146   - define the payment-success handshake back to TCN so approved payments can unlock dispense
+147   - support one shared machine payment flow with two payment-owner modes:
+148     - `BALLBOX` for club machines that Ballbox collects on
+149     - `TENANT` for customer-owned collection setups such as Adidas rental machines
 147   - keep `/admin/payments` positioned as an operator test/debug harness rather than the production vending UX
 148   - document the exact adapter contract and remaining TCN unknowns before implementation
 149 - Notes:
 150   - TCN protocol evidence is documented in `docs/tcn-payments-integration-plan.md`
+154   - master rollout direction is documented in `docs/payments-machine-rollout-rfc.md`
 151   - do not assume extra scanner hardware for the buyer flow; the open question is adapter contract detail, not QR display feasibility
 152   - club settlement automation can be revisited after the machine-facing flow is stable; manual bookkeeping is the current default
-153 - Expected payoff: closes the actual machine integration path instead of overinvesting in the standalone admin QR surface
+157 - Expected payoff: closes the actual machine integration path without fragmenting Ballbox collection vs tenant-direct collection into separate technical stacks
 154
 155 ## P2 Sequenced Refactors
 156
 157 ### PAY-4 Mercado Pago native split for club revenue share
 158 - Priority: P2
 159 - Status: blocked
 160 - Depends on: OPS-1, PAY-2, PAY-3
 161 - Scope:
-162   - keep scheduled manual settlements as the current operating default for club revenue share
+166   - keep scheduled manual settlements as the current operating default for Ballbox-collected club machines
 163   - document Mercado Pago native split as the only future automation path under consideration for club payouts
 164   - if automation is ever chosen, define onboarding, credential storage, rotation, and support rules before implementation
 165   - capture the trigger conditions that justify leaving manual bookkeeping behind
 166 - Notes:
 167   - Ballbox currently runs QR vending payments through the native Mercado Pago order/webhook flow, so split automation is a separate future decision
+172   - first-wave rollout uses mixed owner modes (`BALLBOX` + `TENANT`), and settlement work only applies to the `BALLBOX` side
 168   - keep this behind real-world payments validation first (`OPS-1`) and machine-facing TCN adapter definition (`PAY-3`)
 169 - Expected payoff: a clear path from manual settlements to a future Mercado Pago split if the machine flow and business volume justify it
 170
 171 ### ARCH-4 Domain folder architecture
     ...


Docs reference check passed for README.md, PLAN.md, and docs/index.md


bash

~/.agents/skills/memory-write/memory-write --type decision --subtype rollout_plan --scope project --title 'First machine rollout uses Ballbox and tenant collection modes' --content 'Ballbox payments rollout now assumes one shared technical machine-payment flow with two owner modes: BALLBOX for the first 3 club machines Ballbox collects on and settles manually, and TENANT for the first 2 Adidas rental machines that collect in their own Mercado Pago accounts with Ballbox providing guided setup only. Split/marketplace automation stays future-only.' --source-ref 'docs/payments-machine-rollout-rfc.md' --origin-agent personal-agent --metadata '{"repo":"ballbox"}'


First machine rollout uses Ballbox and tenant collection modes

Ballbox payments rollout now assumes one shared technical machine-payment flow with two owner modes: BALLBOX for the first 3 club machines Ballbox collects on and settles manually, and TENANT for the first 2 Adidas rental machines that collect in their own Mercado Pago accounts with Ballbox providing guided setup only. Split/marketplace automation stays future-only.

Summary: Ballbox payments rollout now assumes one shared technical machine-payment flow with two owner modes: BALLBOX for the first 3 club machines Ballbox collects on and settles manually…


Updated #4 (pending → completed)


Listo.

Creé
- `docs/payments-machine-rollout-rfc.md`

Actualicé
- `PLAN.md`
- `docs/index.md`
- `docs/payments-club-settlement-strategy.md`
- `docs/implemented-payments.md`
- `docs/next-steps-queue.md`

Validé
- `node scripts/check-doc-references.mjs` ✅

Qué quedó decidido en docs
- un solo flujo técnico vía Ballbox
- dos modos de owner de cobro:
  - `BALLBOX`
  - `TENANT`
- primera ola:
  - 3 máquinas club con `BALLBOX`
  - 2 máquinas Adidas con `TENANT`
- settlements manuales solo para `BALLBOX`
- split/marketplace queda futuro, no prerequisito
- Adidas pasa por Ballbox técnicamente, pero con soporte guiado y sin asumir operación pesada de su MP

Dónde mirar
- master plan: `docs/payments-machine-rollout-rfc.md`
- orden ejecutivo: `PLAN.md`
- backlog/dependencias: `docs/next-steps-queue.md`

También guardé memoria durable:
- `mem_de96b3b04d544628b1ab1f6a33d270c8`

Mi recomendación de siguiente paso
- aterrizar `PAY-3` en un spec más técnico:
  - modelo de datos mínimo para `paymentOwnerMode`
  - cómo resolver credenciales por máquina
  - cómo correlacionar webhook -> máquina -> config MP
  - endpoints TCN concretos

Si querés, sigo con eso ahora y te dejo el RFC técnico de implementación.


hace commit de esto y podes seguir


**Planning Git Commit Protocols**

I need to make sure local commits are allowed, which seems fine. So, I'll check the status before I proceed to create a technical RFC. The first steps appear to be a git status check followed by the commit. I'll keep it straightforward and ensure everything is set up properly. It's important to stay organized, especially when creating documentation like RFCs! Let's get this right from the start!

git status --short && git add PLAN.md docs/index.md docs/implemented-payments.md docs/next-steps-queue.md docs/payments-club-settlement-strategy.md docs/payments-machine-rollout-rfc.md && git commit -m "docs: add payments machine rollout master plan" && git status --short


 M PLAN.md
 M docs/implemented-payments.md
 M docs/index.md
 M docs/next-steps-queue.md
 M docs/payments-club-settlement-strategy.md
?? docs/payments-machine-rollout-rfc.md
[main 85457f5] docs: add payments machine rollout master plan
 6 files changed, 278 insertions(+), 13 deletions(-)
 create mode 100644 docs/payments-machine-rollout-rfc.md


**Inspecting commit changes**

I see that an interesting commit mentions that six files changed, but I wonder if some changes are not included or might be overlooked. I should take a closer look at the status of these files to confirm what's been modified and ensure I've got a complete picture. It's essential to verify everything. Let’s dig into the details and figure out what’s really going on with these changes.


(no output)


rg -n "externalReference|MercadoPago|mercadopago|notification_url|externalPosId|PaymentSession|vendingMachineId" app lib prisma tests -S | sed -n '1,240p'


# Payments + machine rollout RFC

## Status
- Proposed operating plan for the first vending rollout.
- Use this as the master document for payment ownership modes, TCN integration, onboarding, and rollout sequencing.

## Decision summary
- Use one Ballbox-controlled technical flow for all vending machines.
- Support two payment-owner modes in that flow:
  - `BALLBOX`: Ballbox owns the Mercado Pago account that collects funds.
  - `TENANT`: the client/tenant owns the Mercado Pago account that collects funds.
- Default first rollout:
  - 3 club machines use `BALLBOX` collection.
  - 2 Adidas rental machines use `TENANT` collection.
- For `BALLBOX` collection, club revenue share is handled by informal/manual settlement at first.
- Do not block rollout on Mercado Pago native split or marketplace approval.
- Keep future split automation as an optional later track, not a prerequisite.

## Why this is the right first plan
- The immediate risk is not payout automation. The immediate risk is getting the machine payment path working end to end.
- TCN machine integration and Mercado Pago webhook persistence are still the highest-risk technical pieces.
- The first wave is small: 5 machines total.
- Manual settlement is acceptable for the 3 Ballbox-collected club machines.
- Adidas-style rental machines need easy setup more than Ballbox ownership of the funds.
- Running all machines through Ballbox keeps one integration surface, one webhook surface, and one observability path.

## Scope
### In scope
- TCN machine payment adapter
- Mercado Pago provider integration through Ballbox
- machine-level payment-owner mode selection
- Ballbox-collected club machines
- tenant-collected Adidas/client machines
- webhook handling through Ballbox
- manual settlement guidance for Ballbox-collected club machines
- onboarding steps that include non-code work

### Out of scope for this phase
- Mercado Pago marketplace/split as a requirement for launch
- fully automated club settlements
- self-serve onboarding for tenants/clubs
- long-term tenant MP support beyond guided setup

## Operating modes

### Mode A: `BALLBOX`
Use for the first 3 club machines.

Flow:
1. machine belongs to a club/venue
2. Ballbox creates the Mercado Pago order with Ballbox credentials
3. buyer pays by scanning the QR shown by the machine
4. Mercado Pago notifies Ballbox webhook
5. Ballbox fetches order details, verifies approval, persists payment
6. Ballbox later settles the club share manually

Properties:
- simplest first rollout
- Ballbox controls setup and debugging
- informal manual settlement is enough at this stage

### Mode B: `TENANT`
Use for the first 2 Adidas rental machines.

Flow:
1. machine belongs to a client/tenant contract
2. Ballbox creates the Mercado Pago order using tenant credentials/config
3. buyer pays by scanning the QR shown by the machine
4. Mercado Pago notifies the same Ballbox webhook endpoint
5. Ballbox fetches order details with the tenant-specific credentials, verifies approval, persists payment
6. tenant owns funds; Ballbox is not doing revenue-share settlement for those payments

Properties:
- Ballbox still owns the technical integration path
- tenant owns the collecting account
- Ballbox should provide guided setup, not heavy day-to-day support

## Why tenant-direct collection should still run through Ballbox
If Adidas/client collection is done outside Ballbox, Ballbox loses:
- unified TCN adapter behavior
- unified webhook and persistence behavior
- centralized debugging for payment-approved-but-no-vend cases
- shared analytics/reporting across machines
- cleaner future migration paths

The better boundary is:
- Ballbox owns the payment orchestration path
- tenant owns the payment account

## Architecture direction

### Core rule
Payment ownership should be resolved per machine or per contract, not globally.

### Required model concept
Each machine should resolve to something like:
- `paymentOwnerMode = BALLBOX | TENANT`
- payment config reference for Mercado Pago
- vending machine identity
- owning club/venue or tenant/customer relationship

### Provider-layer implication
Ballbox needs to choose the right Mercado Pago credentials/config before creating the order and before fetching webhook-triggered order details.

### Webhook implication
Keep one Ballbox webhook endpoint:
- `/notification/mercadopago`

But Ballbox must be able to determine which payment config applies when an event arrives.
That likely means preserving enough correlation to map:
- provider order / external reference -> vending machine -> payment owner mode -> MP config

## TCN integration direction
- TCN remains the machine-facing protocol.
- The machine should render the buyer-facing QR.
- Ballbox should implement the TCN payment adapter over the native Mercado Pago provider layer.
- The Ballbox admin QR page remains a test/debug harness, not the production machine UX.

Related docs:
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`

## Rollout phases

### Phase 0. Provider proof
Goal:
- prove Ballbox native Mercado Pago order + webhook persistence works publicly

Output:
- one real approved payment persisted locally

Related work:
- `OPS-1`
- `docs/mercadopago-webhook-replay-notes-2026-04-23.md`

### Phase 1. TCN contract closure
Goal:
- confirm TCN `CodeUrl` and approval/dispense handshake details with sales/engineering

Output:
- precise adapter contract

Related work:
- `PAY-3`
- `docs/tcn-payments-open-questions.md`

### Phase 2. Single technical path with two payment-owner modes
Goal:
- support the same machine flow for both Ballbox-collected and tenant-collected machines

Output:
- machine-level payment owner resolution
- machine-facing TCN adapter over provider layer
- webhook handling that can resolve the correct config

### Phase 3. Guided onboarding for first five machines
Goal:
- launch 3 club machines and 2 Adidas rental machines

Outputs:
- 3 machines on `BALLBOX`
- 2 machines on `TENANT`
- setup checklist followed per machine
- real payment test per machine/account context

### Phase 4. Informal settlement ops for Ballbox-collected clubs
Goal:
- settle club share simply without blocking rollout

Output:
- lightweight manual ledger/export/notes process

### Phase 5. Re-evaluate automation later
Goal:
- only after machine flow is stable, volume increases, or settlement pain becomes real

Possible future paths:
- better internal settlement tooling
- Mercado Pago split / marketplace if it fits the later buyer flow

## Onboarding plan

### Shared machine onboarding
For every machine:
1. identify machine owner mode: `BALLBOX` or `TENANT`
2. map machine to club/venue or tenant contract
3. map machine identifier between TCN and Ballbox
4. confirm product/pricing setup
5. confirm public webhook reachability from Ballbox
6. run one real payment test
7. confirm approval persistence and vend outcome once hardware exists

### Club-machine onboarding (`BALLBOX`)
Needed now for the first 3 machines:
- confirm machine belongs to one club/venue
- confirm commercial revenue-share terms outside code
- confirm Ballbox account is the collecting account
- note settlement percentage/rule outside the provider path
- after launch, settle informally on a fixed cadence

### Adidas/client onboarding (`TENANT`)
Needed now for the first 2 machines:
- confirm they want to collect in their own Mercado Pago account
- guide them through MP setup only enough to make the machine flow work
- confirm they configure Ballbox webhook endpoint in their MP account if required by the final provider setup
- confirm any required token/POS/external POS values
- run one real payment test with their account
- do not promise heavy ongoing support for their Mercado Pago operations

## Operational expectations
- Manual settlement is acceptable for Ballbox-collected club machines in the first wave.
- For tenant-collected machines, Ballbox is facilitating setup, not owning their payout operations.
- No promise exists that clubs must collect directly in their own account.
- Clubs mainly care about net outcome and avoiding extra invoicing burden, not about ownership of the payment rails themselves.

## Risks
### Technical
- TCN approval/dispense handshake still needs confirmation
- tenant-specific webhook/config resolution may require extra correlation fields
- real webhook validation is not fully closed yet

### Operational
- guided Adidas setup may still stall on account/POS/webhook details
- manual club settlements can become messy if volume rises fast
- support boundaries for tenant-owned MP accounts must stay explicit

## Non-goals to enforce
- do not build split-marketplace complexity into the first machine rollout
- do not treat per-club direct collection as the universal default
- do not overbuild settlement tooling before real machine payments work

## Success criteria
- one Ballbox-collected machine completes payment flow end to end
- one tenant-collected machine completes payment flow end to end
- Ballbox persists approved payments for both owner modes
- TCN machine-facing contract is documented and implemented without guessing
- first five machines have an onboarding checklist that can be repeated

## Related docs
- `PLAN.md`
- `docs/implemented-payments.md`
- `docs/tcn-payments-integration-plan.md`
- `docs/tcn-payments-open-questions.md`
- `docs/tcn-payments-execution-plan.md`
- `docs/payments-club-settlement-strategy.md`
- `docs/mercadopago-webhook-replay-notes-2026-04-23.md`


# Repo Map

## Purpose
- Fast entrypoint for agents and maintainers to find the right files before editing.

## Top-Level Map
- `app/`: Next.js routes and API handlers.
- `components/`: UI clients and route-level presentation pieces.
- `lib/`: backend/domain modules, integration helpers, contracts, shared runtime helpers.
- `prisma/`: schema and seed sources.
- `tests/`: `contracts`, `unit`, `integration`, `e2e`, and support helpers.
- `docs/`: implemented state, discovery context, plans, and execution queue.

## Product Domains

### TVs
- UI surfaces: `app/admin/tvs`, `app/admin/screens`, `app/player/[screenId]/route.ts`
- APIs: `app/api/tvs/*`
- Backend: `lib/tvs-backend-*.ts`, `lib/tvs-player-runtime-core.ts`, `lib/tvs-runtime.ts`
- Implemented doc: `docs/implemented-tvs.md`

### Payments
- UI surface: `app/admin/payments`
- APIs: `app/api/admin/payments/*`, `app/api/integrations/payments/*`
- Backend: `lib/payments.ts`, `lib/payments-auth.ts`, `lib/shared-secret.ts`, `lib/integrations.ts`
- Implemented doc: `docs/implemented-payments.md`

### Network
- UI surface: `app/admin/network`
- APIs: `app/api/network*`
- Backend: `lib/network-backend-*.ts`
- Implemented doc: `docs/implemented-network.md`

### Sports / Classes / Coaches
- UI surfaces: `app/admin/sports`, `app/classes/*`, `app/classes-by-date`, `app/coaches/settings`
- APIs: `app/api/sports`, `app/api/classes/*`, `app/api/coaches/*`
- Backend: `lib/sports-backend-*.ts`, `lib/classes-backend.ts`, `lib/classes.ts`, `lib/coaches-backend.ts`
- Implemented doc: `docs/implemented-sports.md`

### Players
- UI surface: `app/admin/players`
- APIs: `app/api/players/*`
- Backend: `lib/players-backend.ts`
- Implemented doc: `docs/implemented-players.md`

## Shared Entry Docs
- `PLAN.md`: current state + active next-step queue pointer.
- `docs/index.md`: docs navigation index.
- `docs/demo-iteration-mode.md`: L1/L2/L3 demo delivery model.
- `docs/next-steps-queue.md`: prioritized backlog with dependency states.

## Shared HTTP Helpers
- Route JSON/envelope helpers: `lib/http/json.ts`, `lib/http/network-route-helpers.ts`, `lib/http/payments-route-helpers.ts`, `lib/http/players-route-helpers.ts`, `lib/http/sports-route-helpers.ts`