Platform Services

Five production-ready microservices + two React SPAs + Astro landing kit — 100+ REST APIs, each independently deployable with Helm charts, 10-stage CI/CD pipelines, and dedicated databases.

IAM Service

60+ endpoints covering full identity lifecycle for multi-tenant SaaS: signup, password + magic-link, OAuth2/OIDC federation, tenant provisioning, plan enforcement, and access control.

  • Self-service signup — creates user + tenant (multi) or joins default (single); platform user always created
  • Signup status polling, tenant discovery, and async RabbitMQ tenant provisioning with reaper
  • JWT RS256 — 15-min access, 7-day refresh with tenant_id + plan_code claims; JWKS public endpoint
  • Magic link passwordless auth — initiate/resend/exchange, TTL configurable, rate-limited, personal workspace
  • Brute-force protection — 5 attempts → 15-min lockout; admin unlock; failed-attempt cleanup
  • Token revocation — JTI denylist (single signout) + last_global_signout_at timestamp (all sessions)
  • Password reset / change — rate-limited reset; change invalidates all sessions; BCrypt strength 12
  • Email verification — token-based, resend rate-limited; OAuth verified emails auto-linked
  • OAuth2 / OIDC federation — Google, GitHub, Microsoft + PKCE Redis state + tenant-scoped custom OIDC
  • Connected accounts — link/unlink, GitHub requires verified email, admin forced unlink remediation
  • Platform tenant — 'platform' key personal workspace for every user, auto-joined as MEMBER in all modes
  • Tenant owner member mgmt — list, authorities (ADMIN/MEMBER/OWNER), ban, ownership transfer guardrails
  • Avatar uploads — two-phase presigned S3/MinIO, old auto-deleted, tenant-isolated prefixes
  • Announcements — multi-lingual editor, DRAFT→PUBLISHED lifecycle, 1K-batch async fan-out + WebSocket broadcast
  • In-app notifications — persistent table + unread count, mark-as-read bulk/dismiss, STOMP/SockJS per-user push
  • Platform admin — users CRUD + set password, ban/unlock, tenants CRUD, invitations/announcements/counts

Gateway Service

Reactive Spring Cloud Gateway — the single entry point. Handles security, context propagation, plan enforcement, and cross-cutting filters so downstream services get a clean, verified request.

  • JWT RS256 validation via JWKS (Spring Security OAuth2 Resource Server)
  • Header sanitization — strips X-User-*, X-Tenant-ID, X-Audit-*, X-Plan-Code before JWT processing
  • Context propagation — X-User-ID, X-Username, X-User-Email, X-User-Authorities, X-Tenant-ID
  • Plan code header — extracts plan_code from JWT and propagates as X-Plan-Code; client value overwritten
  • Plan feature enforcement — RequiresPlanFeatureFilterFactory for route-level declarative plan checks
  • Audit context — AuditContextFilter injects X-Audit-IP, X-Audit-UA, X-Audit-Source
  • Monitoring filter — per-tenant request rate, latency, status; Grafana dashboard included
  • Correlation ID — generates or propagates X-Correlation-ID on every request; echoed in response
  • Platform mode guard — polls IAM /actuator/info for rollout-mode; 503 REFUSING_TRAFFIC on mismatch
  • Tenant context filter — multi-tenant from JWT, single-tenant injects default tenant key if missing
  • Security response headers — X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy
  • Aggregated Swagger UI — proxies downstream /api-docs through the gateway
  • Configurable public paths via iqkv.gateway.public-paths (OAuth2, magic-link, signup, etc.)
  • Reactive PlanResolver WebClient cache — refreshes plan catalog from billing every 10 minutes
  • Prometheus metrics + structured JSON logging with MDC correlation and tenant context

Billing Service

40+ endpoints, gateway-agnostic payment abstraction. Runtime-selectable Stripe or Lemon Squeezy, tenant-to-customer mapping, FLAT + PER_SEAT pricing, trials, and normalized webhook ingestion.

  • Runtime gateway selection — GatewayType (STRIPE / LEMON_SQUEEZY); @ConditionalOnGateway bean wiring
  • PaymentGatewayPort abstraction — both adapters implement one unified Strategy interface
  • Plan catalog — config-driven YAML; billingPeriod (MONTHLY/ANNUAL), scope (TENANT/USER), active flag
  • Pricing models — FLAT (per billing period) + PER_SEAT (price per user/seat), trialPeriodDays
  • Seat adjustment endpoint — PATCH seats for PER_SEAT plans; validates against plan maxUsers
  • Customer provisioning — auto-created on tenant.provisioned RabbitMQ event; stores externalCustomerId
  • Billing settings — billing email, company name, taxId/VAT/GST, billingAddress JSONB, currency
  • Checkout sessions — Stripe Checkout / Lemon Squeezy variant checkout per tenant per plan
  • Customer portal — Stripe Billing portal or Lemon Squeezy portal sessions for TENANT_OWNER
  • Subscription lifecycle — create/update/cancel/pause/reactivate via gateway; isInTrial + trialDaysLeft
  • Entitlements API — GET /entitlements/me: planCode, status, trials, typed PlanEntitlement quotas
  • Refunds API — create/list full or partial refunds; TENANT_OWNER and PLATFORM_ADMIN access
  • Idempotent webhook processing — signature verification (Stripe / Lemon HMAC-SHA256)
  • Normalized webhook events — subscription, invoice, payment, charge.refunded, refund.created
  • Daily scheduled jobs — trial-ending + payment-overdue notifications (ShedLock-guarded)
  • PlanFeatureRegistry — in-memory O(1) feature evaluation; typed quotas (maxUsers, maxProjects)
  • Grafana dashboard — MRR total, payments/subscriptions/seat adjustments, webhooks, latencies

Audit Service

Centralized, event-driven audit trail. Passively observes all RabbitMQ platform events, normalizes them, and persists them as compliance-ready, searchable records with JSONB metadata.

  • Passive observation — wildcard routing keys; zero code changes required in domain services
  • Event normalization — UserEvent, TenantEvent, Subscription, Invoice, etc. → AuditRecord
  • Technical context enrichment — client IP and User-Agent from X-Audit-* Gateway headers
  • JSONB metadata storage — full event payload preserved, custom MyBatis JsonbTypeHandler
  • ActivitySeverity enum + severity filter on search/count endpoints
  • SPI-based extensibility — AuditProvider interface; plug in Elasticsearch or custom SIEM
  • Dedicated PostgreSQL database — high-volume logging isolated from business transaction DB
  • PLATFORM_ADMIN search API — paginated, filterable by user, tenant, action, severity, date range
  • Audit detail view — full record with structured JSONB metadata expansion
  • RabbitMQ consumer — message converter, DLQ, conditional guards, tenantKey mapping
  • Custom Prometheus metrics — event consumption (by type/source), persistence duration, search latency, storage usage

CMS Service

Content management microservice for static pages, multi-language support, and hierarchical content. Tenant-isolated with event-driven publishing.

  • Static page management — draft/published status, page templates
  • Multi-language support — locale-based content with en-US fallback
  • Hierarchical content structure — parent/child pages with SEO-friendly slugs
  • SEO metadata — title, description, Open Graph tags, canonical URLs
  • Tenant isolation — schema-per-tenant architecture (MyBatisSchemaInterceptor)
  • Event publishing — cms.page.created/updated/deleted to RabbitMQ
  • Public API — GET /pages and GET /pages/{slug} with locale negotiation
  • Platform Admin API — full CRUD for pages across any tenant

Hybrid Tenancy Model

One codebase, two deployment models. Switch multi-tenant B2B vs single-tenant B2C with platform.rolloutMode config flag. Same schema-per-tenant model in both — zero-migration symmetry.

  • Multi-tenant mode — signup creates tenant (TENANT_OWNER); schema-per-tenant PostgreSQL isolation
  • Single-tenant mode — signup joins pre-provisioned default tenant (MEMBER); no tenant creation
  • Platform tenant — fixed 'platform' key/schema; every user auto-added as MEMBER in both modes
  • Zero-migration single→multi symmetry — architectural parity; same schema-per-tenant model in both
  • Liquibase per-tenant schema versioning and migrations per tenant key
  • MyBatisSchemaInterceptor automatically sets t_{tenantKey} search_path per request
  • RabbitMQ async provisioning — runs Liquibase, sets ACTIVE, publishes tenant.provisioned event
  • Stuck provisioning reaper — ShedLock-guarded every 5 min; marks PROVISIONING as PROVISIONING_FAILED
  • Rollout mode validation — validated at startup; published via /actuator/info for cross-service checks
  • Gateway PlatformModeGuard — mismatches set ReadinessState.REFUSING_TRAFFIC returning 503
  • Tenant lifecycle transitions — PROVISIONING→ACTIVE↔SUSPENDED→DELETED with PROVISIONING_FAILED retry
  • Independent tenant status transitions — workspace stays accessible even when org tenant suspended

Tenant App

The customer-facing surface of the platform. A React 19 SPA built with Mantine UI 9, TanStack Router, and Feature-Sliced Design with runtime feature flags.

  • Tenant discovery plus OAuth2/OIDC social sign-in (Google/GitHub/Microsoft) and enterprise SSO entry
  • Magic link passwordless sign-in — initiate/resend screens, token exchange, VITE_ENABLE_MAGIC_LINK flag
  • Self-service signup with async provisioning polling until tenant is ACTIVE
  • Create organization — authenticated route to spin up additional workspaces with platform membership
  • Workspace dashboard with basic stats, team member count, and plan-aware feature gating
  • Team management — member list, ban/unban, role editing, ownership transfer with guardrails
  • Invitation system — send, list, revoke, and accept workspace invites; plan quota-aware
  • Billing self-service — Stripe or Lemon Squeezy portal, subscription view, plan catalog, billing info, refunds
  • Seat adjustments — per-seat plan seat count editor for TENANT_OWNER
  • Plan-based access control — EntitlementsProvider, FeatureGate, useHasFeature, useQuota hooks
  • Tenant settings — organization metadata editing
  • Security settings — TENANT_OWNER config for custom OIDC / enterprise SSO providers
  • In-app notifications — bell, dropdown, notification center, real-time STOMP/SockJS WebSocket push
  • My Account — profile editing, avatar upload, password reset, organization picker, connected accounts
  • Internationalization with Lingui — en-US, bg-BG, de-DE, fr-FR catalogs; locale switcher UI
  • Session security — 30-min inactivity timeout and silent token refresh in sessionStorage
  • Runtime configuration via public/config.js VITE_* overrides without rebuild

Platform Admin

The internal operator console for platform management. Requires PLATFORM_ADMIN authority to access. React 19 SPA with Mantine UI 9, multi-tab detail views, and plan-aware feature gating.

  • Dashboard with parallel count cards for total users, organizations, and active subscriptions
  • Global User management — paginated list; 3-tab detail: Overview, Organizations, Identities; set password, ban/unban/unlock, platform authorities
  • Organization administration — 5-tab detail: Overview, Members, Billing, Subscriptions, Refunds; edit metadata, manage authorities
  • Invitation management — propose, edit, and revoke platform-wide cross-tenant invites
  • Subscription monitoring — global paginated list with status filters; cancel/pause/reactivate via gateway, quantity update
  • Plan catalog — read-only list; sourced from config-driven YAML + deployment
  • Refunds management — global refund list and detail view across Stripe or Lemon Squeezy
  • User identity management — view linked OIDC identities for any user; admin forced unlink remediation
  • Announcements — multi-lingual editor (en-US mandatory + optional translations), publish workflow, delivery tracking
  • Audit logs — global audit trail across all tenants; filter by user, tenant, action, ActivitySeverity, date range; JSONB expansion
  • In-app notifications — bell, dropdown, real-time STOMP/SockJS WebSocket push
  • Operator account — profile editing, password change
  • Internationalization with Lingui — en-US, bg-BG, de-DE, fr-FR catalogs; locale switcher UI
  • Runtime config — public/config.js VITE_* overrides without rebuild
  • Strict RBAC enforcement with automated route guards and PLATFORM_ADMIN authority validation

Technology Stack

Enterprise Java without overhead — proven tools, long-term maintainability

Backend

Java 25 · Spring Boot 4.x · Spring Cloud Gateway (WebFlux) · MyBatis 3.x · PostgreSQL 17 · RabbitMQ · JJWT RS256 · ShedLock 7.x

Security

Spring Security OAuth2 Resource Server + OAuth2 Client · BCrypt strength 12 · JWKS endpoint · JTI denylist · Two-layer token revocation · Redis PKCE store

DevOps

Docker multi-stage builds · Kubernetes + Helm charts · Drone CI/CD 10-stage pipeline · Traefik · Liquibase · Three environments (local / staging / prod)

Observability

Prometheus · Grafana dashboards · Loki + Promtail · Micrometer · Structured JSON logging · Correlation ID tracing · Actuator health probes

Quality Gates

SonarQube · PMD · SpotBugs · Checkstyle (Google Java Style) · JaCoCo coverage thresholds · ArchUnit boundary validation · Testcontainers

Frontend

React 19 · TanStack Router (file-based) · TanStack Query · Mantine UI · Zustand · Lingui i18n · Vite · Astro landing kit