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

# Decision Registry — CRM + Loyalty modules and cross-cutting standards (v1.0)

> The design source of truth. Closes the v1 questionnaire of 50 questions and debate rounds 1 to 4, August 2026.

> Translation. Authoritative: [`../../design/decision-registry-v1.md`](/design/decision-registry-v1).
>
> Design source of truth. Closes questionnaire v1 (50 questions) and debate rounds 1–4 (August 2026).
> Drafts v0.1–v0.3 remain design narrative; this registry is what the constitution, the standards,
> the ADRs and the specs cite.
> Real pending items: **P-1** ~~G1-Engage date~~ closed · **P-2** lawyer for the legal package ·
> **P-3** unit prices (commercial exercise, does not block design).

## A. Identity and contacts

| ID     | Decision                                                                                                                                                                                                                                                                                                                                                              |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-A1 | `contact_kind` = `person \| company`. Every contact may be a natural person or a legal entity. Companies: `legal_name`, no birth\_date; date triggers apply per kind.                                                                                                                                                                                                 |
| DEC-A2 | `core.national_id_types` v1 catalog: EVERY South American country (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: generic) + `passport` + `foreign_id`. Each type: country, applicable kind, format regex, normalizer, check-digit algorithm where one exists. |
| DEC-A3 | Validation: format and normalization ALWAYS (rejected if it does not comply); check digit where an algorithm exists, with a `dv_validated` flag.                                                                                                                                                                                                                      |
| DEC-A4 | `national_id` protection: masked by default in the UI, dedicated RBAC permission for the full value, audited access in `core.audit_log`. The data-classification standard applies the strictest law among supported countries (LGPD + Ley 21.719 as the floor). Column encryption: evaluable if an enterprise customer requires it.                                   |
| DEC-A5 | `national_id` optional by default; requirable by tenant configuration.                                                                                                                                                                                                                                                                                                |
| DEC-A6 | Duplicates (tenant, type, id): rejected on direct creation; on bulk import → a "suggested merge" queue with human review. Uniqueness: partial unique index per tenant. The same document across different tenants: always allowed.                                                                                                                                    |

## B. Data model and standards

| ID     | Decision                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-B1 | Grouping by Postgres schemas: `core.*`, `loyalty.*`, `messaging.*`, `crm.*` (via Drizzle's `pgSchema`). *Extended by ADR-022, which adds `identity`.*                                                                                                                                                                                                                                                                                     |
| DEC-B2 | Business enums = parametric tables ALWAYS. Standard columns: `code` (business key), `label`, `is_system`, `is_active`, `sort_order`, `metadata`. FK by text `code`. Catalogs cached (memory + Redis); zero joins on hot paths. `is_system` rows generate the Zod/TS union types. Adding a row ≠ adding behaviour: the API rejects codes the business does not support.                                                                    |
| DEC-B3 | Cross-cutting catalogs live in `core` (currencies, notification\_channels, national\_id\_types); the rest in their own schema.                                                                                                                                                                                                                                                                                                            |
| DEC-B4 | Tenant-extensible parametric tables: YES for `crm.activity_types` and `loyalty.reward_types`; NO for ledger types or state machines. Explicit rule in `data.md`: extensible ⇔ the value is the tenant's business taxonomy; never ⇔ the value governs a state machine or system logic.                                                                                                                                                     |
| DEC-B5 | Money: `amount` BIGINT minor units + `currency_code` FK ISO 4217. Never floats, never amounts without currency. Points ≠ money (own ledger).                                                                                                                                                                                                                                                                                              |
| DEC-B6 | F1 = single currency per tenant. `base_currency` IMMUTABLE after creation (change only via an assisted migration process). Multi-currency + FX deferred to F2 with its own ADR.                                                                                                                                                                                                                                                           |
| DEC-B7 | Retention per plan (industry standard): `tracked_events` and `sends` detail 13 months (starter) / 25 months (pro, covers YoY analysis) / 37+ months (enterprise). Automatic export to Supabase Storage (compressed NDJSON) before purging a partition; statistical aggregates kept forever.                                                                                                                                               |
| DEC-B8 | Partitioning by criterion (NOT everything): monthly RANGE on `core.tracked_events`, `messaging.sends`, `messaging.send_status_history`, `core.audit_log`, `core.usage_snapshots` (+ evaluate outbox and ledger with real data). DDL in custom SQL migrations; a job pre-creates partitions N+2 months; DEFAULT partition with an alert; pg\_partman spike on Supabase. Queries against partitioned tables MUST include the partition key. |

## C. Platform architecture

| ID     | Decision                                                                                                                                                                                                                                                                                                                                                      |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-C1 | CQRS-lite ratified (ADR-017): per command, ONE transaction = state + outbox + audit. Reads = rebuildable projections. Full event sourcing DISCARDED as a general norm (the append-only domains — ledger, metering, audit — already are by nature).                                                                                                            |
| DEC-C2 | `core.audit_log`: full old→new diff, typed actor (user/member/api\_key/system), correlation\_id. Retention = the events policy per plan, with the legal minimum applying separately. "The most complete possible audit platform" as a principle.                                                                                                              |
| DEC-C3 | Constitution amendment approved: TWO new port categories — `QueuePort` and `NotificationChannelPort`.                                                                                                                                                                                                                                                         |
| DEC-C4 | Hexagonal WITHOUT EXCEPTION across the whole project. Adapter binding is declared in EACH module's composition root (`makeDeps`): different modules may use different adapters for the same port (e.g. messaging→QStash, loyalty→Vercel Queues). A new vendor is still gated by an ADR. F1: every module on Vercel Queues.                                    |
| DEC-C5 | Retries: industry standard — n=5, exponential backoff + jitter, DLQ. EVIDENCE GUARANTEE: every failure and every exhausted retry is persisted in `core.dead_letters` (payload, attempts, last error, status: pending\_review/replayed/discarded) with a BetterStack alert and a replay tool in the Ops backoffice. High-volume successes → metrics, not rows. |
| DEC-C6 | Consumer idempotency: standard `core.processed_jobs` table (dedupe key + TTL), mandatory for every worker.                                                                                                                                                                                                                                                    |

## D. API

| ID     | Decision                                                                                                                                                                                                                                                                                                                                                                                   |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| DEC-D1 | Canonical path: `https://api.softcrum.com/v1/{module}/{resource}` (no `/api`).                                                                                                                                                                                                                                                                                                             |
| DEC-D2 | NO Segment-style aliases in v1: the canonical per-module routes prevail (maintainability and context). `/v1/core/track`, `/v1/core/identify`, `/v1/core/batch`. A Segment compatibility layer only if a real integration demands it.                                                                                                                                                       |
| DEC-D3 | Deprecation: minimum 6-month window + `Sunset` header + Mintlify changelog.                                                                                                                                                                                                                                                                                                                |
| DEC-D4 | Rate limits per plan PUBLISHED in the docs (anti-opacity positioning).                                                                                                                                                                                                                                                                                                                     |
| DEC-D5 | Unified authorization: every endpoint declares EXACTLY ONE permission `{module}.{resource}.{action}` → permissions group into roles → roles attach to users AND to machines (API keys, OAuth clients = "machine roles"). OAuth scopes = permission bundles. The consent screen shows permissions. The authorization-code flow (marketplace) is designed in the spec and implemented later. |
| DEC-D6 | Third-party access WITHOUT a mandatory IP allowlist: auth by API keys + HMAC + rate limits. An IP allowlist is available as extra per-tenant security, off by default. Public write keys (track only) arrive with the widget in F1b; F1a is server-side.                                                                                                                                   |
| DEC-D7 | Runtime API (p95 \<300 ms; track \<100 ms; member reads \<150 ms) / Management API (p95 \<1 s) separation, within the per-module convention. Budgets = DoD items + k6 in certification.                                                                                                                                                                                                    |

## E. Notifications

| ID     | Decision                                                                                                                                                                                                                                                  |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-E1 | F1 channels: email, in\_app, webhook, push, SMS. F2: whatsapp, live\_activity. SMS NUANCE: the channel and the port exist from day 1; the ADAPTER lands in F1b with a provider ADR (new dependency + per-message cost + per-country sender registration). |
| DEC-E2 | Dispatch cascade: level 0 platform → 1 tenant → 2 module → 3 event → recipient preferences/consents/suppressions. `resolveChannels()` as a pure function in core.                                                                                         |
| DEC-E3 | Member preference center by channel AND by category (transactional/marketing/product). Transactional = no opt-out.                                                                                                                                        |
| DEC-E4 | Cross-channel fallback (push fails → email after X min): F2, configurable per event. NOTED in the roadmap.                                                                                                                                                |
| DEC-E5 | Quiet hours default per tenant, override per campaign; frequency caps only for the marketing category.                                                                                                                                                    |
| DEC-E6 | Live Activities (F2): use cases = important ongoing activities to report to the member (redemptions or orders in progress, program milestones). Requires an Expo dev client + native module → ADR when it arrives.                                        |
| DEC-E7 | End-to-end traceability: correlation\_id from the origin event to send\_status\_history (queued→sent→delivered→opened→clicked/bounced/complained/failed) and outgoing webhooks.                                                                           |
| DEC-E8 | Per-channel queues with rate-limit-aware workers (token bucket per provider AND per tenant). The transactional rail ALWAYS outranks marketing.                                                                                                            |

## F. Experiences

| ID     | Decision                                                                                                                                                                                                                                                                                                                  |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-F1 | Two distinct backoffices: (1) **tenant console** — clients manage all their modules (web + mobile); (2) **Softcrum Ops** — internal administration of the suite: tenants, plans/entitlements, per-metric configurable enforcement, impersonation with audit, flags, health of queues/partitions/dead letters with replay. |
| DEC-F2 | Mobile white-label: first proposal = a single multi-tenant app with runtime theming, ARCHITECTED to extend easily to the premium tier of a dedicated binary under the client's Apple/Google account (per-tenant config separated from code from day 1: EAS build profiles). Wallet passes as the middle layer (F2).       |
| DEC-F3 | Mobile stack: Expo + React Native (confirmed). Push: FCM/APNs.                                                                                                                                                                                                                                                            |
| DEC-F4 | Tiered domains: default subdomain `{tenant}.softcrum.com`; custom domain = paid add-on; included at enterprise.                                                                                                                                                                                                           |
| DEC-F5 | The member portal and the widget consume the public API EXCLUSIVELY via `packages/api-client` (the golden headless rule).                                                                                                                                                                                                 |

## G. Metering, consumption and pricing

| ID     | Decision                                                                                                                                                                                                                                                                                                                         |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-G1 | `core.usage_snapshots` every 30 minutes for everyone, with a t1→t2 delta. Contracted-versus-used dashboard in the console; 80/90/100% alerts through the platform's own notification system.                                                                                                                                     |
| DEC-G2 | Per-metric enforcement CONFIGURABLE per tenant from Softcrum Ops. Defaults: contacts = grace + notice; messages = hard at 110%; events = soft with overage.                                                                                                                                                                      |
| DEC-G3 | Vercel-style pricing model: published unit prices, included allowances per plan, metered consumption, projected-spend panel, tenant-configurable spend caps (the self-service face of enforcement). Billable base: the marketable contact; historical/cold storage free; no ratchet; re-evaluated each cycle in both directions. |
| DEC-G4 | In-house rating engine: at cycle close computes `base + overages × unit price` from usage\_snapshots → variable charge via Fintoc (enrolled card) / Paddle (usage-based) → LibreDTE for the SII. The design MUST support it from day 1.                                                                                          |
| DEC-G5 | "Data freshness" add-on: a SINGLE package (drift reconciliation + full RFM + full segment recompute + analytical snapshots) with tiers nightly (default) / 12h / 6h / 3h / 1h. `contact_balances` is near-real-time ALWAYS and is not part of the add-on.                                                                        |

## H. Roadmap and scope

| ID     | Decision                                                                                                                                                                                                                                                                                           |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-H1 | **Official re-sequencing of the suite: CRM + Loyalty is the first commercial module; Tracker follows.** G1-Engage = design partner running CRM + Loyalty end to end, then weekly growth. Target date: **2026-11-01**.                                                                              |
| DEC-H2 | ⚠️ **SUPERSEDED by [ADR-021](/adr/adr-021-multi-program-from-day-one) (2026-08-17): multi-program is a first-class capability in F1.** Original text: multi-program schema-only in F1 — `program_id` on every loyalty table from the first migration + an auto-created, invisible default program. |
| DEC-H3 | Payments↔loyalty seam CONFIRMED as a requirement: mixed points + money redemption is a contract-winning feature. F1 leaves the seam (redemption with a nullable `money_component` + a domain event); implementation with payments in a later phase.                                                |
| DEC-H4 | `apply_discount` effect (promotions engine) ratified for F2. F1: `rule_effect_types` parametric and open (zero cost).                                                                                                                                                                              |
| DEC-H5 | Wallet passes (Apple/Google) ratified for F2. Small ADR for the signing libraries.                                                                                                                                                                                                                 |
| DEC-H6 | Naming: modules are NOT commercialised as separate brands. Commercial brand = Softcrum Suite; modules carry descriptive names. No per-module INAPI registrations.                                                                                                                                  |
| DEC-H7 | Vertical templates as DATA (not code): installable event taxonomies + an onboarding wizard (choose a vertical or start blank). The product must be applicable to any industry (design partners from diverse sectors). First template: subscriptions/services.                                      |

## I. Documentation and process

| ID     | Decision                                                                                                                                                                                                                      |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-I1 | Language: repository docs (constitution, standards, ADRs, specs) in ENGLISH. Mintlify BILINGUAL (EN/ES) with processes, procedures and diagrams. This debate material (ES) = source.                                          |
| DEC-I2 | Diagrams: the `diagram-design` skill (cathrynlavery/diagram-design — validated: 27 types, self-contained HTML+SVG, brand onboarding from the website, SVG/PNG export for Mintlify). HTML sources versioned in the repository. |
| DEC-I3 | Mintlify-first: the monorepo's `/docs` is the Mintlify source; everything per module is generated and evidenced from there. Generation order: see `documentation-plan-v1.md`.                                                 |
| DEC-I4 | ADRs: a single cross-cutting series (ADR-09+) in the same `/docs` (they are generic to the whole platform).                                                                                                                   |
| DEC-I5 | TWO canonical slices coexist: `createInitiative` (synchronous command archetype) + `trackEvent` (asynchronous pipeline archetype). Every task spec declares which archetype it follows.                                       |
| DEC-I6 | Pilot reference throughout the documentation: "design partner (subscriptions/services vertical)". No company names.                                                                                                           |

## J. Compliance and legal

| ID     | Decision                                                                                                                                                                                                                                                                                                                                                                    |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DEC-J1 | Softcrum = processor; tenant = controller. Applicable standard: the strictest among the laws of supported countries (floor: Ley 21.719 + LGPD).                                                                                                                                                                                                                             |
| DEC-J2 | The COMPLETE legal package is produced as professional drafts (batch 7 of the plan): DPA, privacy policy, ToS, internal RAT + per-tenant RAT generator, sub-processor list, DPIA template, annex of security measures, DPO designation record (Daniel, provisional). EVERYTHING requires review by a Chilean data-protection lawyer before signing or publishing (**P-2**). |
| DEC-J3 | Right to erasure: anonymize ledger transactions, delete profile and events. Committed execution ≤30 days, automated. Incorporated into company policy as legal backing.                                                                                                                                                                                                     |
| DEC-J4 | The 72-hour breach runbook is mandatory BEFORE commercial launch (blocking, analogous to tenant-restore pre-G1).                                                                                                                                                                                                                                                            |
