gh_UserManager/docs/architecture.md
bermooda-company 54d5891edf user
2026-08-23 23:59:14 +03:30

7.3 KiB

Architecture

Overview

Identity Platform follows an Adobe-style holding model: the Platform is the central hub/reference, and products (Bermooda, Hamsoo, future apps) are sub-products that connect to it. The Platform owns identity; products own their domain data.

┌──────────────────────────────────────────────────────────────┐
│                    IDENTITY PLATFORM                          │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐              │
│  │  Identity  │  │ Authentication│ │ Organization │           │
│  │  (User)    │  │  (Session)   │  │  (Membership)│           │
│  └──────┬─────┘  └──────┬─────┘  └──────┬─────┘              │
│         └────────────────┴────────────────┘                  │
│            PRIVATE KEY (RS256) — NEVER LEAVES PLATFORM       │
└────────────────────────────┬─────────────────────────────────┘
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
        ┌───────────┐  ┌───────────┐  ┌───────────┐
        │  Bermooda │  │  Hamsoo   │  │  Future   │
        │   (ERP)   │  │ (Network) │  │   Apps    │
        └───────────┘  └───────────┘  └───────────┘
              ▲              ▲              ▲
              │  PUBLIC KEY (verify only)  │
              └──────────────┴──────────────┘

Data Ownership Boundary

Data Owner Notes
User ID (UUID) Identity Platform Immutable, globally unique
Email & Phone Identity Platform Verified, used for auth
Password Hash Identity Platform Never exposed
Authentication & Sessions Identity Platform Full lifecycle
Organizations Identity Platform Shared across products
Memberships & Roles Identity Platform Owner/Admin/Member
Applications (OAuth Clients) Identity Platform Per-product credentials
Service Credentials Identity Platform Client credentials flow
Security Events / Audit Log Identity Platform Immutable, queryable
Employee & Payroll Bermooda Domain data
Profile & Resume Hamsoo Domain data
Projects & Listings Product Domain data

Rule: Identity Platform never stores domain data (payroll, resumes, projects). Products never store auth data (passwords, sessions, tokens).

Modular Monolith (Backend)

The Django backend is a modular monolith with 11 apps:

App Responsibility
common Base models, permissions, pagination, rate limiting, exceptions
identity Custom User model (UUID PK), managers, serializers
authentication Login, refresh, logout, MFA-ready, rate limiting
organization Organization CRUD, slug generation
membership Membership model (User↔Org), roles, statuses
application OAuth clients (confidential/public), scopes
session Session tracking, device info, revocation
security SecurityEvent model, audit log
oauth OIDC discovery, JWKS, authorization server stubs
config Settings, URLs, WSGI/ASGI
admin Django admin registrations

API Versioning

All endpoints under /api/v1/. Breaking changes → /api/v2/.

OpenAPI schema via drf-spectacular at:

  • JSON: /api/schema/
  • Swagger UI: /api/docs/
  • ReDoc: /api/redoc/

Key Design Decisions

UUID Primary Keys

  • User PK = UUID (immutable, unguessable)
  • All references use UUID — no integer IDs exposed

RS256 Asymmetric Signing

  • Platform holds private key (signing tokens)
  • Products hold public key (verifying tokens via JWKS)
  • Private key never leaves platform — products cannot forge tokens

Session Model

  • Each login creates a Session record (type: browser/api/device)
  • Refresh token stored hashed; rotatable; revocable
  • Device fingerprinting for detection

Organization Model

  • Single Organization model reusable as company/team/workspace
  • Membership links User→Org with role (owner/admin/member) and status
  • Products query memberships for authorization

Rate Limiting

  • Per-user and per-IP via Django cache (Redis in prod)
  • Configurable windows; brute-force triggers lockout
  • Endpoint-level decorators

Security Events

  • Immutable SecurityEvent model
  • Types: login_success, login_failed, logout, token_refreshed, session_revoked, password_changed, mfa_changed, suspicious_activity
  • Severity: low, medium, high, critical

Frontend Architecture

Next.js 14 App Router, TypeScript, Tailwind.

apps/web/
├── app/
│   ├── layout.tsx      # Root layout, fonts, providers
│   ├── page.tsx        # Landing page (all sections)
│   └── globals.css     # Tailwind + custom components
├── components/
│   ├── ui/             # Button, Badge, Section primitives (CVA)
│   ├── sections/       # 10 landing sections
│   ├── navbar.tsx      # Sticky, lang toggle, links
│   ├── footer.tsx
│   └── language-provider.tsx  # RTL/LTR, fa/en, localStorage
└── lib/
    ├── utils.ts        # cn() helper
    ├── content.ts      # Products, Features, Steps, Protocols
    └── i18n.ts         # Full fa/en dictionary (370 lines)

RTL-First, Bilingual

  • Default: Persian (fa), RTL
  • Toggle persists to localStorage
  • <html dir="rtl" lang="fa"> set by provider
  • Fonts: Inter (Latin), Vazirmatn (Arabic/Persian)

Brand Config via Env

  • NEXT_PUBLIC_SITE_NAME used in navbar, footer, metadata
  • Default fallback: "Identity Platform"
  • No hardcoded brand strings

Deployment

Docker Compose (Production-Ready)

services:
  postgres:  postgres:16-alpine
  redis:     redis:7-alpine
  api:       gunicorn (3 workers)
  web:       next start (standalone output)

Environment Separation

  • .env for secrets (not committed)
  • .env.example as template
  • DJANGO_ENV=production enforces DJANGO_SECRET_KEY

Static Files

  • Django: WhiteNoise (CompressedManifestStaticFilesStorage)
  • Next.js: output: 'standalone' in Docker

Scaling Considerations

Component Horizontal Scale
API (Django) Stateless — add workers/containers behind LB
PostgreSQL Read replicas for query-heavy workloads
Redis Cluster mode for cache/sessions
Frontend Static CDN + edge functions

Future: Multi-Region

  • Platform deployable per region with shared user namespace
  • Cross-region session sync via Redis
  • DNS-based routing to nearest region