Getting Started
Architecture
API Reference
This document illustrates the key runtime interactions within the TruePortAI platform using sequence diagrams.
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<br/>{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<br/>{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<br/>{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<br/>{tenant_id} PB->>DB: Validate membership DB-->>PB: role: owner PB->>PB: Issue scoped JWT<br/>{sub, tid, role:owner, env:prod} PB-->>UI: 200 OK {scoped_access_token} UI-->>Dev: Dashboard loaded (scoped session)
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<br/>x-api-key: sk-xxxx<br/>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<br/>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<br/>Authorization: Bearer {openai-key}<br/>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<br/>{api_key, provider, tokens, latency_ms, cost_usd} GW->>S3: PUT {tenant-slug}/logs/{YYYY/MM/DD}/{log-id}.json<br/>(raw prompt + completion) end CB->>CB: record_success("openai") → reset failure counter
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<br/>Retry-After: 47 Note over Client: Client must back off and retry after 47s
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<br/>{"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)
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<br/>{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<br/>{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<br/>To: tenant admin(s)<br/>Subject: [CRITICAL] PII Detected in AI Interaction MAIL-->>INGST: Email queued INGST->>DASH: Invalidate analytics cache for tenant
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<br/>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<br/>{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}<br/>{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
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<br/>{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<br/>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<br/>(or login if existing user) PB-->>UI: JWT (global) UI->>PB: POST /platform/api/service/invites/accept<br/>{token: "xxx"}<br/>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
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<br/>{email: "user@example.com"} PB->>MDB: Find user by email MDB-->>PB: User record PB->>PB: create_password_reset_token()<br/>JWT {sub: user_id, type: password_reset_link, exp: +30min} PB->>Mail: Send reset email<br/>Link: https://app.trueportai.com/reset-password?token=<jwt> PB-->>UI: 200 OK (always — prevents enumeration) User->>UI: Click link in email UI->>PB: POST /platform/api/global/auth/reset-password<br/>{token: "<jwt>", 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
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<br/>e.g. auth.mfa_enforced = true AdminUI->>PB: PUT /platform/api/admin/configs/auth.mfa_enforced<br/>{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()<br/>will reload from DB actor TenantAdmin as Tenant Admin TenantAdmin->>AdminUI: Override for their tenant<br/>auth.mfa_enforced = false AdminUI->>PB: PUT /platform/api/service/configs/auth.mfa_enforced<br/>{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)
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<br/>{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