Call Path

Every SDK call travels the same path: REST to cpod-backend, gRPC to the CoreSDK sidecar for policy enforcement, then into the appropriate backing store. This page traces that path end to end.


Overview

SDK (your app)

    │  1. SDK fetches OAuth token (if not cached)
    │     POST /v1/oauth/token  →  gets JWT

    │  2. SDK makes the business call
    │     POST /v1/people  Authorization: Bearer <jwt>

cpod-backend  (FastAPI, 0.0.0.0:8000)

    │  3. Middleware: extract Bearer token from header

    │  4. gRPC AuthService.ValidateToken([::1]:50051)
    │     - Parse JWT, verify RS256 signature
    │     - Check exp, iss, aud
    │     - Check jti not in revocation list
    │     → 401 if invalid

    │  5. gRPC AuthService.Authorize([::1]:50051)
    │     - Evaluate Rego policy: claims + action + resource
    │     → 403 if denied

    │  6. gRPC RateLimitService.CheckRateLimit([::1]:50051)
    │     - Token-bucket per tenantId + clientId
    │     → 429 if exceeded

    │  7. Handler executes
    │     - tenantId stamped from JWT claims (never from request body)
    │     - namespaced query: WHERE tenantId = 'tnt-abc'

Backing Store (MongoDB / Redis / MinIO)

    │  8. Result returned to handler

cpod-backend

    │  9. gRPC AuditService.EmitAuditEvent([::1]:50051)
    │     - Records actor, action, resource, outcome, tenantId
    │     - Hash-chained, tamper-evident

    │  10. Response returned to SDK

SDK (your app)

    │  11. Typed response deserialized and returned to caller

Sequence Diagram

App              cpod-backend         CoreSDK Sidecar     MongoDB/Redis/MinIO
 │                    │                     │                     │
 │  POST /v1/people   │                     │                     │
 │───────────────────►│                     │                     │
 │                    │                     │                     │
 │                    │  ValidateToken      │                     │
 │                    │────────────────────►│                     │
 │                    │◄────────────────────│                     │
 │                    │  valid: tenantId,   │                     │
 │                    │  appId, userId,     │                     │
 │                    │  scopes extracted   │                     │
 │                    │                     │                     │
 │                    │  Authorize          │                     │
 │                    │────────────────────►│                     │
 │                    │◄────────────────────│                     │
 │                    │  policy: allow      │                     │
 │                    │                     │                     │
 │                    │  CheckRateLimit     │                     │
 │                    │────────────────────►│                     │
 │                    │◄────────────────────│                     │
 │                    │  ok                 │                     │
 │                    │                     │                     │
 │                    │  namespaced query   │                     │
 │                    │  WHERE tenantId=... │                     │
 │                    │────────────────────────────────────────────►
 │                    │◄────────────────────────────────────────────
 │                    │  results            │                     │
 │                    │                     │                     │
 │                    │  EmitAuditEvent     │                     │
 │                    │────────────────────►│                     │
 │                    │◄────────────────────│                     │
 │                    │  ack                │                     │
 │◄───────────────────│                     │                     │
 │  200 OK + body     │                     │                     │

Key Properties

The SDK never holds database credentials

The SDK only holds CPOD_CLIENT_ID and CPOD_CLIENT_SECRET. These are OAuth credentials — they authenticate your app to cpod-backend. They are never MongoDB connection strings, Redis passwords, or MinIO access keys. Those credentials exist only inside the platform’s infrastructure, never in SDK configuration.

tenantId cannot be spoofed by the client

cpod-backend extracts tenantId from the validated JWT claims. It is never read from the request body, query string, or any client-supplied header. A client cannot send ?tenantId=tnt-other to access another tenant’s data — the middleware ignores it.

The CoreSDK sidecar is the trust boundary

All auth, policy, rate limiting, and audit decisions flow through the sidecar at [::1]:50051. The sidecar binds to loopback only — it is physically unreachable from any network interface. cpod-backend and the sidecar run on the same host (or pod, in Kubernetes). There is no way to call the sidecar from outside the host.

Every request is audited

Step 9 — AuditService.EmitAuditEvent — runs on every request, including failed ones. The audit log is hash-chained: each record contains SHA-256 of the previous record, making retroactive tampering detectable.

⚠️

Sidecar fail-open risk: if CORESDK_JWKS_URI is not set, the sidecar accepts all tokens in development mode. Always configure CORESDK_JWKS_URI in staging and production environments.


Port Topology

PortBinds toReachable fromPurpose
80000.0.0.0Internet (via reverse proxy)cpod-backend REST API
50051[::1] loopbackcpod-backend process onlyCoreSDK sidecar gRPC
80800.0.0.0Internal network only — firewall requiredCoreSDK Control Plane (OAuth engine)
90910.0.0.0Internal networkSidecar health + Prometheus metrics
🚫

:8080 must be firewalled to your internal network. It issues tokens and manages app credentials. Exposure to the internet is a critical vulnerability.