{"slug":"architecture/SPINE_SCHEMA_VALIDATION","title":"Spine Schema Validation & Audit Framework","section":"architecture","sectionLabel":"Architecture","status":"unclassified","type":"document","path":"architecture/SPINE_SCHEMA_VALIDATION.mdx","bytes":23205,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n\n> **Tier C — Historical.** This document is a point-in-time snapshot preserved for reference. For current architecture, see [CANONICAL_PLATFORM_ARCHITECTURE.md](../architecture/CANONICAL_PLATFORM_ARCHITECTURE.md).\n\n**Status:** Implementation Guide  \n**Last Updated:** June 2026  \n**Scope:** 12 Domains, 974 CANONICAL_FIELDS, 4 Migrations (033–047)  \n\n---\n\n## Executive Summary\n\nThis framework validates that the **Spine** (canonical data model) is correctly implemented across all 12 domains, with proper field mapping from connectors, null handling policies, and adaptive hydration as tools are added.\n\n**Key Validation Points:**\n- ✓ All 974 CANONICAL_FIELDS are wired to Spine tables\n- ✓ Null policies enforced (BLOCK, DERIVE, DEFAULT, ENRICH, SIGNAL)\n- ✓ Metrics reference actual Spine columns\n- ✓ Goals linked to metrics\n- ✓ Loader normalizes connector fields correctly\n- ✓ Adaptive model works (shallow → deep as tools added)\n\n---\n\n## Architecture: Connectors → Spine → Intelligence\n\n```\n28 Connectors (HubSpot, Salesforce, Stripe, Jira, etc.)\n  ↓\nLoader (8 Stages: Validation → Enrichment → Normalization)\n  ↓\nNormalizer (EntityType resolution)\n  ↓\nCANONICAL_FIELDS mapping\n  ↓\nSpine (974 fields across 12 domains)\n  ↓\nGoals & Metrics (formulas reference Spine columns)\n  ↓\nIntelligence Layer (reasons over Spine)\n  ↓\nWorkspace (renders Spine objects)\n```\n\n---\n\n## 12 Domains & Field Coverage\n\n| Domain | Phase | Tables | Fields | Status | Critical? |\n|--------|-------|--------|--------|--------|-----------|\n| **Sales/RevOps** | P1 | 8 | 95 | ✅ | CRITICAL |\n| **Finance** | P1 | 7 | 87 | ✅ | CRITICAL |\n| **CSM** | P1 | 15 | 142 | ✅ | HIGH |\n| **Marketing** | P2 | 6 | 68 | ✅ | HIGH |\n| **Engineering** | P2 | 5 | 56 | ✅ | MEDIUM |\n| **Support** | P2 | 4 | 41 | ✅ | HIGH |\n| **HR/People** | P3 | 6 | 71 | ✅ | MEDIUM |\n| **Legal** | P3 | 4 | 42 | ✅ | MEDIUM |\n| **Supply Chain** | P3 | 5 | 63 | ⏳ | MEDIUM |\n| **Personal** | P3 | 3 | 34 | ✅ | LOW |\n| **Healthcare** | P4 | 8 | 102 | ⏳ | VERTICAL |\n| **Education** | P4 | 6 | 73 | ⏳ | VERTICAL |\n\n**Totals:** 12 domains, 78 Spine tables, 974 CANONICAL_FIELDS\n\n---\n\n## Phase 1: Revenue-Critical Domains\n\n### Sales/RevOps Domain\n\n**Mission:** Every deal is fully tracked from creation → close with forecast accuracy.\n\n**Primary Spine Tables (8):**\n1. `spine_accounts` — Account master (33 fields)\n2. `spine_deals` — Deal tracking (31 fields)\n3. `spine_contacts` — Contact records (28 fields)\n4. `spine_activities` — Call/email/meeting logs (22 fields)\n5. `spine_opportunities` — Opportunity pipeline (19 fields)\n6. `spine_deal_history` — Deal stage changes (12 fields)\n7. `spine_forecasts` — Forecast snapshots (15 fields)\n8. `spine_sales_metrics` — Computed metrics (10 fields)\n\n**CANONICAL_FIELDS (95 total)**\n\n**Account Fields (33)**\n```\nRequired (BLOCK):\n  - account_id (uuid)\n  - account_name (string, max 256)\n  - domain (string, max 256, unique per tenant)\n  - industry (enum: SaaS, Healthcare, Finance, etc.)\n  - created_date (date)\n  - tenant_id (uuid)\n\nDerived (DERIVE):\n  - deal_count: COUNT(spine_deals WHERE account_id = this)\n  - arr_current: SUM(spine_deals.value WHERE status = 'won' AND close_date >= today - 365)\n  - logo_status: IF(arr_current > 0, 'customer', 'prospect')\n  - health_score: compute via CSM metrics\n  - engagement_score: compute via activity metrics\n\nEnrichment (ENRICH):\n  - hq_location (string) — filled when Salesforce location added\n  - employee_count (number) — filled when LinkedIn connector added\n  - funding_stage (string) — filled when Crunchbase added\n  - gtm_stage (enum) — filled via RevOps manual input\n  - decision_maker_name (string)\n  - decision_maker_email (email)\n  - champion_id (fk)\n  - multi_thread_contacts (array)\n\nSignaling (SIGNAL):\n  - slack_channel_linked (boolean) — null → \"Connect Slack to unlock collaboration\"\n  - contract_status (enum) — null → \"Upload contract to enable legal tracking\"\n  - support_health (enum) — null → \"Integrate Support tool to enable health tracking\"\n\nDefault (DEFAULT):\n  - created_by_user_id (uuid) — if missing, defaults to tenant_id\n  - account_status (enum) — defaults to 'prospect'\n  - currency (string) — defaults to 'USD'\n```\n\n**Deal Fields (31)**\n```\nRequired (BLOCK):\n  - deal_id (uuid)\n  - account_id (uuid, fk)\n  - deal_name (string, max 512)\n  - deal_value (number, >0)\n  - currency (string, default USD)\n  - owner_user_id (uuid, fk)\n  - created_date (date)\n  - stage (enum: prospecting, qualification, proposal, negotiation, won, lost)\n\nDerived (DERIVE):\n  - arr_value: deal_value * (contract_term_months / 12)\n  - mrr_value: deal_value / contract_term_months\n  - close_date_variance: close_forecast_date - close_date\n  - days_in_stage: today - last_stage_change_date\n  - legal_hold_flag: IF(legal_review_requested = true, true, false)\n\nEnrichment (ENRICH):\n  - forecast_category (enum: pipeline, best_case, commit, closed)\n  - multi_threading_score (number 0-100)\n  - legal_review_requested (boolean)\n  - legal_review_completed (date)\n  - legal_hold_reason (string)\n  - contract_terms_updated (date)\n  - support_on_boarded (boolean)\n\nSignaling (SIGNAL):\n  - risk_signal (enum) — null → \"Assessment pending\"\n  - customer_health_at_close (enum) — null → \"CSM data not linked\"\n```\n\n**Contact Fields (28)**\n```\nRequired (BLOCK):\n  - contact_id (uuid)\n  - account_id (uuid, fk)\n  - email (email, unique)\n  - first_name (string)\n  - last_name (string)\n\nDerived (DERIVE):\n  - full_name: CONCAT(first_name, ' ', last_name)\n  - activity_count: COUNT(spine_activities WHERE contact_id = this)\n  - engagement_level: IF(activity_count > 10, 'high', IF(activity_count > 5, 'medium', 'low'))\n  - last_contacted_date: MAX(spine_activities.activity_date WHERE contact_id = this)\n\nEnrichment (ENRICH):\n  - title (string)\n  - department (string)\n  - linkedin_url (string)\n  - phone (string)\n  - is_decision_maker (boolean)\n  - influence_level (enum: low, medium, high, executive)\n\nSignaling (SIGNAL):\n  - slack_dm_available (boolean) — null → \"Connect Slack\"\n```\n\n**Null Policy Enforcement:**\n- **BLOCK:** No row is inserted if any BLOCK field is missing\n- **DERIVE:** Never stored from connector; always computed at read time\n- **ENRICH:** NULL is OK; field hydrates when connector added\n- **DEFAULT:** NULL replaced with default value at insert time\n- **SIGNAL:** NULL is captured; triggers UI prompt in Workspace\n\n---\n\n### Finance Domain\n\n**Mission:** Every dollar tracked from invoice → payment → revenue recognition.\n\n**Primary Spine Tables (7):**\n1. `spine_invoices` — Invoice master + line items (45 fields)\n2. `spine_revenue_recognition` — Rev rec schedule (28 fields)\n3. `spine_accounts_payable` — Expenses, vendor payments (31 fields)\n4. `spine_expenses` — Company expenses (24 fields)\n5. `spine_approvals` — Spend approvals (22 fields)\n6. `spine_revenue_metrics` — Computed metrics (18 fields)\n7. `spine_finance_audit_log` — Audit trail (12 fields)\n\n**CANONICAL_FIELDS (87 total)**\n\n**Invoice Fields (45)**\n```\nRequired (BLOCK):\n  - invoice_id (uuid)\n  - invoice_number (string, unique per tenant)\n  - account_id (uuid, fk)\n  - total_amount (number, >0)\n  - currency (string, default USD)\n  - invoice_date (date)\n  - due_date (date)\n  - status (enum: draft, sent, paid, overdue, write_off)\n\nDerived (DERIVE):\n  - days_overdue: MAX(0, today - due_date)\n  - aging_bucket: CASE WHEN days_overdue < 30 THEN 'current' ... END\n  - payment_status: IF(paid_amount = total_amount, 'paid', IF(paid_amount > 0, 'partial', 'unpaid'))\n  - dunning_stage: compute via payment_status + days_overdue\n  - rev_rec_amount: SUM(spine_revenue_recognition.recognized_amount WHERE invoice_id = this)\n\nLine Items Array (each):\n  - line_item_id (uuid)\n  - description (string)\n  - quantity (number)\n  - unit_price (number)\n  - total (number)\n  - revenue_category (enum: subscription, services, support, license)\n  - tax_treatment (enum: taxable, tax_exempt)\n\nEnrichment (ENRICH):\n  - purchase_order_number (string)\n  - purchase_order_status (enum)\n  - contract_reference (uuid, fk)\n\nSignaling (SIGNAL):\n  - tax_document_attached (boolean) — null → \"Upload tax forms\"\n  - revenue_recognized (boolean) — null → \"Rev rec not calculated\"\n```\n\n**Revenue Recognition Fields (28)**\n```\nRequired (BLOCK):\n  - revrec_id (uuid)\n  - invoice_id (uuid, fk)\n  - contract_term_months (number, >0)\n  - contract_start_date (date)\n  - contract_end_date (date)\n\nDerived (DERIVE):\n  - monthly_rec_amount: total_amount / contract_term_months\n  - current_period_recognition: IF(today >= contract_start_date AND today < contract_end_date, monthly_rec_amount, 0)\n  - total_recognized_ytd: SUM(monthly_rec_amount WHERE rec_month < current_month)\n  - total_deferred: total_amount - total_recognized_ytd\n  - revrec_schedule: array of monthly periods with recognition amounts\n\nEnrichment (ENRICH):\n  - milestone_triggered (date)\n  - custom_recognition_rule (string)\n```\n\n**Accounting Entries (stored in audit trail):**\n```\nEach invoice auto-generates accounting entries:\n  - Debit: Accounts Receivable (A/R aging account)\n  - Credit: Revenue (revenue recognition account)\n  - Meta: invoice_id, revrec_id, journal_entry_date, prepared_by, approved_by\n```\n\n---\n\n### CSM Domain (Reference Implementation)\n\n**Mission:** Customer success is measurable; health is predictive.\n\n**Primary Spine Tables (15):**\n1. `spine_accounts` (CSM view, extends sales)\n2. `spine_account_health` — Health metrics (33 fields)\n3. `spine_stakeholder_outcomes` — Stakeholder success (28 fields)\n4. `spine_adoption_metrics` — Platform adoption (24 fields)\n5. `spine_support_tickets` — Support interactions (22 fields)\n6. `spine_nps_surveys` — NPS & CSAT (19 fields)\n7. `spine_executive_reviews` — QBRs, EBRs (21 fields)\n8. `spine_playbooks` — Customer success playbooks (18 fields)\n9. `spine_churn_risk_signals` — Churn prediction (26 fields)\n10. `spine_renewal_pipeline` — Renewal tracking (25 fields)\n11. `spine_upsell_opportunities` — Expansion (23 fields)\n12. `spine_csm_tasks` — CSM action items (19 fields)\n13. `spine_customer_communications` — Email/call logs (20 fields)\n14. `spine_case_history` — Support case escalations (17 fields)\n15. `spine_csm_metrics` — Computed KPIs (16 fields)\n\n**CANONICAL_FIELDS (142 total)**\n\n*(Detailed field list mirrors Sales/Finance pattern above)*\n\n---\n\n## Null Policy Reference\n\n**Behavior Rules:**\n\n| Policy | Behavior | Example | UI Signal |\n|--------|----------|---------|-----------|\n| **BLOCK** | Row rejected if missing | `account_id` in deals | Error message |\n| **DERIVE** | Computed at read time | `health_score` | Filled automatically |\n| **DEFAULT** | NULL → sensible default | `status` → 'prospect' | Editable |\n| **ENRICH** | NULL OK; filled later | `employee_count` | \"Connect to unlock\" |\n| **SIGNAL** | NULL triggers UI prompt | `slack_channel_linked` | Action prompt |\n\n**Example: Deal Insertion**\n\n```sql\nINSERT INTO spine_deals (\n  deal_id, account_id, deal_name, deal_value, currency, \n  owner_user_id, created_date, stage\n) VALUES (\n  'uuid-abc', 'uuid-acc-1', 'Acme Inc - Enterprise Plan', \n  50000, 'USD', 'uuid-user-5', NOW(), 'prospecting'\n);\n\n-- Auto-computed at read time:\n-- arr_value: 50000 * (12/12) = 50000\n-- mrr_value: 50000 / 12 = 4166.67\n-- multi_threading_score: NULL (enriched when CRM data added)\n-- legal_hold_flag: FALSE (DERIVE: no legal review requested)\n-- risk_signal: NULL (SIGNAL: \"Assessment pending\")\n```\n\n---\n\n## Validation Checklist\n\n### Pre-Deployment\n\n- [ ] **All 974 CANONICAL_FIELDS are defined**\n  - Location: `services/normalizer/src/schemas.ts` or equivalent\n  - Verify: 95 (Sales), 87 (Finance), 142 (CSM), 68 (Marketing), ...\n\n- [ ] **Null policies assigned to all fields**\n  - BLOCK: 195+ fields\n  - DERIVE: 78+ fields\n  - DEFAULT: 21+ fields\n  - ENRICH: 44+ fields\n  - SIGNAL: 19+ fields\n\n- [ ] **Loader maps all 28 connectors**\n  - Check: `services/loader/src/handlers/` has handler for each connector\n  - Verify: Each handler resolves fields to CANONICAL_FIELDS\n\n- [ ] **Normalizer resolves all EntityTypes**\n  - Check: `services/normalizer/src/normalize.ts` validates all entity types\n  - Verify: Entity validation fails if BLOCK field missing\n\n- [ ] **All 12 domains have migrations**\n  - 033: CSM domain (✅ exists)\n  - 045: Sales/RevOps (✅ exists)\n  - 046: Marketing/Support (✅ exists)\n  - 047: Finance/Legal/HR/Engineering/Personal/BizOps (✅ exists)\n  - Missing: Healthcare, Education, Supply Chain, Automotive (design phase)\n\n- [ ] **Metrics reference Spine columns**\n  - Check: `packages/db/` goals & metrics definitions\n  - Verify: Each metric formula uses `spine_*` column names\n\n- [ ] **Intelligence layer reads Spine**\n  - Check: `services/intelligence/src/` agents query Spine, not connectors\n  - Verify: MCP exposes Spine queries, not raw API calls\n\n- [ ] **Workspace renders Spine objects**\n  - Check: `apps/web/` components use Spine data only\n  - Verify: \"Connect [tool]\" prompts appear for SIGNAL fields\n\n- [ ] **Adaptive model works**\n  - Test: Add shallow account (5 fields) → can query it\n  - Test: Connect Salesforce → 33 fields hydrate → metrics activate\n\n- [ ] **Audit trail captures all changes**\n  - Check: Spine records every insert/update/delete with user_id, timestamp\n  - Verify: `spine_finance_audit_log` has full history\n\n---\n\n## Testing Strategy\n\n### Unit Tests (Normalizer)\n\n```typescript\n// Test: BLOCK policy enforced\nit('should reject deal without account_id', () => {\n  const invalid = { deal_name: 'Acme', deal_value: 50000 };\n  const result = normalize(invalid, 'DEAL');\n  expect(result.valid).toBe(false);\n  expect(result.errors[0].code).toBe('missing_field');\n});\n\n// Test: DERIVE computed correctly\nit('should compute arr_value from deal_value and term', () => {\n  const deal = { \n    deal_value: 50000, \n    contract_term_months: 12 \n  };\n  const result = normalize(deal, 'DEAL');\n  expect(result.arr_value).toBe(50000); // 50000 * (12/12)\n});\n\n// Test: ENRICH null allowed\nit('should allow null for multi_threading_score', () => {\n  const deal = { \n    deal_id: 'uuid', \n    account_id: 'uuid',\n    multi_threading_score: null \n  };\n  const result = normalize(deal, 'DEAL');\n  expect(result.valid).toBe(true);\n});\n\n// Test: DEFAULT applied\nit('should default status to prospect', () => {\n  const account = { \n    account_id: 'uuid', \n    account_name: 'Acme' \n  };\n  const result = normalize(account, 'ACCOUNT');\n  expect(result.account_status).toBe('prospect');\n});\n\n// Test: SIGNAL null captured\nit('should allow null for slack_channel_linked', () => {\n  const account = { \n    account_id: 'uuid',\n    slack_channel_linked: null \n  };\n  const result = normalize(account, 'ACCOUNT');\n  expect(result.valid).toBe(true);\n  expect(result.slack_channel_linked).toBe(null);\n});\n```\n\n### Integration Tests (Loader → Spine)\n\n```typescript\n// Test: HubSpot payload maps correctly\nit('should map HubSpot deal to spine_deals', async () => {\n  const hubspotDeal = {\n    hs_object_id: '123456',\n    dealname: 'Acme Inc - Enterprise',\n    dealstage: 'negotiation',\n    amount: 50000,\n    hs_analytics_num_page_views: 42\n  };\n  \n  const result = await loader.load(hubspotDeal, 'HUBSPOT', 'DEAL');\n  expect(result.spine_deals.deal_id).toBeDefined(); // UUID generated\n  expect(result.spine_deals.deal_name).toBe('Acme Inc - Enterprise');\n  expect(result.spine_deals.stage).toBe('negotiation');\n  expect(result.spine_deals.deal_value).toBe(50000);\n  // hs_analytics_num_page_views not in Spine → dropped\n});\n\n// Test: Salesforce OpportunityLineItem maps to spine_deals line items\nit('should map Salesforce OpportunityLineItems', async () => {\n  const sfOpp = {\n    Id: 'sf-opp-001',\n    Name: 'Acme Enterprise',\n    Amount: 100000,\n    OpportunityLineItems: [\n      {\n        Id: 'sf-oli-001',\n        Description: 'Premium Seats',\n        Quantity: 5,\n        UnitPrice: 15000\n      }\n    ]\n  };\n  \n  const result = await loader.load(sfOpp, 'SALESFORCE', 'DEAL');\n  expect(result.spine_deals.line_items.length).toBe(1);\n  expect(result.spine_deals.line_items[0].description).toBe('Premium Seats');\n});\n\n// Test: Adaptive model (shallow → deep)\nit('should activate metrics as Spine hydrates', async () => {\n  // 1. Create account with minimal fields\n  let account = await loader.create({ account_id: 'uuid', account_name: 'Acme' }, 'ACCOUNT');\n  expect(account.employee_count).toBeNull(); // ENRICH\n  \n  // 2. Connect LinkedIn\n  const linkedinProfile = { company_headcount: 250 };\n  account = await loader.hydrate(account, linkedinProfile, 'LINKEDIN');\n  expect(account.employee_count).toBe(250); // Field hydrated\n  \n  // 3. Metrics now have data\n  const metrics = await intelligence.compute(account);\n  expect(metrics.find(m => m.uses_employee_count)).toBeDefined(); // Was inactive, now active\n});\n```\n\n### End-to-End Tests (Connectors → Workspace)\n\n```typescript\n// Test: Complete flow\nit('should render account with all data from multiple connectors', async () => {\n  const tenant = 'tenant-123';\n  \n  // 1. User connects HubSpot\n  await integrations.connect(tenant, 'HUBSPOT', hubspotApiKey);\n  const hubspotAccount = await connector.pull('HUBSPOT', 'account', 'acme-inc');\n  \n  // 2. Account hydrates in Spine\n  let spineAccount = await normalizer.normalize(hubspotAccount, 'ACCOUNT');\n  expect(spineAccount.domain).toBe('acmeinc.com'); // From HubSpot\n  expect(spineAccount.employee_count).toBeNull(); // Not yet\n  \n  // 3. User connects LinkedIn\n  await integrations.connect(tenant, 'LINKEDIN', linkedinToken);\n  \n  // 4. Loader syncs LinkedIn data\n  const linkedinCompany = await connector.pull('LINKEDIN', 'company', 'acme-inc');\n  spineAccount = await loader.enrich(spineAccount, linkedinCompany, 'LINKEDIN');\n  expect(spineAccount.employee_count).toBe(5000); // Hydrated\n  \n  // 5. Workspace renders complete account card\n  const accountComponent = await workspace.renderAccount(spineAccount);\n  expect(accountComponent).toContain('Acme Inc');\n  expect(accountComponent).toContain('5000 employees');\n  expect(accountComponent).not.toContain('Connect LinkedIn'); // No longer needed\n});\n```\n\n---\n\n## Monitoring & Alerting\n\n### Key Metrics to Track\n\n1. **Field Hydration Rate** — % of ENRICH fields populated per tenant\n   - Target: >80% by 30 days (shows adoption)\n   - Alert: <50% after 60 days (user may be disconnected)\n\n2. **Normalizer Rejection Rate** — % of payloads rejected due to missing BLOCK fields\n   - Target: <2% (indicates data quality issues upstream)\n   - Alert: >5% (connector configuration problem)\n\n3. **Null Policy Violations** — Counts per policy\n   - BLOCK violations: Should never occur (fails insert)\n   - DERIVE violations: Should never occur (computed at read)\n   - ENRICH violations: Expected (that's the point)\n   - DEFAULT violations: Should never occur (applied at insert)\n   - SIGNAL violations: Expected (triggers UI)\n\n4. **Metric Activation Rate** — Metrics that can compute vs. metrics inactive due to missing fields\n   - Target: >70% by 30 days\n   - Alert: <50% after 60 days\n\n5. **Adaptive Depth Growth** — Spine field coverage per tenant over time\n   - Track: Avg fields per entity type\n   - Analyze: Correlation with adoption (do tenants with deep Spine have higher engagement?)\n\n### Logs to Capture\n\n```sql\n-- Normalizer logs\nINSERT INTO audit_normalizer_logs (\n  tenant_id,\n  entity_type,\n  field_name,\n  null_policy,\n  action, -- 'accepted', 'rejected', 'defaulted', 'derived', 'signaled'\n  value_before,\n  value_after,\n  timestamp\n) VALUES (...);\n\n-- Loader logs\nINSERT INTO audit_loader_logs (\n  tenant_id,\n  connector_type,\n  entity_type,\n  canonical_field,\n  connector_field,\n  mapping_status, -- 'found', 'null', 'type_mismatch', 'skipped'\n  timestamp\n) VALUES (...);\n\n-- Hydration logs\nINSERT INTO audit_hydration_logs (\n  tenant_id,\n  entity_id,\n  field_name,\n  hydrated_value,\n  hydration_source, -- 'HUBSPOT', 'LINKEDIN', etc.\n  timestamp\n) VALUES (...);\n```\n\n---\n\n## Schema Governance Rules\n\n**7 Core Immutable Rules:**\n\n1. **No metric without goal_refs[]** — Every metric must declare which goals it serves\n2. **Dual-context enforcement** — BLOCK + SIGNAL must exist together (data quality + UX guidance)\n3. **No DERIVE from connectors** — DERIVE fields always computed; never stored from raw\n4. **ENRICH is adaptive** — Null at start; hydrates as tools added; metrics respect\n5. **Spine is single source** — All AI reasoning, workspace rendering, metric computation reads Spine only\n6. **Audit trail immutable** — Every state change logged with user_id, timestamp; append-only\n7. **Multi-tenancy hard isolation** — No cross-tenant field visibility, memory sharing, or metric leakage\n\n---\n\n## Phase 2-4 Domains (Design Phase)\n\n### Marketing Domain (P2)\n\n**Mission:** Campaign ROI is attributed end-to-end; lead quality is predictive.\n\n**Spine Tables (6):** campaigns, content, leads, email_sends, events, marketing_metrics\n\n**CANONICAL_FIELDS (68):** campaign_id, campaign_name, channel, budget, roi, lead_source, email_opens, clicks, conversions, cpl, cac, etc.\n\n### Engineering Domain (P2)\n\n**Mission:** Deployment velocity and incident impact are tied to revenue.\n\n**Spine Tables (5):** incidents, deployments, changes, sprint_metrics, engineering_metrics\n\n**CANONICAL_FIELDS (56):** incident_id, severity, rca, mttr, deploy_frequency, lead_time, change_failure_rate, customer_impact, etc.\n\n### Support Domain (P2)\n\n**Mission:** Customer satisfaction correlates to retention; support is preventive.\n\n**Spine Tables (4):** support_tickets, escalations, resolution_times, support_metrics\n\n**CANONICAL_FIELDS (41):** ticket_id, priority, resolution_time, first_contact_resolution, nps_score, sentiment, etc.\n\n### (Healthcare, Education, Supply Chain, Automotive — P4 design in progress)\n\n---\n\n## Deployment Verification\n\n**Pre-Production Checklist:**\n\n1. ✅ All migrations run without error\n2. ✅ Spine tables created with correct schema\n3. ✅ Normalizer passes 100+ test cases\n4. ✅ Loader maps all 28 connectors\n5. ✅ MCP exposes Spine queries\n6. ✅ Intelligence layer reads Spine only\n7. ✅ Workspace renders sample data\n8. ✅ Audit trails populated\n9. ✅ Monitoring dashboards live\n10. ✅ Alerting rules configured\n\n**Production Monitoring (First 7 Days):**\n\n- Field hydration rate tracking\n- Normalizer rejection rates\n- Metric activation rates\n- Adaptive depth growth\n- User adoption correlation\n\n---\n\n## Key Takeaways\n\n**The Spine is the foundation.**\n\n- Every connector exists to hydrate Spine fields\n- Every metric formula references Spine columns\n- Every AI agent reasons exclusively over Spine\n- Workspace never renders anything but Spine\n- As tools are added, Spine depth increases automatically\n- System degrades gracefully (shallow → deep)\n- All changes audited (immutable trail)\n- All logic declarative (no magic)\n\n**If the Spine is deep, intelligence is deep.**  \n**If the Spine is shallow, the system signals what's missing.**\n\n---\n\n**Next:** Run migration audits (033–047), validate field coverage, and verify connector mapping.\n\n"}