Architecture
How CoreSDK works — three-layer design, data flow, and deployment modes.
Architecture
CoreSDK has a three-layer architecture: Core Engine (Rust), Sidecar (standalone daemon), and Wrapper SDKs (Python, Go, TypeScript, Java).
Layers
┌─────────────────────────────────────────────────────────────────┐
│ Your App (Python / Go / TypeScript / Java) │
│ │
│ pip install coresdk ← Wrapper SDK │
│ │ │
│ │ gRPC / mTLS [::1]:50051 │
│ ▼ │
│ coresdk-sidecar ← Sidecar daemon │
│ ├── JWT/JWK verification │
│ ├── Rego policy evaluation (regorus) │
│ ├── PII masking SpanProcessor │
│ ├── OTel trace + metrics export │
│ └── HMAC-verified local cache (offline mode) │
│ │ │
│ │ OTLP │
│ ▼ │
│ Your collector (Grafana / Datadog / Jaeger) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Your App (Rust) │
│ │
│ cargo add coresdk-engine ← Core Engine embedded │
│ │ in-process (no network hop) │
│ ├── Rego engine pool (N engines, one per thread) │
│ ├── JWK cache (ArcSwap, lock-free reads) │
│ └── PII masking + OTel spans │
└─────────────────────────────────────────────────────────────────┘Two deployment modes
Python / Go / TypeScript / Java — sidecar mode
Your app talks to the sidecar over local gRPC/mTLS. The sidecar handles all crypto and policy evaluation. Your app calls a thin wrapper SDK.
from coresdk import CoreSDKClient, SDKConfig
from coresdk.middleware.fastapi import CoreSDKMiddleware
_sdk = CoreSDKClient(SDKConfig(
sidecar_addr="[::1]:50051", # sidecar runs here
tenant_id="acme-corp",
fail_mode="open", # allow on sidecar error (dev)
))Rust — in-process mode
The coresdk-engine crate embeds the full Rust engine directly. No sidecar, no network hop. Auth and policy evaluation happen in the same process.
use coresdk_engine::{Engine, EngineConfig};
let engine = Engine::from_env()?;
// engine.authorize(), engine.evaluate_policy() — all in-processRequest lifecycle
Every request through CoreSDKMiddleware follows this chain:
1. HTTP request arrives
2. Middleware extracts Authorization: Bearer <token>
3. Token sent to sidecar via gRPC (or evaluated in-process for Rust)
4. Sidecar verifies JWT signature against cached JWKS
5. Claims extracted → stored on request.state.coresdk_user (FastAPI)
g.claims (Flask)
request.coresdk_claims (Django)
6. Your route handler runs with the claims available
7. Optional: evaluate_policy("data.authz.allow", {...}) for ABAC/RBAC
8. OTel span closed → PII masking SpanProcessor strips emails/tokens
9. Clean span exported to your collectorIf the sidecar is unreachable and fail_mode = "open", requests are allowed through. With fail_mode = "closed" (enterprise default), all requests are rejected.
Fail modes
| Mode | Sidecar unreachable | HMAC mismatch |
|---|---|---|
open (default) | Allow, claims = None | Reject cache entirely |
closed (enterprise) | Deny with RFC 9457 503 | Reject cache entirely |
The Rust Core Engine
The engine is built with:
| Concern | Crate |
|---|---|
| Policy evaluation | regorus (Rust-native OPA/Rego — no WASM) |
| JWT / JWK / OIDC | coresdk-auth (RS256, ES256, PS256) |
| TLS 1.3 / mTLS | rustls (no OpenSSL) |
| Config hot-reload | ArcSwap + notify file watcher |
| PII masking | aho-corasick + regex, fires in SpanProcessor |
| gRPC server | tonic |
Policy eval is <2ms p99 at 500 rps. The engine uses a pool of N regorus::Engine instances (one per blocking thread) — never a single mutex.
Key environment variables
| Variable | Default | Description |
|---|---|---|
CORESDK_SIDECAR_ADDR | [::1]:50051 | Sidecar gRPC address |
CORESDK_TENANT_ID | acme-corp | Default tenant |
CORESDK_FAIL_MODE | open | open = allow on error · closed = deny |
CORESDK_JWKS_URL | — | IdP JWKS endpoint for real JWT validation |
CORESDK_POLICY_DIR | — | Path to Rego bundle directory |
OTEL_EXPORTER_OTLP_ENDPOINT | — | OTel collector (Grafana / Datadog / Jaeger) |
All sdk.* keys in coresdk.toml can be overridden with CORESDK_* env vars.