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

# customer-core

> customer-core is the layer that knows who a customer is. It resolves identities across the systems a company already runs, holds their attributes and their consent, records what they do, and computes which segments they belong to.

> customer-core is the layer that knows who a customer is. It resolves identities across the
> systems a company already runs, holds their attributes and their consent, records what they do,
> and computes which segments they belong to. Loyalty, messaging and CRM are all consumers of it.
> Nobody else in the suite owns a contact, and nothing else is allowed to.

## Who this is for

Nobody buys `core`. It has no console section of its own and no line on an invoice, and that is
the point: it is infrastructure the other three modules stand on. Its users are internal.

| Consumer              | Depends on core for                                                                           |
| --------------------- | --------------------------------------------------------------------------------------------- |
| **loyalty**           | The contact a program is about, the events its rules match, the segments its campaigns target |
| **messaging**         | Who to send to, on which channel, with what consent, and whether they are suppressed          |
| **crm**               | The 360 timeline, which is a merge over core's events plus the other modules' records         |
| **Any future module** | The same, without touching loyalty — which is precisely why this is a separate context        |

## The problem today

A company's customer data is scattered across a point of sale, an ecommerce, a billing system and
a spreadsheet, and the same person exists in each with a different key. Every engagement tool then
builds its own half-resolved copy, and the answers disagree.

ADR-009 states the structural argument: if profiles, events and segments live inside loyalty, then
the day a second module needs a segment we refactor loyalty to get it. Building the core first
costs one extra bounded context to govern and buys every future module for free.

There is a second, sharper problem specific to Latin America. Identity here is a national ID — RUT,
CPF, CUIT, CC — with a different format, a different check digit and a different legal status per
country, and it identifies both people and companies. Tools built elsewhere model a customer as a
person with an email. That mismatch is a real differentiator, not a localisation detail.

## What it does *(normative)*

* Holds **contacts** that may be a person or a company (DEC-A1), each optionally carrying a
  national ID validated for its country and type.
* **Resolves identity**: an anonymous visitor becomes a known contact, duplicates across systems
  converge, and merges are recorded and reversible in their consequences.
* Records **consent** as history, per channel, with proof and timestamp — never as a mutable flag.
* Ingests **behavioural events** through a public API that acknowledges in under 100 ms and
  processes asynchronously.
* Evaluates **segments** from a declarative DSL, incrementally, so membership changes emit events
  in near real time.
* Ships **vertical event taxonomies as installable data**, so a subscription business and a retailer
  start with a vocabulary that fits them (DEC-H7).
* Owns the **platform tables** every module needs: audit log, usage snapshots, processed jobs,
  dead letters, and the cross-cutting catalogs (currencies, national ID types, notification
  channels).
* Executes **erasure and portability** so the whole suite can honour a data subject's rights from
  one place.

## Non-goals *(normative)*

* **Not a CDP.** No warehouse sync, no reverse ETL, no arbitrary destination catalog. We ingest,
  resolve, segment and emit — that is the whole surface.
* **Not a marketing tool.** Core computes a segment; sending anything to it is `messaging`.
* **Not a customer service workspace.** Notes, activities and timelines are `crm`.
* **No automatic merging without evidence.** Bulk imports produce a review queue, never a silent
  merge (DEC-A6). A wrong merge is close to unrecoverable.
* **Not multi-region in F1.** The `cell_id` seam exists; routing tenants across cells does not.

## Success

| Measure                                                   | Target                                                                | By                       |
| --------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------ |
| `track` p95                                               | \<100 ms (fast-ack 202)                                               | certification, pre-G1    |
| Event to segment membership change                        | \<5 s p95                                                             | certification, pre-G1    |
| Identity resolution correctness on a seeded duplicate set | zero false merges                                                     | before G1                |
| National ID validation coverage                           | every South American country with a check-digit algorithm implemented | G1-Engage                |
| Erasure request executed end to end                       | ≤30 days, fully automated, zero manual steps                          | before commercial launch |

## Commercial shape

Core defines the billable base for the whole suite: the **marketable contact** (ADR-014). It also
produces `usage_snapshots` every 30 minutes (DEC-G1), which is what the rating engine bills from
and what the consumption dashboard reads.

It is never sold on its own. Its capabilities are gated indirectly — retention tiers on
`tracked_events`, the data-freshness add-on on full segment recomputation.

## Phases

| Phase   | Contents                                                                                                                                                                | Target                |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| **F1a** | Platform catalogs · contacts and national IDs · identity resolution · consents · ingestion pipeline · segment DSL v1 · audit log · job infrastructure · usage snapshots | G1-Engage, 2026-11-01 |
| **F1b** | Custom attribute definitions · CSV import with merge review · event taxonomies · public write keys for browser ingestion · erasure and portability automation           | post-G1               |
| **F2**  | Multi-region cell routing · Segment-compatibility layer if a real integration demands it                                                                                | 2027                  |

## Compliance and risk

Core is where the suite's regulatory exposure concentrates: it holds the personal data, the
consent record and the audit trail. Three obligations shape the design rather than sit beside it.

* **Consent is an entity, not a column.** Every grant and revocation is a row with proof and
  timestamp, because Ley 21.719 audits evidence, not policy.
* **The national ID is the most sensitive field in the platform.** Masked by default everywhere,
  full value behind a dedicated permission, every full read audit-logged (DEC-A4). The strictest
  applicable law across supported countries governs.
* **Erasure is orchestrated here.** Core deletes the profile and its events, and instructs loyalty
  to anonymize rather than destroy its ledger (DEC-J3). No other module decides this on its own.

The main technical risk is identity resolution: a false merge combines two real people, and
unwinding it is close to impossible. Every design choice here is biased toward refusing to merge
when uncertain.

## Dependencies

Postgres partitioning for `tracked_events` (ADR-018). Better Auth for both realms (ADR-010).
Upstash for rate limiting and the compiled-segment cache. `QueuePort` for the ingestion pipeline.
Core depends on **no other bounded context** — that is enforced, not aspirational.

## Open questions

| # | Question                                                                                                          | Decides | By                           |
| - | ----------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------- |
| 1 | Which vertical taxonomy ships second, after subscription-services?                                                | Daniel  | before FS-CORE-0012          |
| 2 | Does an anonymous visitor's event history survive if they never become known, or is it purged on a shorter clock? | Daniel  | before FS-CORE-0006 approval |

## Changelog

| Version | Date       | Change                                                   | Why | Author                 |
| ------- | ---------- | -------------------------------------------------------- | --- | ---------------------- |
| 0.1.0   | 2026-08-17 | Initial draft from the decision registry and module spec | —   | daniel + claude-opus-5 |
