Appearance
Agency Profile Fields
Extends the Agency entity with corporate identity, contact channels, and fiscal information.
Fields
| Field | Type | Storage | Notes |
|---|---|---|---|
masterEmail | string | null | varchar | Primary agency email |
websiteUrl | string | null | varchar | Agency website URL |
currency | Currency | null | varchar | USD or MXN |
timezone | string | null | varchar | IANA timezone, validated via Intl.supportedValuesOf('timeZone') |
contactChannels | ContactChannelProps[] | null | jsonb | Array of { type, label, value } |
legalName | string | null | varchar | Fiscal legal name |
taxId | string | null | varchar | Tax identification (RFC) |
fiscalAddress | string | null | text | Fiscal address |
All fields are nullable — existing agencies work without backfill.
Shared Enums (in @repo/schemas)
Currency:USD | MXNContactChannelType:EMAIL | PHONE
Contact Channels
Stored as a JSONB column (no separate table). Each entry:
typescript
{ type: ContactChannelType, label: string, value: string }Max 20 channels per agency.
Validation
masterEmail: standard email, max 255 charswebsiteUrl: valid URL (z.url())currency: enum (USD,MXN)timezone: refined againstIntl.supportedValuesOf('timeZone')contactChannels: array of contact channel schemas, max 20 itemslegalName: 1–255 charstaxId: 1–50 charsfiscalAddress: 1–500 chars
API
Agency self-service routes live under /api/identity/agency:
GET /api/identity/agency/current: returns the agency selected in the current session claims.POST /api/identity/agency: creates a new agency owned by the authenticated user.PUT /api/identity/agency/:id: updates an owned agency profile.
All agency profile fields are returned in the agency response DTO.
Key Files
- Domain:
apps/api/src/modules/identity/domain/entities/agency.entity.ts - Persistence:
apps/api/src/modules/identity/infrastructure/persistence/agency.persistence.ts - Schemas:
packages/schemas/src/identity/agency/ - Mapper:
apps/api/src/modules/identity/infrastructure/mappers/agency.mapper.ts