Fuente de verdad de diseño. Cierra el cuestionario v1 (50 preguntas) y las rondas de debate 1–4 (agosto 2026). Los borradores v0.1–v0.3 quedan como narrativa de diseño; este registro es lo que citan la constitución, los estándares, los ADRs y las specs. Pendientes reales: P-1 fecha objetivo G1-Engage · P-2 abogado para revisión del paquete legal · P-3 precios unitarios (ejercicio comercial, no bloquea diseño).
A. Identidad y contactos
| ID | Decisión |
|---|---|
| DEC-A1 | contact_kind = person | company. Todo contacto puede ser persona natural o jurídica. Companies: legal_name, sin birth_date; los triggers de fecha aplican según kind. |
| DEC-A2 | Catálogo core.national_id_types v1: TODOS los países de Sudamérica (CL: RUT · AR: DNI/CUIT/CUIL · BR: CPF/CNPJ · UY: CI/RUT · PY: CI/RUC · BO: CI/NIT · PE: DNI/RUC/CE · EC: CI/RUC · CO: CC/CE/NIT · VE: CI/RIF · GY/SR: genérico) + passport + foreign_id. Cada tipo: país, kind aplicable (person/company), regex de formato, normalizador, algoritmo DV si existe. |
| DEC-A3 | Validación: formato + normalización SIEMPRE (rechazo si no cumple); dígito verificador donde exista algoritmo, con flag dv_validated. |
| DEC-A4 | Protección de national_id: masking por defecto en UI, permiso RBAC dedicado para valor completo, acceso auditado en core.audit_log. Estándar de clasificación de datos aplica la legislación más estricta entre países soportados (LGPD + Ley 21.719 como piso). Cifrado de columna: evaluable si un enterprise lo exige. |
| DEC-A5 | national_id opcional por defecto; requerible por configuración de tenant. |
| DEC-A6 | Duplicados (tenant, type, id): rechazo en creación directa; en importación masiva → cola de “merge sugerido” con revisión humana. Unicidad: índice único parcial por tenant. Mismo DNI en tenants distintos: permitido siempre. |
B. Modelo de datos y estándares
| ID | Decisión |
|---|---|
| DEC-B1 | Agrupación por schemas de Postgres: core.*, loyalty.*, messaging.*, crm.* (vía pgSchema de Drizzle). |
| DEC-B2 | Enums de negocio = tablas paramétricas SIEMPRE. Columnas estándar: code (clave de negocio), label, is_system, is_active, sort_order, metadata. FK por code texto. Catálogos cacheados (memoria+Redis); cero joins en caminos calientes. Los is_system generan los union types Zod/TS. Agregar fila ≠ agregar comportamiento: la API rechaza códigos no soportados por negocio. |
| DEC-B3 | Catálogos transversales viven en core (currencies, notification_channels, national_id_types); el resto en su schema. |
| DEC-B4 | Paramétricas extensibles por tenant: SÍ en crm.activity_types y loyalty.reward_types; NO en tipos de ledger ni estados de máquina. Regla explícita en data.md: extensible ⇔ el valor es taxonomía del negocio del tenant; nunca ⇔ el valor gobierna una máquina de estados o lógica del sistema. |
| DEC-B5 | Money: amount BIGINT unidades menores + currency_code FK ISO 4217. Nunca floats, nunca montos sin moneda. Puntos ≠ money (ledger propio). |
| DEC-B6 | F1 = mono-moneda por tenant. base_currency INMUTABLE post-creación (cambio solo vía proceso asistido de migración). Multi-moneda + FX difieren a F2 con su ADR. |
| DEC-B7 | Retención por plan (estándar de industria): tracked_events y sends detalle 13 meses (starter) / 25 meses (pro, cubre análisis YoY) / 37+ meses (enterprise). Export automático a Supabase Storage (NDJSON comprimido) antes de purgar partición; agregados estadísticos se conservan siempre. |
| DEC-B8 | Particionamiento por criterio (NO todo): RANGE mensual en core.tracked_events, messaging.sends, messaging.send_status_history, core.audit_log, core.usage_snapshots (+ evaluar outbox y ledger con datos reales). DDL en migraciones SQL custom; job pre-crea particiones N+2 meses; partición DEFAULT con alerta; spike pg_partman en Supabase. Queries sobre particionadas DEBEN incluir la partition key. |
C. Arquitectura de plataforma
| ID | Decisión |
|---|---|
| DEC-C1 | CQRS-lite ratificado (ADR-17): por comando, UNA transacción = estado + outbox + audit. Lecturas = proyecciones regenerables. Event sourcing completo DESCARTADO como norma general (los dominios append-only —ledger, metering, audit— ya lo son por naturaleza). |
| DEC-C2 | core.audit_log: diff completo old→new, actor tipado (user/member/api_key/system), correlation_id. Retención = política de events por plan, con mínimo legal aparte. Plataforma de auditoría “lo más completa posible” como principio. |
| DEC-C3 | Enmienda de constitución aprobada: DOS categorías nuevas de puerto — QueuePort y NotificationChannelPort. |
| DEC-C4 | Hexagonal SIN EXCEPCIÓN en todo el proyecto. El binding de adaptador se declara en el composition root de CADA módulo (makeDeps): módulos distintos pueden usar adaptadores distintos para el mismo puerto (ej. messaging→QStash, loyalty→Vercel Queues). Vendor nuevo sigue gateado por ADR. F1: todos los módulos sobre Vercel Queues. |
| DEC-C5 | Reintentos: estándar industria — n=5, backoff exponencial + jitter, DLQ. GARANTÍA DE EVIDENCIA: toda falla y todo agotamiento de reintentos queda persistido en core.dead_letters (payload, intentos, último error, estado: pending_review/replayed/discarded) con alerta a BetterStack y herramienta de replay en el backoffice Ops. Éxitos de alto volumen → métricas, no filas. |
| DEC-C6 | Idempotencia de consumidores: tabla core.processed_jobs estándar (dedupe key + TTL), obligatoria para todo worker. |
D. API
| ID | Decisión |
|---|---|
| DEC-D1 | Path canónico: https://api.softcrum.com/v1/{module}/{resource} (sin /api). |
| DEC-D2 | SIN aliases estilo Segment en v1: las rutas canónicas por módulo priman (mantenibilidad y contexto). /v1/core/track, /v1/core/identify, /v1/core/batch. Capa de compatibilidad Segment: solo si una integración real la exige (feature explícita futura). |
| DEC-D3 | Deprecación: ventana mínima 6 meses + header Sunset + changelog en Mintlify. |
| DEC-D4 | Rate limits por plan PUBLICADOS en docs (posicionamiento anti-opacidad). |
| DEC-D5 | Autorización unificada: cada endpoint declara EXACTAMENTE UN permiso {module}.{resource}.{action} → permisos se agrupan en roles → roles se asignan a usuarios Y a máquinas (API keys, clientes OAuth = “roles de máquina”). Scopes OAuth = bundles de permisos. Pantalla de consentimiento muestra permisos. Flujo authorization code (marketplace) se diseña en la spec, se implementa después. |
| DEC-D6 | Acceso de terceros SIN allowlist de IP obligatoria: auth por API keys + HMAC + rate limits. Allowlist de IP disponible como opción de seguridad extra por tenant, apagada por defecto. Write keys públicas (solo track) llegan con el widget en F1b; F1a server-side. |
| DEC-D7 | Separación Runtime API (SLO p95 <300 ms; track <100 ms; member reads <150 ms) / Management API (p95 <1 s), dentro de la convención por módulo. Presupuestos = ítems del DoD + k6 en certificación. |
E. Notificaciones
| ID | Decisión |
|---|---|
| DEC-E1 | Canales F1: email, in_app, webhook, push, SMS. F2: whatsapp, live_activity. MATIZ SMS: canal y puerto existen desde el día 1; el ADAPTADOR aterriza en F1b con ADR de proveedor (dependencia nueva + costos por mensaje + registro de remitentes por país). |
| DEC-E2 | Cascada de despacho: Nivel 0 plataforma → 1 tenant → 2 módulo → 3 evento → preferencias/consents/suppressions del destinatario. resolveChannels() como función pura en core. |
| DEC-E3 | Preference center del member por canal Y por categoría (transaccional/marketing/producto). Transaccional = no-opt-out. |
| DEC-E4 | Fallback entre canales (push falla → email tras X min): F2, configurable por evento. ANOTADO en roadmap. |
| DEC-E5 | Quiet hours default por tenant, override por campaña; frequency caps solo categoría marketing. |
| DEC-E6 | Live Activities (F2): casos de uso = actividades importantes en curso que informar al member (canjes/pedidos en progreso, hitos de programa). Requiere dev client Expo + módulo nativo → ADR cuando llegue. |
| DEC-E7 | Trazabilidad end-to-end: correlation_id desde evento origen hasta send_status_history (queued→sent→delivered→opened→clicked/bounced/complained/failed) y webhooks salientes. |
| DEC-E8 | Colas por canal con workers rate-limit-aware (token bucket por proveedor Y por tenant). Carril transaccional SIEMPRE prioridad sobre marketing. |
F. Experiencias
| ID | Decisión |
|---|---|
| DEC-F1 | Dos backoffices distintos: (1) Consola del tenant — clientes gestionan todos sus módulos (web + mobile); (2) Softcrum Ops — administración interna de la suite: tenants, planes/entitlements, enforcement configurable por métrica/tenant, impersonación con audit, flags, salud de colas/particiones/dead letters con replay. |
| DEC-F2 | Mobile white-label: primera propuesta = app única multi-tenant con theming runtime, ARQUITECTURADA para extenderse fácil al tier premium de binario dedicado con cuenta Apple/Google del cliente (config por tenant separada del código desde el día 1: EAS build profiles). Wallet passes como capa intermedia (F2). |
| DEC-F3 | Stack mobile: Expo + React Native (confirmado). Push: FCM/APNs. |
| DEC-F4 | Dominios escalonados: default subdominio {tenant}.softcrum.com; dominio custom = add-on pago; incluido en enterprise. |
| DEC-F5 | Portal member y widget consumen EXCLUSIVAMENTE la API pública vía packages/api-client (regla de oro headless). |
G. Metering, consumo y pricing
| ID | Decisión |
|---|---|
| DEC-G1 | core.usage_snapshots cada 30 min fijo para todos, con delta t1→t2. Dashboard contratado-vs-usado en Consola; alertas 80/90/100% por el propio sistema de notificaciones. |
| DEC-G2 | Enforcement por métrica CONFIGURABLE por tenant desde Softcrum Ops. Defaults: contactos = gracia+aviso; mensajes = duro al 110%; events = soft con overage. |
| DEC-G3 | Modelo de pricing estilo Vercel: precios unitarios publicados, cuotas incluidas por plan, consumo medido, panel de gasto proyectado, spend caps configurables por el tenant (self-service del enforcement). Base facturable: contacto accionable (marketable); histórico/frío gratis; sin ratchet; re-evaluación por ciclo en ambas direcciones. |
| DEC-G4 | Rating engine propio: al cierre del ciclo computa base + overages × precio unitario desde usage_snapshots → cobro variable vía Fintoc (tarjeta enrolada) / Paddle (usage-based) → LibreDTE para SII. El diseño DEBE soportarlo desde el día 1. |
| DEC-G5 | Add-on “frescura de datos”: paquete ÚNICO (reconciliación drift + RFM completo + recompute total de segmentos + snapshots analíticos) con tiers nocturno (default) / 12h / 6h / 3h / 1h. contact_balances es near-real-time SIEMPRE, no forma parte del add-on. |
H. Roadmap y alcance
| ID | Decisión |
|---|---|
| DEC-H1 | Re-secuenciamiento oficial de la suite: CRM + Fidelización es el primer módulo comercial; Tracker después. G1-Engage = design partner operando CRM+Fidelización end-to-end, luego crecimiento semanal. Fecha objetivo: P-1 pendiente. |
| DEC-H2 | ⚠️ SUPERADA por ADR-021 (2026-08-17): multi-programa es capacidad de primera clase en F1. Texto original: Multi-program: esquema-only en F1 — program_id en todas las tablas loyalty desde la primera migración + programa default auto-creado e invisible. Habilitación multi-programa = UI/validaciones, cero migración. (Criterio: menor dolor futuro para nosotros y los clientes.) |
| DEC-H3 | Costura pagos↔loyalty CONFIRMADA como requisito: canje mixto puntos+dinero es plus de contratación. F1 deja la costura (redemption con money_component nullable + evento de dominio); implementación con pagos en fase posterior. |
| DEC-H4 | Efecto apply_discount (motor de promociones) ratificado para F2. F1: rule_effect_types paramétrica abierta (costo cero). |
| DEC-H5 | Wallet passes (Apple/Google) ratificado para F2. ADR chico por librerías de firma. |
| DEC-H6 | Naming: NO se comercializan módulos como marcas separadas. Marca comercial = Softcrum Suite; módulos con nombres descriptivos. Sin registros INAPI por módulo. |
| DEC-H7 | Plantillas verticales como DATA (no código): taxonomías de eventos instalables + wizard de onboarding (elegir vertical o partir en blanco). El producto debe ser aplicable a cualquier industria (design partners de rubros diversos). Primera plantilla: suscripciones/servicios. |
I. Documentación y proceso
| ID | Decisión |
|---|---|
| DEC-I1 | Idioma: docs de repo (constitución, estándares, ADRs, specs) en INGLÉS. Mintlify BILINGÜE (EN/ES) con procesos, procedimientos y diagramas. Este material de debate (ES) = fuente. |
| DEC-I2 | Diagramas: skill diagram-design (cathrynlavery/diagram-design — validada: 27 tipos, HTML+SVG autocontenidos, onboarding de marca desde el sitio, export SVG/PNG para Mintlify). Fuentes HTML versionadas en el repo. |
| DEC-I3 | Mintlify-first: /docs del monorepo es la fuente de Mintlify; desde ahí se genera y evidencia todo el trabajo por módulo. Orden de generación: ver plan-generacion-documental-v1.md. |
| DEC-I4 | ADRs: serie única transversal (ADR-09+) en el mismo /docs (son genéricos a toda la plataforma). |
| DEC-I5 | DOS slices canónicos conviven: createInitiative (arquetipo comando síncrono) + trackEvent (arquetipo pipeline asíncrono). Cada task spec declara qué arquetipo sigue. |
| DEC-I6 | Referencia al piloto en toda la documentación: “design partner (vertical suscripciones/servicios)”. Sin nombres de empresas. |
J. Compliance y legal
| ID | Decisión |
|---|---|
| DEC-J1 | Softcrum = encargado de tratamiento (processor); tenant = responsable (controller). Estándar aplicable: el más estricto entre legislaciones de países soportados (piso: Ley 21.719 + LGPD). |
| DEC-J2 | Paquete legal COMPLETO se genera como borradores profesionales (lote 7 del plan): DPA, política de privacidad, ToS, RAT interno + generador por tenant, lista de subencargados, plantilla DPIA, anexo de medidas de seguridad, acta de designación de DPO (Daniel, provisional). TODO requiere revisión de abogado chileno antes de firmar/publicar (P-2). |
| DEC-J3 | Derecho de supresión: anonimizar transacciones del ledger, borrar perfil/eventos. Plazo comprometido ≤30 días, automatizado. Incorporado a políticas de la empresa como respaldo legal. |
| DEC-J4 | Runbook de brecha 72h obligatorio ANTES del lanzamiento comercial (bloqueante, análogo al tenant-restore pre-G1). |