Release History
Two independently versioned artifacts: the backend library set (dev.mpofusindie:iam-*,
currently 2.0.0) and the React package (@mpofusindie/iam-react, currently 1.4.0).
The canonical detailed record is
CHANGELOG.md.
Coming from a 1.x install? Follow the
1.3.1 → 2.0.0 upgrade guide
— coordinate renames, both database migration paths, the ES256 default, and the SPI signature changes.
Unreleased — on main Feature
Section titled “Unreleased — on main ”Pluggability & portability (ADR-002) plus bootstrap ergonomics:
- Tenancy isolation strategies —
row-level(hardened default) |schema|database - MySQL support — vendor-partitioned migrations + Testcontainers parity suite
- Resource auto-registration — yml definitions merged with
@RequiresPermissionharvesting - Pluggable permission cache — memory (new default) / Redis / off; Redis opt-in on the classpath
PermissionCheckerpublic API; persistence ports behind all 16 repositories- Fixed: host-controller
@RequiresPermissiondenials now return 403 (previously 401)
react 1.4.0 — FieldGuard Security Fix + Login Helper Security
Section titled “react 1.4.0 — FieldGuard Security Fix + Login Helper ”The @mpofusindie/iam-react companion to backend 2.0.0. Treat as a security upgrade.
- SECURITY —
FieldGuardno longer fails open. 1.3.1 read permission fields in snake_case (field_access,cross_cutting,user_id) the backend never sent — it always serialized camelCase — so the visibility lookup returnedundefinedand masked/hidden fields rendered visible. Fixed across the provider, guards, and hooks; API types are now generated from the committed OpenAPI contract and drift-checked in CI. loginWithPassword(config, credentials)— statelessPOST /auth/loginhelper for the pre-provider login screen (returns aTokenPair, throws typedLoginError; does not persist).ProtectedRouteis now router-agnostic (BREAKING) —redirectToremoved in favour offallback?: ReactNode;react-router-domis no longer a peer dependency. Pass your own redirect (fallback={<Navigate to="/login" replace />}).- Explain API —
useCheckAccess()/useAccessSimulation()mirrorPOST /me/check-accessandPOST /access-simulations(the latter needs theiam_permissions:simulatepermission).
2.0.0 — Library Modularization Breaking
Section titled “2.0.0 — Library Modularization ”Backend restructured into a proper library set (ADR-001):
iam-apinow denotes the Spring-free contract; the old REST module isiam-rest- Zero-config dev boot (
iam.dev-mode) — ephemeral secrets, boots with no configuration iam-bomplatform for version alignment; OAuth2 feature-gating- Host apps can override IAM’s
SecurityFilterChain(@ConditionalOnMissingBean) - Migration table for the coordinate changes in the changelog
1.3.2 — Cookie Path Config Fix
Section titled “1.3.2 — Cookie Path Config ”Configurable refresh token cookie path — fixes dual-cookie issues for apps with custom login flows (OTP, magic link, social auth).
- Configurable
iam.jwt.refresh-cookie-pathproperty (default:/) createCookie()andclearCookie()both use the configured path- Default changed from
/api/iam/v1/authto/(industry standard) - Fixes “No refresh token provided” errors in custom auth flows
1.3.1 — Field Masking + Role Simulation Feature
Section titled “1.3.1 — Field Masking + Role Simulation ”Three-state field visibility (visible/masked/hidden), scope-aware field filtering, and client-side role simulation.
- Three-state
FieldGuard— render prop returning'visible' | 'masked' | 'hidden' isSensitiveflag infield_accesspermission response for masking derivation- Scope-aware
@FieldFiltered— reads scope fromIamScopeResolverSPI useFieldVisibility(resource, field)hook for programmatic three-state checksuseIAMSimulation()hook — client-side role preview without API callsisSimulatingflag for admin “View as” banner UI
1.3.0 — Scoped RBAC Feature
Section titled “1.3.0 — Scoped RBAC ”Sub-tenant role scoping — users hold different roles in different contexts within a tenant.
iam_scopestable for named, typed boundaries (portfolios, projects, departments)scope_idoniam_user_roles— NULL = tenant-wide, non-null = scopedIamScopeResolverSPI — host app resolves scope from request context@RequiresPermission(scopeParam = "portfolioId")— scope-aware annotation- Additive merge — scoped roles ADD to tenant-wide, never replace
- Scoped permission caching per (userId, tenantId, scopeId)
- Scope admin API — CRUD + scoped role assignment endpoints
GET /me/permissions?scopeId=— optional scope on permission resolutionuseScopedPermissions(scopeId)React hook +scopeIdprop on all guards
1.2.3 — User/Tenant SPI Feature
Section titled “1.2.3 — User/Tenant SPI ”Host apps bridge existing users/tenants via SPI — no data duplication, no native SQL hacks.
IamTenantProviderSPI — read-only interface for tenant resolution from the host appIamUserProviderSPI — read-only interface for user identity resolution- Shadow record pattern — auto-creates minimal IAM records on first SPI-resolved auth
- Identity synced from SPI on each resolution (email, name changes reflected)
- SPI-first-with-fallback — no SPI = standalone mode unchanged
- Wired into AuthService, JwtAuthenticationFilter, OAuth2, PasswordReset, TwoFactor
1.2.2 — Table Isolation Fix
Section titled “1.2.2 — Table Isolation ”All 20 IAM tables prefixed with iam_ to prevent collisions with host app tables.
- Renamed:
tenants→iam_tenants,users→iam_users,audit_logs→iam_audit_logs, etc. - All 20 tables + indexes + constraints + junction tables prefixed
- Entity
@Tableand@JoinTableannotations updated - SpringDoc OpenAPI upgraded from 2.3.0 to 2.8.6 (Spring Boot 3.4 compatibility)
1.2.1 — Quality Release Feature
Section titled “1.2.1 — Quality Release ”Idempotent migrations, OpenAPI documentation, typed DTOs, error boundaries, and comprehensive docs.
- Squashed 22 migrations into 4 idempotent files (
IF NOT EXISTS,ON CONFLICT DO NOTHING) - OpenAPI
@Operationand@ApiResponseannotations on all 13 controllers - Replaced 40+
anytypes inuseIAMAdminwith typed DTOs (PageResponse<T>, etc.) IAMErrorBoundarycomponent with configurableerrorFallbackpropProtectedRouteloadingFallbackprop — no more flash of empty content- 18 error sites now parse API response bodies instead of generic status codes
- JSDoc on all exported hooks, guards, and provider
- CONTRIBUTING.md, deployment guide, API reference, issue templates
1.2.0 — Plugin Isolation Fix
Section titled “1.2.0 — Plugin Isolation ”Resolves bean name, JPA, and Flyway collisions when IAM is added to an existing Spring Boot app.
- All 75+ IAM beans prefixed with
iam(controllers, services, repositories, components) IamExceptionHandlerscoped to IAM controllers only (basePackages)- CORS and
PasswordEncoderbeans conditional via@ConditionalOnMissingBean - Flyway migrations moved to
classpath:db/iam/migration - React library synced: 2FA hooks, password reset, session management, updated types
1.1.8 — Rate Limiting Feature
Section titled “1.1.8 — Rate Limiting ”Distributed rate limiting with pluggable store and OpenAPI tag grouping.
RateLimitStoreinterface —MemoryRateLimitStore(default) +RedisRateLimitStore- Sliding window algorithm with atomic Redis Lua script
- Fail-open on Redis unavailability — allows traffic with warning log
- Configurable rules per endpoint (path pattern, max requests, window)
- OpenAPI tag grouping for all 13 IAM controllers in Swagger UI
1.1.7 — TOTP 2FA Feature
Section titled “1.1.7 — TOTP 2FA ”Two-factor authentication with backup codes and challenge token login flow.
- TOTP setup — generates secret + QR code URI
- Confirm setup with TOTP code verification
- Challenge token flow — login returns
requires2fa, verify completes auth - 8 backup codes stored hashed (BCrypt), single-use, regenerable
@ConditionalOnPropertytoggle — zero overhead when disabled
1.1.5 — Password Reset + Sessions Feature
Section titled “1.1.5 — Password Reset + Sessions ”Self-service password recovery and session management.
- Forgot-password — generates token, sends via
IamNotificationSenderSPI - Reset-password — validates token, updates password, optionally invalidates sessions
- Revoke all sessions per user or per tenant
- Scheduled cleanup of expired refresh tokens and reset tokens
1.1.3 — Extension Points Feature
Section titled “1.1.3 — Extension Points ”5 SPI interfaces for customizing authentication, lifecycle, JWT, security, and notifications.
IamAuthenticationProvider— plug in custom auth (LDAP, biometric)IamUserLifecycleListener— hook into user create/update/deactivate eventsIamJwtClaimsEnricher— add custom claims to JWT tokensIamSecurityCustomizer— customize the Spring Security filter chainIamNotificationSender— send emails/SMS for password reset and 2FAadditional-permit-allconfig for unprotected paths
1.1.0 — OAuth2 / OIDC Feature
Section titled “1.1.0 — OAuth2 / OIDC ”Full OAuth2/OIDC authentication engine with provider management.
- Google, Microsoft, and generic OIDC provider support
- PKCE authorization code flow for secure SPA authentication
- JIT (Just-In-Time) user provisioning on first OAuth2 login
- Account linking — multiple providers to one user identity
- Encrypted client secrets (AES-256-GCM)
- Domain restrictions — limit signups to specific email domains
- Provider management admin API + admin UI pages
1.0.0 — Foundation Feature
Section titled “1.0.0 — Foundation ”Three-tier permission model with JWT auth, RBAC, caching, and admin UI.
- Feature-level, action-level, and field-level access control
- RBAC with deny-takes-precedence — roles, groups, hierarchical roles
@RequiresPermissionannotation for declarative endpoint protection@FieldFilteredannotation for automatic field masking in responses- Permission resolution engine — merges direct roles, group roles, hierarchy
- Redis caching with TTL-based refresh and automatic invalidation
- JWT authentication — access tokens (15m) + refresh tokens (7d)
- Spring Boot auto-configuration starter — add dependency and go
- Management APIs — full CRUD for users, roles, groups, resources, permissions
- Multi-tenancy — shared schema with tenant-per-row isolation
- React library —
IAMProvider,usePermissions, guards (Feature, Action, Field, Route)