ADR 010: Use "User" Not "Member" for the Tenant-Scoped Entity

ADR 010: Use “User” Not “Member” for the Tenant-Scoped Entity

Status

Accepted

Date

2026-03-10

Context

The original domain model used “Member” as the name for the tenant-scoped person entity (e.g., Member, MemberId, MemberRegistered). This made sense when distinguishing between a Zitadel identity (universal) and a tenant-local person.

However, in practice:

  • Every person who uses the platform has a login via Zitadel — they are all “users”
  • The codebase already has a User entity in Core/Identity for the authenticated person
  • Having both User (auth) and Member (domain) for the same person creates confusion
  • In REST APIs, “user” is the natural resource name

Decision

Use User as the tenant-scoped entity name, not Member.

  • The aggregate is User with UserId
  • Domain events: UserRegistered, UserProfileUpdated, UserJoinedOrganization, etc.
  • The User entity holds profile fields directly (no separate MemberProfile VO)
  • The word “membership” is preserved for relationships:
    • OrgMembership — a user’s role in an organization
    • GroupMembership — a user’s role in a group
    • MembershipStatus — active, inactive, pending

Consequences

  • Single concept: One User entity per tenant, not User + Member
  • Natural API design: /api/users/{id}, not /api/members/{id}
  • Clear distinction: User = the person, Membership = the relationship
  • UI labels remain configurable: Tenants can still display “Member”, “Participant”, “Attendee” via tenant.memberLabel — the domain name doesn’t constrain the UI
  • Docs updated: docs/domain-model.md renamed throughout