CRM Tenant UUID Migration (Draft)
Status: Draft Owner: @digiwedge/engineering Scope: CRM only
Goals
- Introduce a canonical Tenant registry with UUID primary keys.
- Migrate CRM data from string tenant IDs (slugs) to UUID tenant IDs.
- Preserve tenant slugs for human-readable routing and external references.
- Keep CRM public endpoints stable with a clear transition path.
Non-goals
- No changes to non-CRM services in this phase (except integration updates where required).
- No changes to branding, UI, or frontend UX in this migration.
Current State (Audit Summary)
- CRM uses a string
tenantIdacross all models. - There is no
Tenanttable inlibs/prisma/crm-client/prisma/schema.prisma. - Public lead intake expects
tenantIdas a slug (example:digiwedge). - Seeded system segments are club-centric and not tenant-specific.
Target Model
Create a Tenant model with a UUID primary key and slug:
Tenant.id(UUID, primary key)Tenant.slug(unique, human-readable)Tenant.displayNameTenant.status(ACTIVE, DISABLED)Tenant.createdAt,Tenant.updatedAt
All CRM models should reference Tenant.id via a UUID tenantId field.
Migration Strategy (Phased)
Phase 1: Introduce Tenant Registry
- Add
Tenantmodel to CRM Prisma schema. - Seed existing tenants with UUIDs and slugs (initial:
digiwedge,yolo). - Add new column
tenantUuid(UUID, nullable) to all CRM tables. - Backfill
tenantUuidusingtenantIdslug ->Tenant.slugmapping. - Keep existing
tenantId(slug) for compatibility.
Phase 2: Dual Write + Read Migration
- Update CRM services to write both:
tenantUuid(UUID, canonical)tenantId(slug, compatibility)
- Update queries to use
tenantUuidand fallback totenantIdwhen missing. - Emit events containing both
tenantId(UUID) andtenantSlug(string).
Phase 3: Cutover
- Require
tenantUuidfor all new writes. - Update public endpoints to accept:
tenantSlugfor external calls (mapped to UUID)tenantIdfor internal UUID usage
- Update documentation to reflect new API fields.
Phase 4: Cleanup
- Rename slug field to
tenantSlug(if needed for clarity). - Drop legacy slug-only indexes and constraints.
- Remove deprecated code paths after stable period.
API Contract Changes
Public lead intake currently accepts tenantId as a slug. Post-migration:
- Accept
tenantSlugin public endpoints. - Accept
tenantId(UUID) for internal calls. - Return
tenantId(UUID) in events and internal responses.
Seed & Onboarding Templates
- System segments must be tenant-specific.
- Add a YOLO segment template pack (B2B lifecycle) distinct from club templates.
- Ensure onboarding journeys differ per tenant.
Data Validation Queries
- Verify all rows have
tenantUuidafter backfill. - Validate join integrity between CRM tables and
Tenant.
Risks
- External integrations assuming slug-only
tenantId. - Data backfill mistakes due to unknown tenant slugs in the database.
- Breaking public lead intake if tenant mapping fails.
Rollback Plan
- Keep slug columns and old query paths until cutover is proven stable.
- Disable UUID enforcement in Prisma until backfill verified.