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

# ADR-021 — Multi-programa desde el día uno

> DEC-H2 decidió que multi-programa sería solo de schema en F1: program_id en cada tabla de loyalty, sin superficie de consola ni de API. Este ADR revierte esa posición.

Estado: Propuesto · Fecha: 2026-08-17 · Supera: **DEC-H2** · Refs: OQ-LOY-07, ADR-011, ADR-016

> Traducción. Autoritativo: [`../../adr/adr-021-multi-program-from-day-one.md`](/adr/adr-021-multi-program-from-day-one).

## Contexto

DEC-H2 decidió que multi-programa sería **solo-esquema en F1**: `program_id` en todas las tablas de
loyalty desde la primera migración, un programa por defecto auto-creado e invisible para la UI y la
API v1, y la capacidad de crear más habilitada después como puro trabajo de UI. El razonamiento era
la complejidad de consola: cada pantalla, regla y reporte gana un selector de programa, y ningún
design partner lo había pedido.

Dos cosas cambiaron esa evaluación, y ambas vienen del owner:

1. **La demanda es probable el día uno, no después.** Un holding con dos marcas, una empresa con un
   programa B2C junto a uno B2B para distribuidores, o una campaña estacional que no debe contaminar
   el principal son situaciones corrientes. Descubrirlo en la primera reunión comercial y responder
   "después" es un negocio perdido.
2. **Es una palanca de pricing, no solo una feature.** La cantidad de programas es una dimensión de
   plan natural y honesta: el plan base incluye uno, y necesitar un segundo es una razón concreta
   para subir de tier. Una capacidad invisible no se puede vender; una visible y limitada genera la
   conversación de upgrade sola.

El argumento decisivo es la asimetría del arrepentimiento. El costo de esquema ya está pagado —
`program_id` está de todas formas. Lo que DEC-H2 difería era superficie de consola y de API, y esa
superficie solo se encarece a medida que se acumulan pantallas. Meter el selector en seis pantallas
ahora es más barato que retrofitearlo en treinta después.

## Decisión

**Multi-programa se entrega como capacidad de primera clase en F1.**

* Un programa es una **entidad visible y nombrada por el tenant** desde el primer release.
* Un tenant puede **crear, renombrar, activar y desactivar** programas por la consola y la Management
  API, sujeto a un entitlement.
* `program_id` se **expone en la API pública v1**. Cuando un request lo omite, se resuelve el
  programa por defecto del tenant — así una integración de un solo programa nunca tiene que saber que
  el concepto existe.
* Todo tenant sigue recibiendo un programa por defecto creado automáticamente al aprovisionarse, y
  exactamente un programa por tenant lleva `is_default = true`.
* **La cantidad de programas es un entitlement**, no una métrica medida: el plan declara cuántos
  incluye, y excederlo se bloquea en vez de facturarse como overage. Un tope duro es la forma
  correcta para una capacidad que el tenant elige adoptar, no para consumo que genera el
  comportamiento de sus clientes.
* La **agregación entre programas en reportería queda explícitamente fuera de alcance en F1**. Cada
  programa reporta sobre sí mismo. Agregar abre preguntas reales —de quién son los puntos, en qué
  moneda, con qué escalera de niveles— que merecen su propia decisión.
* Un contacto puede tener saldos, niveles y membresías en más de un programa a la vez. Los puntos,
  niveles y recompensas **nunca cruzan la frontera de un programa** (ADR-011 sin cambios).

## Consecuencias

**+** El modelo comercial gana una dimensión de upgrade honesta, que no cuesta nada medir y es fácil
de entender para un cliente.
**+** El modelo de dominio calza con lo que muestra la consola, así que no hay un período en que la
API esconde un concepto que el esquema ya tiene — la clase de bug donde un identificador "oculto" se
filtra por un mensaje de error o una exportación simplemente no puede ocurrir.
**+** Nunca se requiere una migración para habilitarlo, porque el esquema ya era correcto.

**−** La superficie de consola crece de inmediato: un selector de programa en las pantallas de
loyalty, y alcance por programa en cada reporte. Estimado en el orden de un feature spec adicional,
absorbido dentro de la entrega de la propia consola.
**−** Todo endpoint de loyalty debe resolver un programa, y todo test de loyalty gana un caso
multi-programa. La regla de resolución por defecto mantiene el camino común sin cambios.
**−** Las conversaciones de soporte ganan una dimensión más ("¿qué programa?"). Mitigado porque el
programa por defecto es invisible en la práctica para tenants de un solo programa.

## Trabajo de seguimiento

* FS-LOY-0001 reescrito: CRUD de programas, nombre visible para el tenant, verificación de
  entitlement, `program_id` expuesto en la API.
* PRD-LOY: multi-programa sale de los no-objetivos; la cantidad de programas entra al modelo
  comercial.
* ADR-016: la cantidad de programas se declara como dimensión de entitlement junto a las métricas
  medidas.
* Consola: selector de programa, como parte de su propio feature spec.

## Alternativas consideradas

**Mantener DEC-H2 como estaba** — lo más barato ahora, y el costo de esquema ya estaba hundido.
Perdió porque el costo diferido es superficie de consola, que crece monótonamente; diferirlo lo hace
estrictamente más caro, nunca más barato.

**Visible y nombrado, pero un solo programa por tenant en v1** — la opción intermedia. Arregla la
incomodidad del "concepto oculto" a casi ningún costo, pero deja la palanca comercial sin construir y
sigue exigiendo el trabajo del selector después. Optimiza por un ahorro que ADR-021 muestra que es
temporal.
