# Sequence Diagrams
This document illustrates the key runtime interactions within the TruePortAI platform using sequence diagrams.
---
## 1. User Registration & Onboarding
```mermaid
sequenceDiagram
autonumber
actor Dev as Developer
participant UI as Platform UI (Angular)
participant PB as platform-backend
participant DB as MongoDB Atlas
participant Mail as Mail Service (SMTP)
Dev->>UI: Fill registration form
UI->>PB: POST /platform/api/global/auth/register
{email, password, first_name, last_name}
PB->>PB: Hash password with Argon2
PB->>DB: Insert User document
DB-->>PB: User created {id}
PB->>Mail: Send welcome email
PB-->>UI: 201 Created {user_id}
UI-->>Dev: Redirect to login
Dev->>UI: Login
UI->>PB: POST /platform/api/global/auth/login
{email, password}
PB->>DB: Find user by email
DB-->>PB: User record
PB->>PB: Verify Argon2 hash
PB-->>UI: 200 OK {access_token (global JWT), refresh_token}
Dev->>UI: Create organization
UI->>PB: POST /platform/api/global/tenants
{name, slug}
PB->>DB: Insert Tenant + Membership (owner)
PB-->>UI: 201 Created {tenant_id, slug}
Dev->>UI: Select organization
UI->>PB: POST /platform/api/global/auth/select-tenant
{tenant_id}
PB->>DB: Validate membership
DB-->>PB: role: owner
PB->>PB: Issue scoped JWT
{sub, tid, role:owner, env:prod}
PB-->>UI: 200 OK {scoped_access_token}
UI-->>Dev: Dashboard loaded (scoped session)
```
---
## 2. AI Request — Happy Path (Streaming)
```mermaid
sequenceDiagram
autonumber
actor Client as Client App (OpenAI SDK)
participant CF as CloudFront
participant GW as TruePortAI Gateway
participant GWMW as Gateway Middleware
participant RL as Rate Limiter (Redis)
participant CB as Circuit Breaker (Redis)
participant LLM as LLM Provider (e.g. OpenAI)
participant S3 as S3 / Blob Storage
participant MDB as MongoDB
Client->>CF: POST /trueportai-services/openai/v1/chat/completions
x-api-key: sk-xxxx
body: {model, messages, stream: true}
CF->>GW: Forward request
GW->>GWMW: verify_api_key()
GWMW->>MDB: Find api_key where key=sk-xxxx AND is_active=true
MDB-->>GWMW: APIKey {id, rate_limit_rpm: 60}
GWMW->>RL: check_rate_limit(api_key, rpm=60)
RL->>RL: INCR rate_limit:sk-xxxx:2024-01-15-10-30
EXPIRE 60s
RL-->>GWMW: count=12 (within limit)
GWMW->>CB: check_circuit_breaker("openai")
CB->>CB: GET circuit_breaker:openai:state
CB-->>GWMW: CLOSED (null)
GW->>LLM: Forward request
Authorization: Bearer {openai-key}
stream: true
LLM-->>GW: 200 OK (stream chunks...)
loop Stream response chunks
GW-->>Client: SSE chunk
end
GW->>GW: Capture full response + metrics
par Async Tasks
GW->>MDB: INSERT UsageLog
{api_key, provider, tokens, latency_ms, cost_usd}
GW->>S3: PUT {tenant-slug}/logs/{YYYY/MM/DD}/{log-id}.json
(raw prompt + completion)
end
CB->>CB: record_success("openai") → reset failure counter
```
---
## 3. AI Request — Rate Limit Exceeded
```mermaid
sequenceDiagram
autonumber
actor Client as Client App
participant GW as TruePortAI Gateway
participant GWMW as Gateway Middleware
participant RL as Rate Limiter (Redis)
Client->>GW: POST /trueportai-services/openai/v1/chat/completions
GW->>GWMW: verify_api_key() → OK
GWMW->>RL: check_rate_limit(api_key, rpm=60)
RL->>RL: INCR → count = 61 (> 60)
RL-->>GWMW: RATE_LIMIT_EXCEEDED
GWMW-->>Client: 429 Too Many Requests
Retry-After: 47
Note over Client: Client must back off and retry after 47s
```
---
## 4. AI Request — Circuit Breaker Open (Provider Down)
```mermaid
sequenceDiagram
autonumber
actor Client as Client App
participant GW as TruePortAI Gateway
participant CB as Circuit Breaker (Redis)
participant LLM as OpenAI API
note over CB: Previous 5 requests to OpenAI failed
note over CB: circuit_breaker:openai:state = OPEN
Client->>GW: POST /trueportai-services/openai/v1/...
GW->>CB: check_circuit_breaker("openai")
CB-->>GW: OPEN (timeout not expired)
GW-->>Client: 503 Service Unavailable
{"detail": "Service openai is temporarily unavailable"}
Note over GW: After 30 seconds, OPEN → HALF_OPEN
Client->>GW: Retry POST /trueportai-services/openai/v1/...
GW->>CB: check_circuit_breaker("openai")
CB-->>GW: HALF_OPEN (try single request)
GW->>LLM: Forward request
LLM-->>GW: 200 OK
GW->>CB: record_success("openai")
CB->>CB: DELETE circuit_breaker:openai:failures → CLOSED
GW-->>Client: 200 OK (response)
```
---
## 5. Violation Detection Pipeline
```mermaid
sequenceDiagram
autonumber
participant S3 as S3 Bucket (Tenant Storage)
participant INGST as Analytics Ingest
participant DESER as Deserializer
participant POL as Policy Engine
participant NER as PII NER (RoBERTa)
participant BIAS as Bias Classifier (DeBERTa-v3)
participant INJ as Injection Shield (DistilBERT)
participant EXFIL as Exfil Guard (Regex+Entropy)
participant MDB as MongoDB
participant MAIL as Mail Service
participant DASH as Dashboard API
S3->>INGST: S3 Event: ObjectCreated
{tenant-slug}/logs/2024/01/15/log-001.json
INGST->>DESER: Load and parse JSON payload
DESER-->>INGST: {request_body, response_body, metadata}
INGST->>POL: Evaluate PolicyRules for tenant
POL-->>INGST: [no keyword/regex matches]
par ML Analysis (parallel)
INGST->>NER: Analyze request_body + response_body
NER-->>INGST: [{entity: "SSN", value: "[REDACTED]", confidence: 0.97}]
INGST->>BIAS: Analyze response_body
BIAS-->>INGST: {bias_detected: false}
INGST->>INJ: Analyze request_body
INJ-->>INGST: {injection_attempt: false}
INGST->>EXFIL: Analyze response_body
EXFIL-->>INGST: {secrets_detected: false}
end
INGST->>INGST: Aggregate violations: [{type: pii, severity: critical}]
INGST->>MDB: INSERT Violation
{type:pii, severity:critical, auto_blocked:false,\nredacted_payload: {...}, usage_log_id}
MDB-->>INGST: Violation {id: VIO-001}
INGST->>MDB: UPDATE UsageLog {has_violation: true, violation_id: VIO-001}
INGST->>MAIL: Send alert email
To: tenant admin(s)
Subject: [CRITICAL] PII Detected in AI Interaction
MAIL-->>INGST: Email queued
INGST->>DASH: Invalidate analytics cache for tenant
```
---
## 6. API Key Lifecycle
```mermaid
sequenceDiagram
autonumber
actor Admin as Tenant Admin
participant UI as TruePortAI UI
participant TSAPI as trueportai-services API
participant MDB as MongoDB
Admin->>UI: Navigate to API Keys
UI->>TSAPI: GET /trueportai-services/api/v1/keys
Authorization: Bearer {scoped_jwt}
TSAPI->>MDB: Find api_keys where tenant_id=xxx
MDB-->>TSAPI: [{id, key: sk-abc...xyz, is_active: true, rpm: 60}]
TSAPI-->>UI: 200 OK [keys list]
UI-->>Admin: Display keys table
Admin->>UI: Click "Create New Key"
UI->>TSAPI: POST /trueportai-services/api/v1/keys
{owner: "prod-app", rate_limit_rpm: 120}
TSAPI->>TSAPI: Generate sk-{32-char secure token}
TSAPI->>MDB: INSERT APIKey {key, owner, tenant_id, rpm: 120}
MDB-->>TSAPI: APIKey {id: key_01}
TSAPI-->>UI: 201 Created {key: "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
Note over UI: Key shown ONCE — admin copies it
Admin->>UI: Disable a key
UI->>TSAPI: PATCH /trueportai-services/api/v1/keys/{id}
{is_active: false}
TSAPI->>MDB: UPDATE APIKey {is_active: false}
MDB-->>TSAPI: Updated
TSAPI-->>UI: 200 OK
Note over TSAPI: All subsequent requests with this key → 401
```
---
## 7. Team Invitation Flow
```mermaid
sequenceDiagram
autonumber
actor Owner as Tenant Owner
actor Invitee as New Team Member
participant UI as Platform UI
participant PB as platform-backend
participant MDB as MongoDB
participant Mail as Mail Service
Owner->>UI: Invite team member
UI->>PB: POST /platform/api/service/invites
{email: "dev@acme.com", role: "member"}
PB->>PB: Generate secure token (UUID4)
PB->>MDB: INSERT Invite {tenant_id, email, role, token, expires_at: +7 days}
PB->>Mail: Send invitation email
Link: https://app.trueportai.com/accept-invite?token=xxx
Mail-->>PB: Queued
PB-->>UI: 201 OK {invite_id}
Invitee->>UI: Click invitation link
UI->>PB: POST /platform/api/global/auth/register
(or login if existing user)
PB-->>UI: JWT (global)
UI->>PB: POST /platform/api/service/invites/accept
{token: "xxx"}
Authorization: Bearer {global_jwt}
PB->>MDB: Find Invite by token
MDB-->>PB: Invite {tenant_id, role, expires_at}
PB->>PB: Validate not expired
PB->>MDB: INSERT Membership {tenant_id, user_id, role: member, status: active}
PB->>MDB: DELETE Invite
PB-->>UI: 200 OK
UI-->>Invitee: Redirect to tenant dashboard
```
---
## 8. Password Reset Flow
```mermaid
sequenceDiagram
autonumber
actor User
participant UI as Platform UI
participant PB as platform-backend
participant MDB as MongoDB
participant Mail as Mail Service
User->>UI: Click "Forgot Password"
UI->>PB: POST /platform/api/global/auth/forgot-password
{email: "user@example.com"}
PB->>MDB: Find user by email
MDB-->>PB: User record
PB->>PB: create_password_reset_token()
JWT {sub: user_id, type: password_reset_link, exp: +30min}
PB->>Mail: Send reset email
Link: https://app.trueportai.com/reset-password?token=
PB-->>UI: 200 OK (always — prevents enumeration)
User->>UI: Click link in email
UI->>PB: POST /platform/api/global/auth/reset-password
{token: "", new_password: "..."}
PB->>PB: Verify JWT {type == password_reset_link, not expired}
PB->>PB: Hash new password with Argon2
PB->>MDB: UPDATE User {password_hash}
PB-->>UI: 200 OK
UI-->>User: Password updated — redirect to login
```
---
## 9. Dynamic Configuration Update
```mermaid
sequenceDiagram
autonumber
actor PlatAdmin as Platform Admin
participant AdminUI as Admin UI
participant PB as platform-backend (Admin API)
participant CL as ConfigLoader (Singleton)
participant MDB as MongoDB
PlatAdmin->>AdminUI: Update global config
e.g. auth.mfa_enforced = true
AdminUI->>PB: PUT /platform/api/admin/configs/auth.mfa_enforced
{value: true, scope: GLOBAL}
PB->>PB: Validate admin token
PB->>MDB: UPSERT ConfigItem {key: auth.mfa_enforced, val: true, scope: GLOBAL}
MDB-->>PB: Updated
PB->>CL: clear_cache(global)
PB-->>AdminUI: 200 OK
Note over CL: Next request that calls get_global_config()
will reload from DB
actor TenantAdmin as Tenant Admin
TenantAdmin->>AdminUI: Override for their tenant
auth.mfa_enforced = false
AdminUI->>PB: PUT /platform/api/service/configs/auth.mfa_enforced
{value: false}
PB->>MDB: Check if config is locked
MDB-->>PB: is_locked: false
PB->>MDB: UPSERT ConfigItem {tenant_id, key, val: false, scope: TENANT}
PB->>CL: clear_cache(tenant_id)
PB-->>AdminUI: 200 OK
Note over CL: Merge priority: Tenant Override (false) wins over Global (true)
```
---
## 10. Subscription / Billing Flow
```mermaid
sequenceDiagram
autonumber
actor Owner as Tenant Owner
participant UI as Platform UI
participant PB as platform-backend
participant MDB as MongoDB
Owner->>UI: View available plans
UI->>PB: GET /platform/api/service/catalog/plans
PB->>MDB: Find plans where product_id=trueportai
MDB-->>PB: [{Developer, $0/mo}, {Pro, $299/mo}, {Enterprise, Custom}]
PB-->>UI: 200 OK [plans]
Owner->>UI: Select Pro plan
UI->>PB: POST /platform/api/service/subscriptions
{plan_id: "pro-monthly"}
PB->>MDB: Find Plan
MDB-->>PB: Plan {price: 299, billing_cycle: MONTHLY}
PB->>MDB: UPSERT Subscription {tenant_id, plan_id, status: ACTIVE, start_date: now}
PB->>MDB: UPDATE Tenant {subscription_id}
PB-->>UI: 201 Created {subscription_id, status: ACTIVE}
UI-->>Owner: Subscription activated
```