iam-service
Catalog entry · Enterprise Architecture §6 · Security & Tenancy · Deep bundle:
services/iam-service/
1. Purpose
Authoritative source of "who a principal is" for the entire Melmastoon platform. Owns credentials, sessions, devices, MFA factors, API keys, and federated identity links. Issues short-lived JWTs consumed by every other service. Does not own profile data, role assignments, organizational membership, or property scoping — those belong to tenant-service.
2. Bounded Context
| Field | Value |
|---|---|
| Context | Identity & Access |
| Type | Generic subdomain |
| Strategic pattern | Open Host Service (OHS) for JWT validation |
| Upstream of | every other service (JWT consumer) |
| Downstream of | tenant-service (consumes membership lifecycle), KMS, OIDC/SAML IdPs |
3. Aggregates
| Aggregate | Root | Notes |
|---|---|---|
User | User | Identity-side projection only (no profile, no roles). |
Credential | User (child) | Password hash, breach-list state, rotation history. |
Session | Session | Refresh-token family, device binding, AMR. |
Device | Device | Hardware fingerprint + Ed25519 public key; offline binding cert. |
MFAFactor | User (child) | TOTP / WebAuthn / recovery codes. |
APIKey | APIKey | Hashed key, scopes, tenant binding. |
ExternalIdentity | User (child) | OIDC / SAML link records. |
4. Top Responsibilities
| # | Responsibility | Detail |
|---|---|---|
| 1 | Registration | Email + password, magic link, social SSO, JIT from SAML. |
| 2 | Login | Password / SSO (OIDC, SAML) / WebAuthn / magic link. |
| 3 | Token issuance | Access JWT (EdDSA Ed25519, 15 min) + rotating refresh (30 d online / 7 d offline). |
| 4 | MFA | TOTP, WebAuthn, recovery codes; adaptive challenge via ai-orchestrator-service. |
| 5 | Device binding | Long-lived Ed25519 device cert for Electron desktop offline. |
| 6 | API key lifecycle | Hashed at rest (argon2id), prefix-only logging, scope-bound. |
| 7 | JWKS publication | /.well-known/jwks.json via CDN, 5-min TTL, rotation overlap ≥ 2 days. |
| 8 | GDPR erasure | Participates in saga; purges credentials/sessions/devices/MFA on guest request. |
5. REST Excerpt (top 5 endpoints)
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/auth/register | Create User + Credential; emit melmastoon.iam.user.registered.v1. |
POST | /api/v1/auth/login | Verify credential; issue access + refresh; may return mfa_required. |
POST | /api/v1/auth/refresh | Rotate refresh token; detect reuse → revoke entire family. |
POST | /api/v1/auth/devices/{id}/bind-offline | Issue Ed25519 device certificate (≤ 7 d) for Electron desktop. |
GET | /.well-known/jwks.json | Public signing keys (CDN-cached). |
Full surface in API_CONTRACTS.md.
6. Top Events
Published
| Subject | Retention | Trigger |
|---|---|---|
melmastoon.iam.user.registered.v1 | regulated | Successful registration. |
melmastoon.iam.user.login_succeeded.v1 | operational | Login (any factor) success. |
melmastoon.iam.user.login_failed.v1 | security | Login failure (any reason). |
melmastoon.iam.user.mfa_enrolled.v1 | regulated | MFA factor added. |
melmastoon.iam.session.refreshed.v1 | operational | Refresh-token rotation. |
melmastoon.iam.session.revoked.v1 | security | Logout, lockout, reuse, admin revoke. |
melmastoon.iam.device.registered.v1 | operational | New device record. |
melmastoon.iam.device.bound_for_offline.v1 | regulated | Offline cert issued (Electron). |
melmastoon.iam.apikey.issued.v1 | regulated | API key created. |
melmastoon.iam.apikey.revoked.v1 | security | API key revoked. |
melmastoon.iam.password.reset_requested.v1 | security | Password reset initiated. |
melmastoon.iam.password.reset_completed.v1 | security | Password successfully reset. |
melmastoon.iam.user.locked.v1 | security | Account locked (lockout / admin). |
Consumed
| Subject | Effect |
|---|---|
melmastoon.tenant.created.v1 | Provision super-tenant-admin user. |
melmastoon.tenant.deleted.v1 | Revoke all sessions / API keys for that tenant. |
melmastoon.tenant.guest.erasure_requested.v1 | Purge identity rows; emit melmastoon.iam.user.erased.v1. |
7. Storage
| Store | Use |
|---|---|
| Cloud SQL (PostgreSQL 16 HA) | All aggregates; RLS by tenant_id for tenant-scoped users; platform.* rows are tenant-less. |
| Memorystore (Redis) | Session cache, refresh-token reuse window, rate limits, magic-link nonces. |
| Cloud KMS | JWT signing key (EdDSA Ed25519), tenant device-CA root, breach-list HMAC secret. |
| Secret Manager | OIDC/SAML client secrets, breach-list API key, SMTP credentials. |
| Firestore | Sync cursors for Device deltas (consumed by sync-service). |
8. Multi-Tenancy
| Layer | Enforcement |
|---|---|
| Domain | User.tenantId? — nullable for platform.super_admin; required otherwise. JWT tid claim required for tenant-scoped endpoints. |
| Application | Use cases reject mismatched tid ↔ requested-tenant. |
| Storage | Postgres RLS: USING (tenant_id = current_setting('app.tenant_id')::uuid OR tenant_id IS NULL) on tenant-aware tables. |
| Edge | API gateway sets app.tenant_id GUC on connection checkout via pgbouncer hook. |
See Security & Compliance & Tenancy §3.
9. Hotel-Specific Concerns
- Personas: front-desk staff, housekeeping, maintenance, GM, tenant owner, chain operator, platform admin, guest (email + magic link or social SSO for direct-bookings).
- Electron desktop offline: A bound desktop install holds an Ed25519 device certificate signed by the tenant CA. Allows refresh-token rotation entirely offline for up to 7 days (configurable per tenant). See ADR-0003.
- Property scope: iam-service issues a tenant-scoped JWT; per-property authorization is decided downstream by
tenant-serviceagainstpropertyIdclaims it injects on token mint. - Guest account vs staff account: distinct
userTypeprojection (staff | guest | platform_admin). Guests cannot acquire API keys or device-bind for offline.
10. Edge Cases
- Brute-force lockout: 5 failures / 15 min → 15-min lockout; exponential to 120 min on repeated lockouts.
- Refresh-token reuse → entire session family revoked;
melmastoon.iam.session.revoked.v1withreason='rotation_reuse'. - Device offline > grace period → certificate expires; next online contact forces re-bind.
- SSO IdP downtime → circuit breaker; fallback to local password if tenant policy permits.
- Magic-link replay → server-side single-use nonce; second use returns
MELMASTOON.IAM.MAGIC_LINK_USED. - Concurrent MFA enrollment → optimistic lock on
users.version; second writer retries. - Password breach-list match (HIBP) → reject at registration / reset; force change on existing user via
melmastoon.iam.user.locked.v1(reason='breached_credential').
11. Deep Bundle Index
| File | Purpose |
|---|---|
SERVICE_OVERVIEW.md | Purpose, dependencies, decisions, hotel concerns. |
DOMAIN_MODEL.md | Aggregates, invariants, domain events. |
APPLICATION_LOGIC.md | Use cases, ports, orchestration. |
API_CONTRACTS.md | REST surface, error codes. |
EVENT_SCHEMAS.md | Event JSON Schemas. |
DATA_MODEL.md | Postgres DDL, RLS, indexes. |
SYNC_CONTRACT.md | Desktop sync surface. |
AI_INTEGRATION.md | Adaptive MFA + login anomaly. |
SECURITY_MODEL.md | Crypto, RBAC/ABAC, audit, GDPR. |
OBSERVABILITY.md | SLIs/SLOs, alerts, dashboards. |
TESTING_STRATEGY.md | Test pyramid, scenarios. |
DEPLOYMENT_TOPOLOGY.md | Cloud Run, KMS, HA. |
FAILURE_MODES.md | Failure catalog. |
LOCAL_DEV_SETUP.md | Compose recipe, seed data. |
SERVICE_READINESS.md | Production gate checklist. |
SERVICE_RISK_REGISTER.md | Known risks. |
MIGRATION_PLAN.md | Migration policy + tenant onboarding. |