ADR-005: IAM Domain Boundary
| Field | Value |
|---|---|
| Status | ✅ Accepted |
| Date | 2026-02-21 |
| Author | @architect |
| Deciders | @architect, @ivko |
Context
As the Renault Club Bulgaria platform grows, identity and access management (IAM) concerns risk becoming scattered across business domains. For example:
EventServicechecking roles inlineNewsServiceduplicating membership validation- Each domain importing Keycloak classes directly
This creates maintenance burden, makes security auditing difficult, and violates Domain-Driven Design principles (supporting domain vs. core domain).
Decision
All IAM concerns are consolidated into a dedicated iam domain:
Package structure:
com.rcb.core.service.iam.*— role assignment, audit logging, Keycloak synccom.rcb.rest.controller.iam.*— IAM HTTP endpointscom.rcb.persistence.entity.iam.*—RoleEntity,AuditLogEntitycom.rcb.persistence.repository.iam.*—RoleRepository,AuditLogRepository
What IAM domain does:
- Administrative role management (assign/revoke roles via
IamService) - GDPR audit logging (who accessed/changed what personal data)
- Optional: Keycloak Admin API sync for role changes (
@ConditionalOnProperty)
What IAM domain does NOT do:
- Runtime authorization checks — these use
@PreAuthorizewith JWT claims directly - Business logic (events, news, campaigns)
- Membership validation (stays in
MembershipServicein the membership domain)
Boundary Rules (enforced by ArchUnit)
-
Business domains do NOT import
IamService:EventService,NewsService,CampaignService, etc. must NOT callIamService- They use
@PreAuthorize("hasRole('...')")for runtime security IamServiceis used only for administrative operations (changing roles, audit logging)
-
IamServiceis used only byIamControllerandSecurityConfig -
Module boundary:
persistence/IAM entities do NOT import fromcore/
Consequences
Positive
- Clear domain responsibility — single place for all IAM operations
- GDPR audit trail is centralized and consistent
- ArchUnit enforces boundaries at CI build time — violations caught early
- Adding new roles or permissions only touches the
iamdomain - Security audit only needs to review the
iamdomain for identity-related vulnerabilities
Negative
- Slight overhead for admin operations (must go through
IamService) - Two-step authorization: runtime (
@PreAuthorize) + administrative (IamService) — can be confusing initially
Neutral
- Role changes in DB are reflected in JWT on next Keycloak token refresh (not immediate) — acceptable for a small community site
References
- DDD: Supporting Domain pattern
- Story 034: IAM Module implementation
- Story 035: GDPR Compliance (uses
AuditLogServicefrom this domain) - ArchUnit docs
- ADR-001 — PostgreSQL schema standards
- ADR Index