# Account and Org NexusCRM Cutover

- Status: Blank-key incident repaired on `cjl`; broader full-active Account/Org cutover remains open
- Priority: P0
- Owner: Data Platform Finance
- Created: 2026-08-03
- Last updated: 2026-08-04
- Base SHA: `e96f9838edae9a640f2fb246debfd07c848d5295`
- Delivered repair SHA: `b823c031ad091421b4b72ecac287d7012b710524`
- Related branch: `cjl`
- Related Finance branch: `codex/account-org-nexuscrm-cutover`
- Related PR: Not created

## Objective

Make NexusCRM Account and Org the direct customer-identity authority, remove the
`stg_salesforce_account` / `stg_salesforce_org` compatibility dependency from
the canonical models, and prevent an active NexusCRM Org from disappearing
before Finance and NS consume it.

## Scope

- `salesforce_accounts` reads `nexuscrm.account` directly.
- `salesforce_orgs` reads `nexuscrm.org` directly and resolves duplicate tenant
  ids deterministically, preferring the row with an Account link.
- `customer_surrogate_keys` admits NexusCRM Org-only tenants that are absent
  from both existing Account links and the Cloud tenant registry.
- Generic dbt tests enforce direct source authority, full active source
  coverage, customer-key coverage, and unique nonblank tenant authority.
- Finance Account/Org materialization and NS delivery remain a separate deploy
  and terminal verification boundary.

## Evidence

### 2026-08-04 blank-key repair delivery

- `b823c031ad091421b4b72ecac287d7012b710524` is the exact deployed repair
  code commit and remains in `cjl` ancestry. The repair normalizes blank
  Account/Org identifiers, removes nondeterministic identity aggregation, and
  adds no-blank/no-empty-hash plus unique-instance tests.
- dbt Cloud run `70437513235149` built the focused production chain from that
  exact SHA and finished successfully at `2026-08-04 15:11:04 UTC`; its
  `run_results.json` has `16/16` successful models/tests.
- Two frozen-source candidate builds and the production relation share mapping
  fingerprint `-8392786627031688193`. Production has `163,935` rows,
  `162,826` distinct keys, zero blank identifiers, zero SHA256('') rows, and
  zero active Account/Org coverage gaps.
- Reviewed production mappings are stable: Elasti.ai -> `577e8337...`, Yi's
  Org -> `9be98b2d...`, and KickAss Products Pty Ltd -> `b06f6f1c...`.
- BigQuery rollback copies for the identity chain are retained for 30 days in
  `gcp-digital-bi.codex_customer_identity_backup` with suffix
  `20260804t1505z_blankkey` and an independently checked manifest.
- Finance Account/Org were staged together and swapped atomically. Live TiDB
  readback is Account `4,101`, Org `1,683`, with zero duplicate/blank keys and
  zero Org -> Account closure gaps. Exact rollback tables are
  `salesforce_account_pre_blankfix_20260804t1516z` (`4,028`) and
  `salesforce_org_pre_blankfix_20260804t1516z` (`1,681`). Finance run
  `finance-load-20260804T152901Z-98edca06` independently reloaded Account and
  Org; Account was `success`, while Org produced only the expected row-count
  growth warning (`1,321` prior baseline -> `1,683` current), not a blocker.

This closes the blank-input nondeterminism and the three named customer
mappings. It does not close the broader all-active Org/NS-delivery criteria
below.

- The 2026-08-03 readiness evidence below is superseded for production
  admission. Production run `70437513149178` on 2026-08-04 generated
  SHA256('') from blank NexusCRM tenant ids and moved that key between
  customers under nondeterministic aggregation. Finance run
  `finance-load-20260804T142331Z-9c0d5cb9` correctly blocked before writes.
- The repair must normalize blank identifiers before grouping, eliminate
  `ANY_VALUE` from identity selection, reject SHA256(''), refresh the persisted
  key impact census, and bind new PASS evidence to the repaired git head and
  dbt run. The historical counts below remain evidence for the earlier head,
  not current acceptance.

- RED on the production relations before implementation:
  - direct dependency failures: `4`
  - active NexusCRM Org ids missing from customer keys: `27`
  - duplicate nonblank canonical tenant ids: `2`
- Candidate BigQuery dry-run processed `25,906,022` bytes.
- Candidate read-only reconciliation:
  - active NexusCRM Org ids missing from canonical Org: `0`
  - active NexusCRM Account ids missing from canonical Account: `0`
  - active NexusCRM Org ids missing from candidate customer keys: `0`
  - new instance keys: `27`
  - missing existing instance keys: `0`
  - changed existing instance keys: `0`
  - June incident Org coverage: `84/84` in canonical Org and customer keys
- Sandbox `gcp-digital-bi.codex_account_org_nexuscrm_20260803` built at
  2026-08-03 12:56 CST with 72-hour expiration:
  - `salesforce_orgs`: view
  - `salesforce_accounts`: view
  - `customer_surrogate_keys`: table, `163,446` rows
  - focused dbt tests: `5/5 PASS`

## Required Follow-Ups

- Prove the broader all-active Org cohort and the June `84/84` set in the
  formal downstream AR/NS consumer; current Finance success proves its bounded
  eligible Account/Org projection, not NS writer acceptance.
- Add key-to-customer ownership validation and explicit SHA256('') rejection to
  the Finance preflight guard, and persist blocked table audits outside the
  target-write transaction so a blocked first table cannot disappear from the
  run summary.

## Acceptance Criteria

- No blank Account/tenant/customer identifier and no SHA256('') key exists in
  the production customer-key output.
- Two builds over one frozen source snapshot produce the same instance-to-key
  mapping hash.
- Elasti.ai, Yi's Org, and KickAss Products resolve to their reviewed keys in
  both dbt output and Finance Account/Org targets after coordinated migration.

- Production compiled `salesforce_accounts` and `salesforce_orgs` have direct
  NexusCRM source dependencies and no direct `stg_salesforce_*` dependency.
- All five focused production dbt tests pass on the released SHA.
- Active NexusCRM Org and Account coverage gaps are zero.
- Existing distinct instance keys are neither removed nor changed; the 27 new
  Org-only instances are present.
- Finance target readback contains every active nonblank NexusCRM Org exactly
  once, including the June incident set, and the downstream consumer no longer
  rejects those rows as unknown Org ids.

## Notes

The four June partner-child Orgs had no Account link or direct billing row. The
paired Finance change therefore admits all active nonblank NexusCRM Orgs instead
of relying on Account/billing eligibility. Their customer identity remains
tenant-based; no Account mapping is invented.
