> ## 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.

# Spec de módulo — fidelización (schema loyalty)

> Evento → condiciones (atributos de perfil, pertenencia a segmento o nivel, agregados, frecuencia) → efectos (rule_effect_types paramétricos, seeds is_system: award_points, issue_coupon, send_webhook, trigger_campaign).

> Traducción. El inglés es la versión autoritativa: [`../../../modules/loyalty/spec.md`](/modules/loyalty/spec).

## Entidades e invariantes

| Tabla                                   | Invariantes clave                                                                                                                                                                                                                                        |
| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| programs                                | `program_id` en TODAS las tablas de loyalty desde la migración 1; nombrado por el tenant, CRUD completo, cantidad gateada por entitlement; programa por defecto auto-creado y resuelto cuando el request lo omite (ADR-021)                              |
| point\_currencies                       | ≥2 por programa: canjeable + estatus; nunca mezcladas (ADR-011)                                                                                                                                                                                          |
| ledger\_transactions                    | append-only; tipos paramétricos earn\|redeem\|expire\|revoke\|adjust; pending→available tras la ventana de devolución del tenant                                                                                                                         |
| point\_lots                             | consumo FIFO; expiración rolling\|end\_of\_month\|end\_of\_year, sobreescribible por nivel; escaneo de expiring\_soon (cron fan-out)                                                                                                                     |
| contact\_balances                       | proyección, MISMA transacción que la escritura del libro; reconciliación nocturna de drift (el add-on de frescura sube solo la frecuencia de la reconciliación)                                                                                          |
| rule\_campaigns / rules                 | versionadas; AST de condiciones (JSON) + efectos; presupuestos totales y por contacto; publicar invalida la caché de reglas compiladas                                                                                                                   |
| rewards                                 | `reward_types` paramétrico (extensible por tenant); `cost_points`; catálogo por programa                                                                                                                                                                 |
| coupon\_campaigns / coupon\_codes       | generación masiva de códigos únicos (F1b) o código genérico; estados issued→redeemed\|expired\|void                                                                                                                                                      |
| redemptions                             | padre/hijo desde el día 1; `Idempotency-Key` obligatorio; rollback a nivel de padre revert\|keep; `money_component` nullable (costura puntos + dinero, DEC-H3 — sin usar en F1)                                                                          |
| stacking\_rules                         | UI en F1b; política ALL vs PARTIAL; categorías de descuento y jerarquía; conjuntos no combinables                                                                                                                                                        |
| referral\_codes / referral\_conversions | recompensa doble liberada por evento calificante (primera compra PAGADA, nunca el registro); flags de fraude: auto-referido, velocidad, heurísticas de dispositivo/IP                                                                                    |
| tier\_definitions / tier\_memberships   | `qualification_metric`: points\_earned\|spend\|event\_count; ventana rolling\|calendar; política de descenso explícita + período de gracia; `tier_overrides` (multiplicadores de acumulación, precios de recompensas, expiración) — schema día 1, UI F1b |
| badges / challenges                     | schema reservado, F2 (gamificación estratégica: goal-gradient, endowed progress)                                                                                                                                                                         |

## Contrato del motor de reglas

Evento → condiciones (atributos de perfil, pertenencia a segmento o nivel, agregados, frecuencia) →
efectos (`rule_effect_types` paramétrico, semillas `is_system`: award\_points, issue\_coupon,
send\_webhook, trigger\_campaign; fila F2: apply\_discount según DEC-H4). Los efectos se deduplican
por (evento, regla) — idempotentes.

## Eventos emitidos

points.earned|redeemed|expired|adjusted|revoked · points.expiring\_soon ·
coupon.issued|redeemed|expired · referral.link\_created|converted · tier.upgraded|downgraded

## Endpoints (Runtime caliente: SLO \<300 ms)

`POST /v1/loyalty/redemptions` (loyalty.redemptions.create) ·
`POST /v1/loyalty/coupons/validate` (loyalty.coupons.validate) ·
`POST /v1/loyalty/qualifications` (loyalty.qualifications.read) ·
`GET /v1/loyalty/members/me` (token de member) ·
CRUD de gestión: campañas, reglas, recompensas, niveles, referidos (loyalty.\{resource}.\{action})
