Domain: identity
Curated entry point for the
identitybounded context. New hires onto the identity team start here.
Owner
Founder + agents (Phase 1).
Mission
Owns user identity, authentication, sessions, MFA, OAuth, password reset, role-based access control (RBAC), and the JWT contract used across the rest of the platform. Boundary: identity owns who the actor is and what they are allowed to do; it does not own business-domain authorization (e.g., "can this user request a payout") - that lives with the relevant domain (payouts, accounts, etc.) and is layered on top of the identity claims.
Code paths
- Application code:
apps/api/src/modules/identity/ - Domain logic (pure):
packages/domain/identity/ - Auth helpers + custom flows:
packages/auth/ - Contracts:
packages/contracts/api/identity.ts - External clients: Auth.js providers (Google, Apple, GitHub, Discord) configured declaratively
- Database schemas owned:
identity(User, Account, Session, VerificationToken, UserMfaSecret, MfaBackupCode, AuthAuditLog, LoginAttempt, RoleAssignment)
PRD chapters that touch this domain
16-open-questions.md- Q-E8 (Auth.js + Prisma + Vault Transit), Q-E16 (Vault for JWT signing)13-compliance-legal.md- identity verification, OFAC screening tie-in09-admin-backoffice.md- admin user-management endpoints
TDD chapters
(Empty - will populate as TDDs arrive.)
ADRs that affected this domain
- ADR-0001: Modular monolith for the application layer with extracted long-runners (transversally applies)
Service interfaces this domain exposes
export interface IdentityService {
// getActorBySessionToken(token: string): Promise<Actor | null>
// signInWithCredentials(args): Promise<SessionResult>
// initiateMfaChallenge(userId: string): Promise<ChallengeId>
// verifyMfa(challengeId: string, code: string): Promise<MfaResult>
// assignRole(userId: string, role: Role): Promise<void>
// listUserSessions(userId: string): Promise<Session[]>
// revokeSession(sessionId: string): Promise<void>
// (full surface defined during identity TDD)
}
Events this domain produces / consumes
| Direction | Topic | Triggered by |
|---|---|---|
| produces | identity.user.signed_up | New user signup |
| produces | identity.user.signed_in | Successful sign-in (incl. for ATO detection) |
| produces | identity.mfa.enrolled | TOTP MFA enrollment |
| produces | identity.password.reset | Password reset completion |
| produces | identity.session.revoked | Session forcibly revoked |
| consumes | accounts.user.role_required | When the accounts module needs the actor to gain a new role |
(Final shape locked during identity TDD; topics created in packages/contracts/events/identity.ts.)
External integrations
- Auth.js OAuth providers - Google, Apple, GitHub, Discord (configurable)
- Resend - transactional email (verification, password reset, suspicious-signin alerts)
- HashiCorp Vault Transit - JWT signing keys (per Q-E16)
Runbooks for this domain
(Empty - will populate when alerts are defined in Section 17.6.)
On-call
To be filled in Section 17.6 of docs/PRD/17-engineering-standards.md.
Cross-domain dependencies
- This domain calls: nothing (identity is the lowest layer).
- This domain emits events consumed by:
audit(every security event),notifications(signin alerts, password-reset emails),admin(user-management surfaces).