v2.0 AI EXECUTION FABRICYou are viewing Pranor v2.0 Documentation. Switch to Stable v1.0 Docs →

Pranor Documentation

Welcome to the Pranor documentation. Pranor is a unified, modular backend infrastructure engine with its own programming language, designed to build high-performance microservices with zero glue code.

💡 Documentation Version Selector

Quick Navigation

SectionDescription
Getting StartedInstall Pranor and build your first service in 5 minutes
Language ReferenceSyntax, standard library, CLI commands
Module DocsFull documentation for each Pranor module
DeploymentDocker, Kubernetes, standalone deployment guides
ArchitectureSystem design, security model, observability
EnterpriseEE features, licensing, and comparison
ChangelogUnified release history

Modules

ModuleWhat it doesDocs
Pranor (CLI)Compiler & language runtimeLanguage →
GateAPI Gateway & AI Guardgate.md →
PulseAsync Event Broker & Message Queuepulse.md →
VaultS3 Storage & Vector Searchvault.md →
ChronoDistributed Job Schedulerchrono.md →
AuthIdentity & Access Controlauth.md →
CacheDistributed Cache Enginecache.md →
MeshService Discovery & Load Balancingmesh.md →
TraceDistributed Tracing Enginetrace.md →
ConsoleObservability Dashboardconsole.md →
PoolDatabase Connection Proxypool.md →
NotifyEmail/Slack/SMS Gatewaynotify.md →
FlowWorkflow Engine & Saga Orchestratorflow.md →
DeployDocker/K8s Deployment Pipelinedeploy.md →
TunnelWebSocket Dev Tunnelingtunnel.md →
HubPackage Registryhub.md →
LockDistributed Lockinglock.md →
SecretSecret Managementsecret.md →

Install

# macOS/Linux
brew tap vyuvaraj/pranor && brew install pranor

# Windows
scoop bucket add pranor https://github.com/vyuvaraj/scoop-pranor
scoop install pranor

# From source
git clone https://github.com/vyuvaraj/pranor && cd pranor/lang && go build -o pranor .

First Service

pranor init myapp && cd myapp && pranor run main.pnr --watch

v2.0 AI Execution Fabric (v2.0-dev — merges post v1.0 release)

Pranor v2.0 extends the ecosystem with a governed AI agent execution layer built on top of the existing infrastructure. All v2.0 modules are CGO-free (CGO_ENABLED=0) and follow the OSS/EE build-tag convention.

ModulePathDescription
Pranor Graphstd/graphVirtual entity context assembly — Hot/Warm/Cold 3-tier with fail-closed contract
Pranor Decisionstd/decision6-level priority veto ladder: Auth > Budget > Risk > Rules > Learn > Default
Pranor Learnstd/learnPluggable ML inference provider (wazero WASM + gRPC sidecar)
Pranor Evalstd/evalTrajectory replay and quality scoring — 4 evaluators (accuracy, latency, cost, safety)
Trace Schemastd/traceCanonical OTLP span hierarchy + mandatory attribute contract for all modules
Flow AgentStepstd/flowAgentStep interface + Saga runner + HITL approval queue

Branch: All v2.0 features live on v2.0-dev. See v2.0 modules docs for full API reference.

Getting Started with Pranor

Build and deploy a backend service in 5 minutes.

Prerequisites

  • Go 1.22+ installed (download)
  • A terminal (bash, PowerShell, or cmd)

Install

macOS / Linux (Homebrew)

brew tap vyuvaraj/pranor
brew install pranor

Windows (Scoop)

scoop bucket add pranor https://github.com/vyuvaraj/scoop-pranor
scoop install pranor

From Source

git clone https://github.com/vyuvaraj/pranor.git
cd pranor/lang
go build -o pranor .
# Add to PATH or move to /usr/local/bin

Verify

pranor --version

Create Your First Service

pranor init myapp
cd myapp

This creates a main.pnr file:

server "8080"
database "sqlite://app.db"

migration "create_users" {
    db.query("CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        email TEXT UNIQUE
    )")
}

export route "GET" "/api/users" (req) {
    let users = db.query("SELECT * FROM users")
    return { "users": users }
}

export route "POST" "/api/users" (req) {
    let name = req.body.name
    let email = req.body.email
    db.query("INSERT INTO users (name, email) VALUES (?, ?)", name, email)
    return { "status": "created" }
}

Run

pranor run main.pnr --watch

Your API is now running at http://localhost:8080. The --watch flag auto-reloads on file changes.

Test It

# Create a user
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "email": "alice@example.com"}'

# List users
curl http://localhost:8080/api/users

Build for Production

pranor build main.pnr -o myapp
./myapp  # Single binary, no runtime needed

Add More Capabilities

Pranor modules extend your service without glue code:

// Add a scheduled task
every 5m {
    log.info("Running cleanup...")
    db.query("DELETE FROM sessions WHERE expires_at < datetime('now')")
}

// Add caching
cache "in-memory"

export route "GET" "/api/users/:id" (req) {
    let cached = cache.get("user:" + req.params.id)
    if cached != nil { return cached }
    
    let user = db.query("SELECT * FROM users WHERE id = ?", req.params.id)
    cache.set("user:" + req.params.id, user, 300)
    return user
}

Deploy

# Docker
pranor deploy --target docker

# Kubernetes
pranor deploy --target k8s --namespace production

What's Next

Pranor: A Programming Language for Background Services

Pranor is a modern, high-level DSL (Domain-Specific Language) designed specifically for building background services, schedulers, event-driven applications, and API microservices. It compiles directly into native binaries via Go code generation, providing high performance, low resource consumption, and rapid development.


Table of Contents


Key Features

  • Declarative Infrastructure: Routes, schedulers, pub/sub, databases, caches, and WebSockets as language keywords — not library calls.
  • Compiles to Native Binaries: Go code generation → single binary deployment. No runtime dependencies.
  • Optional Static Typing: Gradual type system with int, float, string, bool, optional types (T?), union types (T | error), and generics with constraints.
  • 48 Standard Library Modules: Auth, JWT, retry, circuit breaker, pagination, CORS, rate limiting, validation, and more — written in Pranor itself.
  • Built-in Test Framework: test "name" { assert expr } blocks with structured assertion messages.
  • Multiple Database Backends: SQLite, PostgreSQL, Oracle, MongoDB — same db.query() API.
  • Multiple Broker Backends: Kafka, NATS, RabbitMQ, MQTT — same subscribe/publish syntax.
  • Concurrency Primitives: spawn, async/await, channels, worker pools.
  • Middleware & Auth: Declarative middleware with use [auth, logging] on routes.
  • Python Interop: Call Python scripts via extern fn bindings.
  • Go Package FFI: Import any Go package with pranor add <package> and auto-generated declarations.
  • VS Code Extension: Full LSP with diagnostics, autocomplete, hover, go-to-definition, and 30+ snippets.
  • OpenTelemetry & Prometheus: Built-in tracing and metrics export.
  • Docker Support: pranor dockerize generates production-ready Dockerfiles.
  • Multi-File Import System: Import types and schemas across .pnr files with cross-file type resolution and circular import detection.
  • async Task & concurrent {} Primitives: First-class language support for async task execution and parallel concurrent blocks.
  • Multi-Target Code Generation: Generate Rust (pranor generate --lang rust) or Python (pranor generate --lang python) client code from .pnr service definitions.
  • Breaking Change Detector: pranor diff old.pnr new.pnr detects field removals, type changes, and new required fields — safe to use in CI pipelines.
  • Zero-Install WASM Playground: Try Pranor in the browser at playground.pranor.dev — runs the full compiler in WebAssembly, no install required.

Getting Started

Prerequisites

  • Go: Version 1.22 or higher is required to build the compiler and execute Go-transpiled code.
  • Python 3.x: Optional (needed if using Python external functions).

Install via Scoop (Windows)

scoop bucket add pranor https://github.com/vyuvaraj/scoop-pranor
scoop install pranor

Install via Homebrew (macOS / Linux)

brew tap vyuvaraj/pranor
brew install pranor

Install via Script (Windows)

irm https://raw.githubusercontent.com/vyuvaraj/Pranor/main/release-scripts/install.ps1 | iex

Build from Source

git clone https://github.com/vyuvaraj/Pranor.git
cd Pranor
go build -o pranor.exe .

Add the binary to your system PATH for global access.


Editor Support

VS Code Extension

Install Pranor Language Support from the VS Code Marketplace (or from .vsix in the repo):

  • Syntax highlighting for .pnr files
  • Real-time diagnostics (type errors, unused variables, missing returns)
  • Autocomplete and hover information
  • Go-to-definition across files
  • 30+ code snippets (route, fn, struct, test, every, subscribe, etc.)
  • Commands: Run (Ctrl+Shift+R), Build (Ctrl+Shift+B), Test (Ctrl+Shift+T)
  • Format on save

CLI Commands Reference

CommandDescription
pranor build <file.pnr> [-o output]Compile to native binary
pranor run <file.pnr> [--watch]Compile and run (with optional hot-reload)
pranor test <file.pnr> [--cover] [--filter name]Run test blocks
pranor lint <file.pnr>Check syntax and static analysis
pranor fmt <file.pnr> [--check]Format code (4-space indent)
pranor replInteractive shell
pranor add <go-package>Generate .pnr.d declaration for a Go package
pranor packagesList installed package declarations
pranor remove <package>Remove a package declaration
pranor install <name>Install a community package
pranor publish <dir>Publish a package to the registry
pranor init [name]Create a new Pranor project
pranor dockerize <file.pnr>Generate a production Dockerfile
pranor debug <file.pnr>Debug with Delve
pranor auditAudit Go dependencies for vulnerabilities

Language Syntax Guide

Core Architecture Statements

Pranor allows you to declare global settings and connections dynamically or using values loaded from environment variables:

// Declare port dynamically from environment variables
server env("PORT")

// Setup global message broker (options: "in-memory", or Kafka address)
broker "in-memory"

// Setup databases (SQLite, PostgreSQL, Oracle, MongoDB)
database "sqlite://service_data.db"
database env("DATABASE_URL")

// Setup in-memory cache
cache "in-memory"

Static Typing & Type Annotations

Pranor supports optional static typing on variables and function signatures. Providing types compiles them directly into native Go types, skipping the performance overhead of runtime interface{} conversions.

Supported types: int, string, bool.

Variable Type Annotations

Specify types using : type after the identifier:

let count: int = 100
let label: string = "Items in queue"
let isActive: bool = true

Function Signature Type Annotations

Specify parameter and return types to optimize function calls and compiler math:

fn calculateTotal(base: int, tax: int) -> int {
    let result: int = base + tax
    return result
}

Schedulers (every & cron)

Easily define background routines that run periodically or at scheduled times.

Interval Scheduler

Runs a block of code at a specific time duration (e.g., s for seconds, m for minutes, h for hours).

every 5s {
    log.info("System healthcheck running...")
}

Cron Scheduler

Executes using standard cron patterns. Can load patterns from environment variables.

cron "0 */2 * * * *" {
    log.info("This runs every 2 minutes.")
}

// Load from environment variable
cron env("BACKUP_CRON") {
    log.warn("Starting system database backup...")
}

Web Servers & HTTP APIs (route)

Declare HTTP request endpoints with simple routes. Pranor handles request body parsing natively.

route "GET" "/status" (req) {
    log.info("Status check requested")
    return { 
        "status": "Pranor is operating normally", 
        "timestamp": time.now() 
    }
}

route "POST" "/webhook" (req) {
    let body = req.body
    log.info("Received body payload: ", body)
    return { "received": true }
}

Pub/Sub Broker (publish & subscribe)

Publish event messages and register subscriptions.

// Publish message onto a topic channel
publish "events.incoming" { "user_id": 101, "action": "login" }

// Subscribe to messages on a topic
subscribe "events.incoming" (msg) {
    log.info("Broker received event: ", msg)
}

Concurrency & Worker Pools (spawn)

You can execute operations asynchronously without blocking the main workflow thread.

Fire-and-Forget Goroutines

subscribe "incoming.tasks" (msg) {
    // Spawns a lightweight concurrent thread
    spawn processTask(msg)
}

Rate-Limited Worker Pools

Specify a worker limit to control resource consumption:

// Spawns up to 5 concurrent workers maximum
spawn(5) handleHeavyCalculation(data)

Database Operations (db.query)

Execute queries directly on the configured databases.

SQL Databases (SQLite, PostgreSQL, Oracle)

Supports query parsing and placeholders (? translates automatically to appropriate placeholders like $1 dynamically for PostgreSQL).

// Create schema table on startup
db.query("CREATE TABLE IF NOT EXISTS metrics (id INTEGER PRIMARY KEY, ts TEXT)")

// Insert records
db.query("INSERT INTO metrics (ts) VALUES (?)", time.now())

// Read records
let results = db.query("SELECT * FROM metrics LIMIT 5")
log.info("Metrics: ", results)

MongoDB Operations

Executes collection queries using standardized document queries:

let result = db.query("insert", "logs", "{\"service\": \"Pranor\", \"action\": \"db_test\"}")

Cache Operations (cache.set & cache.get)

Leverage native in-memory caching to save and read states quickly:

// Set key with cache TTL (Time to Live)
cache.set("session_user_1", { "id": 1, "role": "admin" }, "10m")

// Fetch value from cache
let session = cache.get("session_user_1")
log.info("Active Session: ", session)

S3 & Pranor Vault Client Operations (s3)

Interact with S3-compatible endpoints or a Pranor Vault gateway using the native s3 runtime functions. You can also import the helper wrapper from the standard library:

import { newClient, put, get, deleteObject, list, at, search } from "stdlib/s3.pnr"

// Initialize client
let client = newClient("http://localhost:8080", "admin", "adminsecret")

// Create and configure a bucket
client.createBucket("my-bucket")
client.setBucketVersioning("my-bucket", true)

// Upload and retrieve objects
client.put("my-bucket", "config.json", "{\"status\": \"active\"}")
let content = client.get("my-bucket", "config.json")
log.info("Content: ", content)

// Time-travel to retrieve previous versions of an object (Pranor Vault only)
let historicalContent = client.at("my-bucket", "config.json", "2026-06-15T09:00:00Z")

// Perform semantic search queries (Pranor Vault only)
let searchResults = client.search("my-bucket", "find active config files", 5)

Python Interoperability (extern fn)

Map complex algorithms or specialized Python libraries directly to Pranor functions:

// Map external Python method
extern fn analyzeText(text) from "python:./scripts/analyzer.py:analyze"

let result = analyzeText("Hello world!")
log.info("Python output: ", result)

Built-in Functions & Utilities

JSON Support

let obj = json.parse("{\"status\": true}")
let rawString = json.stringify(obj)

String Interpolation (f-strings)

let name = "Pranor"
let statusMessage = f"System: {name} is running!"

Pattern Matching (match)

match eventType {
    "PAYMENT_COMPLETED" => {
        log.info("Processing checkout success...")
    }
    "USER_LOGOUT" => {
        log.info("Cleaning session...")
    }
    _ => {
        log.warn("Unknown event category received")
    }
}

Exception Handling (try-catch)

try {
    let res = http.get("http://invalid-url.com")
} catch (err) {
    log.error("HTTP request failed: ", err)
}

Web Playground

Pranor includes an interactive Web Playground for trying the language in-browser.

  • WASM Compiler: Syntax analysis and formatting run client-side
  • Sandbox Runner: Compiles and executes code server-side with auto-termination
go build -o web_playground/server/server.exe web_playground/server/main.go
./web_playground/server/server.exe
# Open http://localhost:8080

Standard Library

Pranor ships with 48 importable modules written in Pranor itself:

CategoryModules
Auth & Securityauth, jwt, crypto, cors, sanitize, ip
Resilienceretry, circuit_breaker, timeout, semaphore, dlq
HTTPhttp_client, response, middleware, ratelimit, webhook
Datavalidation, pagination, pagination_cursor, csv, diff, sort, collections
Config & Envconfig, env, feature_flags
Observabilitytracing, metrics, health, audit
Utilitiesstrings_util, datetime, math, url, base64, mask, idempotency, batch, queue
Infras3, cache_patterns, tenant, scheduler, job, graceful

Import with:

import { hashPassword, verifyPassword } from "stdlib/crypto"
import { ok, notFound, created } from "stdlib/response"
import { retry } from "stdlib/retry"

Package Management

Publishing

pranor publish <package-dir>

Installing

pranor install <package-name>

Using

import { Helper, helperFunc } from "mypkg"

Resolves to packages/mypkg/index.pnr or packages/mypkg/main.pnr. Only export-marked declarations are accessible.


Testing Support

Pranor includes a native test harness built into the language itself. This makes it trivial to write unit tests alongside your code and verify logic without external framework setups.

Defining Tests

Add test blocks and use the assert statement to check variables:

fn doubleValue(val) {
    return val * 2
}

test "doubling math verification" {
    assert doubleValue(2) == 4
    assert doubleValue(5) == 10
}

test "check string comparison" {
    let val = "Pranor" + "Lang"
    assert val == "ServLang"
}

Running Tests

Execute:

pranor test test_sample.pnr

Output:

Running tests from test_sample.pnr...
=== RUN   Test_DoublingMathVerification
--- PASS: Test_DoublingMathVerification (0.00s)
=== RUN   Test_CheckStringComparison
--- PASS: Test_CheckStringComparison (0.00s)
PASS
ok  	pranor/.build	1.518s

Compilation & Deployment

When pranor build or pranor test is executed, the compiler compiles the input .pnr code into a temporary directory called .build.

Inside .build:

  1. service.go: Synthesizes code for all declarations, routes, and background routines.
  2. main.go: Provides the service runtime engine and entry points.
  3. pranor_test.go: Aggregates the test blocks translated to Go's native testing framework.

The output binary compiles out all debug logs and features a fast, low-overhead native runtime engine.


Documentation


Multi-File Import System

Pranor supports splitting service definitions across multiple .pnr files. Types and schemas defined in one file can be imported and used in another:

// types/user.pnr
type User {
    id:    string
    name:  string
    email: string
}
// services/auth.pnr
import "./types/user.pnr"

route POST "/api/users" {
    body: User
    handler: createUser
}

Features:

  • Cross-file type resolution with full type checking
  • Circular import detection with descriptive error messages
  • Wildcard imports: import "./types/*"
  • Re-export: export type AdminUser extends User { role: string }

Async & Concurrent Primitives

Pranor provides first-class async and concurrent language constructs:

// Async task — fire and forget
async fn sendNotification(userID: string) {
    call POST "http://notifications/send" { userID }
}

route POST "/api/orders" {
    handler: fn(req) {
        let order = db.insert("orders", req.body)

        // Fire async — doesn't block the response
        async sendNotification(req.body.userID)

        return { order_id: order.id }
    }
}
// Concurrent block — run steps in parallel, collect results
route GET "/api/dashboard" {
    handler: fn(req) {
        let results = concurrent {
            orders:      call GET "http://orders/summary"
            inventory:   call GET "http://inventory/levels"
            analytics:   call GET "http://analytics/today"
        }

        return results  // all three completed in parallel
    }
}

Multi-Target Code Generation

Generate type-safe client code for other languages from your Pranor service definitions:

# Generate Go client (default — used within Pranor compilation)
pranor generate --lang go services/orders.pnr

# Generate Rust client
pranor generate --lang rust services/orders.pnr -o ./clients/rust/

# Generate Python client
pranor generate --lang python services/orders.pnr -o ./clients/python/

Generated Rust client:

#![allow(unused)]
fn main() {
// Auto-generated by `pranor generate --lang rust`
pub struct OrdersClient { base_url: String }
impl OrdersClient {
    pub async fn create_order(&self, body: CreateOrderRequest) -> Result<Order, Error> { ... }
    pub async fn get_order(&self, id: &str) -> Result<Order, Error> { ... }
}
}

Generated Python client:

# Auto-generated by `pranor generate --lang python`
class OrdersClient:
    def create_order(self, body: CreateOrderRequest) -> Order: ...
    def get_order(self, id: str) -> Order: ...

Breaking Change Detector

pranor diff compares two .pnr files (or two git revisions) and detects breaking API changes — safe to run in CI before merging:

pranor diff api/v1/orders.pnr api/v2/orders.pnr

Example output:

⚠️  BREAKING CHANGES DETECTED

[FIELD_REMOVED]   Order.discount_code      (line 12 → removed)
[TYPE_CHANGED]    Order.total: int → float  (line 8)
[REQUIRED_ADDED]  CreateOrderRequest.currency  (line 23 → now required)

✅ NON-BREAKING CHANGES

[FIELD_ADDED]     Order.created_at (optional)

Detected breaking change categories:

  • Field removals from request/response types
  • Type changes (e.g., intstring)
  • Making optional fields required
  • Route removal or method change
  • Removing enum variants

Use in CI:

# GitHub Actions
- run: pranor diff main:api/orders.pnr HEAD:api/orders.pnr
  # Exits with code 1 if breaking changes detected

License

Apache 2.0 — see LICENSE


Pranor Standard Library

Reusable .pnr modules for common service patterns. Import what you need:

import { ok, notFound } from "stdlib/response.pnr"
import { requireAuth, bearerToken } from "stdlib/auth.pnr"

Module Index

ModuleExportsCategory
auth.pnrbearerToken, basicAuth, requireAuthSecurity
crypto.pnrhashPassword, verifyPassword, randomToken, randomHex, hmacSign, hmacVerifySecurity
jwt.pnrjwtEncode, jwtDecode, jwtIsExpiredSecurity
sanitize.pnrescapeHTML, stripTags, escapeSQL, sanitizeFilename, normalizeWhitespaceSecurity
ratelimit.pnrcreateLimiter, isAllowed, remaining, resetLimiterSecurity
validation.pnrrequired, isEmail, isURL, minLength, maxLength, validateFieldsInput
response.pnrok, created, badRequest, notFound, serverError, errorResponseHTTP
pagination.pnroffset, pageResponse, parsePageParamsHTTP
middleware.pnrcorsHeaders, requestId, logRequest, isPreflightHTTP
http_client.pnrgetJSON, postJSON, isSuccess, isClientError, isServerErrorHTTP
url.pnrencodeURI, parseQuery, buildQuery, joinPath, extractPathHTTP
datetime.pnrnow, timestamp, isExpired, formatDuration, sleepUtilities
strings_util.pnrslugify, truncate, capitalize, isEmpty, repeat, matchesUtilities
math.pnrmin, max, clamp, abs, percent, between, sum, averageUtilities
sort.pnrsortAsc, sortDesc, reverse, minOf, maxOfUtilities
collections.pnrgroupBy, unique, flatten, chunk, first, last, countWhereData
csv.pnrparseCSV, parseRow, toRow, toCSVData
diff.pnrhasChanged, fieldChanged, changeRecordData
env.pnrrequireEnv, envOrDefault, envInt, envBool, envExistsConfig
retry.pnrbackoffDelay, defaultMaxRetries, defaultBaseDelayResilience
circuit_breaker.pnrcreateBreaker, isOpen, recordSuccess, recordFailure, resetBreaker, failureCountResilience
queue.pnrcreateQueue, enqueue, dequeue, queueSize, queueIsEmptyResilience
events.pnron, emit, hasHandlerMessaging
metrics.pnrcounter, counterWithLabel, gauge, recordLatency, trackRequestObservability
testing_helpers.pnrassertEqual, assertNotNil, assertNil, assertContains, assertTrue, assertFalse, assertLengthTesting
health.pnrhealthy, unhealthy, degraded, buildHealthResponseOps
scheduler.pnrscheduleAfter, isScheduled, cancelSchedule, getDelayScheduling
webhook.pnrbuildPayload, sendWebhook, verifySignature, retryRecordIntegration
cors.pnrallowOrigin, allowAll, preflightResponse, isOriginAllowedHTTP
graceful.pnrinitShutdown, isShuttingDown, connectionOpened, connectionClosed, isDrainedOps
tracing.pnrtraceId, spanId, startSpan, endSpan, addTag, traceContextObservability
semaphore.pnrcreateSemaphore, tryAcquire, release, available, utilizationConcurrency
batch.pnrcreateBatch, addToBatch, batchSize, isBatchFull, flushBatchProcessing
idempotency.pnrcheckIdempotency, markProcessed, isProcessed, getProcessedResultReliability
job.pnrcreateJob, startJob, completeJob, failJob, jobStatusProcessing
feature_flags.pnrenableFlag, disableFlag, isEnabled, toggleFlag, initFlagConfig
config.pnrgetConfig, requireConfig, configInt, configBool, configList, hasConfigConfig
tenant.pnrextractTenant, tenantConfig, isTenantActive, tenantCacheKey, tenantFilterMulti-tenancy
dlq.pnrcreateDLQ, sendToDLQ, dlqSize, dlqHasItems, clearDLQReliability
audit.pnrauditLog, auditAction, auditAccess, auditAuth, auditDeniedCompliance
cache_patterns.pnrcacheKey, cacheGet, cacheSet, invalidate, invalidatePrefix, cacheTTL, computeIfAbsentCaching
pagination_cursor.pnrencodeCursor, decodeCursor, hasCursor, extractCursor, cursorResponse, cursorResponseWithHTTP
timeout.pnrwithDeadline, isTimedOut, remainingTime, startTimer, elapsed, hasExceededResilience
ip.pnrextractIP, isPrivate, isTrustedProxy, rateLimitKey, anonymizeIPSecurity
mask.pnrmaskEmail, maskPhone, maskCard, maskString, redactSecurity

Categories

Security

  • auth.pnr — Token extraction, bearer/basic auth, auth guards
  • crypto.pnr — Password hashing, HMAC signing, token generation
  • jwt.pnr — JWT encode/decode/expiry (lightweight; use pranor add github.com/golang-jwt/jwt/v5 for production)

HTTP

  • response.pnr — Standard HTTP response builders (ok, notFound, etc.)
  • pagination.pnr — Page offset calculation, response envelope
  • middleware.pnr — CORS headers, request ID generation, preflight detection
  • http_client.pnr — JSON GET/POST wrappers, status code helpers

Utilities

  • datetime.pnr — Timestamps, expiry checks, duration formatting
  • strings_util.pnr — Slugify, truncate, capitalize, pattern matching
  • collections.pnr — Array utilities (unique, flatten, chunk, first/last)

Config & Environment

  • env.pnr — Required env vars, defaults, type coercion (int/bool)

Resilience

  • retry.pnr — Exponential backoff calculation

Messaging

  • events.pnr — In-process event bus (emit/on pattern)

Testing

  • testing_helpers.pnr — Expressive assertions for test blocks

Operations

  • health.pnr — Custom health check builders
  • graceful.pnr — Shutdown state, connection draining, drain detection

Scheduling

  • scheduler.pnr — Dynamic runtime scheduling beyond every/cron

Integration

  • webhook.pnr — Outgoing webhook payloads, signature verification, retry records
  • cors.pnr — CORS header generation, origin checking, preflight responses

Concurrency

  • semaphore.pnr — Named semaphores with slot tracking and utilization metrics

Processing

  • batch.pnr — Accumulate-and-flush batch pattern with size tracking
  • job.pnr — Background job lifecycle (pending → running → completed/failed)

Reliability

  • idempotency.pnr — Idempotency key pattern for deduplication
  • dlq.pnr — Dead letter queue for failed message tracking

Multi-tenancy

  • tenant.pnr — Tenant extraction from requests, scoped config/cache/DB keys

Compliance

  • audit.pnr — Structured audit trail (actions, access, auth, denied events)

Usage Example

import { requireAuth, bearerToken } from "stdlib/auth.pnr"
import { ok, badRequest } from "stdlib/response.pnr"
import { required, isEmail } from "stdlib/validation.pnr"
import { envOrDefault } from "stdlib/env.pnr"

server envOrDefault("PORT", "8080")

route "POST" "/api/users" (req) {
    let authErr = requireAuth(req)
    if authErr != nil {
        return authErr
    }

    let errors = validate(req.body, {
        "email": "required,email",
        "name": "required"
    })
    if errors != nil {
        return badRequest(errors)
    }

    return ok({ "created": true })
}

Contributing

Add new modules as stdlib/<name>.pnr. Export functions with export fn. Follow existing patterns:

  • Pure functions where possible
  • No side effects unless explicitly documented
  • Use interface{} params (no type annotations) for maximum flexibility

Pranor CLI Reference

The pranor command is the single entry point for all development and deployment tasks.

Usage

pranor <command> [options] [arguments]

Commands

Development

CommandDescription
pranor init <name>Create a new Pranor project
pranor run <file.pnr> [--watch]Run a .pnr service (with optional hot-reload)
pranor dev <file.pnr>Run with hot-reload enabled (alias for run --watch)
pranor build <file.pnr> -o <binary>Compile to a native binary
pranor test <file.pnr> [--cover] [--filter]Run test blocks
pranor lint <file.pnr>Static analysis and syntax checking
pranor fmt <file.pnr>Auto-format source code
pranor replInteractive Pranor shell

Package Management

CommandDescription
pranor add <package>Add a Go package dependency
pranor remove <package>Remove a package
pranor packagesList installed packages
pranor publishPublish to Pranor Hub registry

Deployment

CommandDescription
pranor deploy [--target docker|k8s]Deploy service to Docker or Kubernetes
pranor dockerize <file.pnr>Generate a production Dockerfile

Infrastructure

CommandDescription
pranor gateManage Pranor Gate (API gateway)
pranor pulseManage Pranor Pulse (message queue)
pranor cacheManage Pranor Cache
pranor meshManage Pranor Mesh (service discovery)
pranor tunnelManage Pranor Tunnel (dev tunneling)
pranor traceManage Pranor Trace (distributed tracing)
pranor lockAcquire/release distributed locks
pranor secretManage secrets (inject, unseal)

Tooling

CommandDescription
pranor bench <file.pnr>Generate load test scripts from routes
pranor doc <file.pnr>Generate HTML API documentation
pranor diff <old.pnr> <new.pnr>Detect breaking API changes
pranor migrateRun database migrations
pranor doctorDiagnose environment issues
pranor upgradeCheck for and apply Pranor updates
pranor auditScan dependencies for vulnerabilities

Global Flags

FlagDescription
--versionPrint Pranor version
--helpShow help for any command
--env <name>Set environment profile (dev, staging, prod)
--verboseEnable verbose output

Environment Variables

VariableDescription
PRANOR_HOMEPath to Pranor installation (runtime, stdlib)
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL for tracing
PRANOR_DISCOVERYJSON service discovery manifest

Examples

# Create and run a project
pranor init my-api
cd my-api
pranor run main.pnr --watch

# Build for production
pranor build main.pnr -o my-api --target linux/amd64

# Run tests with coverage
pranor test main.pnr --cover

# Deploy to Docker
pranor deploy --target docker

# Add a package
pranor add github.com/google/uuid

Blog & Articles

Technical articles about Pranor architecture and design decisions.

These articles were originally published on Medium and provide deep-dives into individual modules.

ArticleTopic
Introducing PranorPlatform vision and architecture
Getting Started with Pranor LanguageLanguage tutorial
API Gateway Deep DiveGate architecture
Caching StrategiesCache patterns
Event-Driven ArchitecturePulse design
Full-Stack SaaSBuilding complete apps
Pranor Gate v2 — AI Guard & WAFAdvanced gateway features
Pranor Pulse — Event BrokerMessage broker internals
Pranor Vault — Object StorageS3-compatible storage design
Pranor Vault v2 — Vector SearchEmbedded vector search
Pranor Mesh — Service DiscoveryClient-side mesh
Pranor Console — DashboardObservability UI
Pranor Auth — IdentityOAuth2/OIDC/RBAC
Pranor Tunnel — Dev TunnelingWebSocket relay
Pranor Deploy — OrchestrationDocker/K8s deployment
Pranor Notify + ChronoNotifications & scheduling
Pranor Lang — The LanguageCompiler internals
Connecting the EcosystemHow modules work together

Tooling & IDE Support

Pranor provides dedicated developer tooling and IDE integration to support language editing, code refactoring, diagnostics, and visual cloud control.


1. VS Code Extension (pranor-vscode)

The official Pranor Platform & Language Tools extension converts VS Code into an integrated control plane for your entire microservice infrastructure.

Installation

  • Search for Pranor Platform & Language Tools in the VS Code Marketplace, or install the .vsix package:
    code --install-extension pranor-vscode-1.0.0.vsix
    

Key Features & Control Panels

  • Language Intelligence: Syntax highlighting, formatting, diagnostics, and code lens shortcuts for .pnr files.
  • Interactive API Client Panel (pranor.apiClient): In-editor HTTP test runner targeting Pranor Gate API routers.
  • Live Event Stream & DLQ Tailer Panel (pranor.tailPulseEvents): Tail Pranor Pulse event topics in real-time with one-click Dead Letter Queue (DLQ) replay.
  • S3 & Vector Search Explorer (pranor.vectorSearch): Browse Pranor Vault object buckets and run natural language HNSW cosine vector searches directly inside VS Code.
  • Live Distributed Flamegraph Viewer (pranor.flamegraphLogs): Trace execution bottlenecks with CPU/latency flamegraphs correlated side-by-side with log entries by trace_id.
  • Visual Secret Console (pranor.secretConsole): Manage cluster master keys, unseal vault stores, and inspect environment secrets.
  • Multi-Cluster Infrastructure Dashboard (pranor.clusterDeployments): Monitor multi-region cluster health and trigger one-click blue/green canary deployments.

2. Language Server Protocol (pranor-lsp)

pranor-lsp is an enterprise-grade Language Server implementing the Language Server Protocol (LSP) specification for standard editor integration (VS Code, Neovim, Emacs, Sublime Text, JetBrains).

Capabilities

  • Workspace-Wide Rename (textDocument/rename): Safe multi-file refactoring emitting WorkspaceEdit diffs across all workspace .pnr files.
  • Auto-Imports & Code Actions (textDocument/codeAction): Quick-fixes including missing use std/... imports and error handler stubs.
  • Fuzzy Workspace Symbol Search (workspace/symbol): High-performance background symbol indexing (Ctrl+T / Cmd+T).
  • Call Hierarchy Navigation (textDocument/prepareCallHierarchy): Visual incoming and outgoing call tree inspection for functions and HTTP routes.
  • Chained Type Inference (textDocument/completion): Context-aware member completions for chained calls (e.g. db.query().first(), encoding.base64.).
  • Document Highlighting & Incremental Sync (textDocument/documentHighlight): Zero-latency symbol occurrence highlighting on cursor focus.

Standalone Server Usage

Start pranor-lsp via standard stdin/stdout JSON-RPC:

pranor lsp
# or directly:
pranor-lsp

Pranor Gate — API Gateway & Ingress Router

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/gate
Default Port: 8080
License: AGPL-3.0 (OSS) / Enterprise License (EE with eBPF, GraphQL Federation, Geo-IP Steering)


Overview

Pranor Gate is a high-performance API gateway and reverse proxy that routes, secures, and transforms traffic between clients and upstream services. It features WASM-based plugin extensibility, AI-aware traffic management (prompt guard, semantic caching, PII redaction, token billing), weighted canary/blue-green deployments with automatic promotion, circuit breaking, SSE passthrough, WebSocket proxying, and a declarative per-route configuration model.

Pranor Gate can run as:

  • A standalone binary with local JSON configuration
  • An integrated module within the Pranor ecosystem with S3-based dynamic config, JWT auth, OTel tracing, and Console visibility
  • An edge proxy with Let's Encrypt auto-TLS or dynamic certificate fetching from Pranor Secret

Table of Contents


Key Features

FeatureDescription
WASM Plugin MiddlewareUpload and hot-register WebAssembly request/response transform modules per route at runtime.
Rate LimitingPer-IP, per-route RPM limits with optional Redis-backed distributed enforcement.
Circuit BreakerAutomatic circuit breaking on upstream failure thresholds with half-open recovery.
AI Prompt GuardInspects and sanitizes inputs for prompt injection attacks on AI/LLM routes.
Semantic CacheEmbedding-based response cache for AI endpoints — returns cached responses for semantically similar prompts.
PII RedactionAutomatic detection and masking of personally identifiable information in AI payloads.
Canary / Blue-GreenWeighted traffic splitting with automated canary promotion and error-rate rollback.
SSE PassthroughTransparent proxying of Server-Sent Events streams without buffering.
WebSocket ProxyFull-duplex WebSocket proxying with connection tracking.
mTLS to UpstreamsPer-route mutual TLS client certificates for service-to-service authentication.
Let's Encrypt Auto-TLSZero-config HTTPS with automatic ACME certificate provisioning.
Response CachingConfigurable per-route TTL response cache for GET requests.
Backpressure ControlConcurrent request limiting with queue overflow protection.
OpenAPI ValidationRequest payload validation against OpenAPI 3.0 spec per route.
IP Allowlist/BlocklistPer-route network ACLs via CIDR ranges.
Structured Access LogsJSONL access logging with request/response metadata.
GitOps Config SyncWebhook-triggered git pull + config reload for GitOps workflows.
Dynamic Policy EngineServPolicy integration for fine-grained authorization rules compiled to WASM.
AI Agent Security FirewallProgrammable zero-trust execution boundary inspecting AI tool call intent, parameters, and risk score for ALLOW / DENY / APPROVE / TRANSFORM decisions.
Agent Security ChainFirst-class Agent ID -> User ID -> Tenant ID -> Capability identity tracking and delegation authorization.
Human-in-the-Loop (HITL)Asynchronous approval workflows (Agent -> Gate -> Approval -> Gate -> Tool) for high-risk capability execution.
Agent Trajectory SimulationRecord execution steps and replay against candidate models/policies to simulate and diff execution outcomes prior to deployment.
Agent Budget & Blast-RadiusTool-invocation level limits (max tool calls/session, action rate limits, queue bounds).
Protocol-Agnostic ExposerRegister capabilities once and auto-expose over MCP, gRPC, HTTP/REST, and WASM plugin adapters.
AI Token BillingPer-route and per-tenant LLM token usage tracking with budget enforcement.
Traffic ReplayRecord traffic to JSONL and replay against WASM middlewares or candidate backends.

Architecture

graph TD
    subgraph Edge ["Global Ingress Layer"]
        DNS["Geo-IP Anycast DNS"]
        XDP["eBPF XDP Packet Filter"]
    end

    subgraph Security ["Zero-Trust Security and WASM Engine"]
        TLS["PCIe Hardware TLS Offload"]
        WASM["WASM Security Sandbox"]
        PromptGuard["AI Prompt Injection Guard"]
    end

    subgraph Core ["Proxy Router and Rate Limiter"]
        CRDT["Global CRDT Rate Limiter"]
        Router["Dynamic Reverse Proxy"]
    end

    subgraph Upstream ["Upstream Microservices"]
        AIModel["LLM / Model Service"]
        Microservice["gRPC / REST Microservice"]
    end

    DNS --> XDP
    XDP --> TLS
    TLS --> WASM
    WASM --> PromptGuard
    PromptGuard --> CRDT
    CRDT --> Router
    Router -->|mTLS| AIModel
    Router -->|mTLS| Microservice

Request Processing Sequence & WASM Execution Flow

sequenceDiagram
    autonumber
    participant Client as Client Application
    participant Gate as Pranor Gate Ingress
    participant Auth as Pranor Auth / JWT Validator
    participant WASM as WASM Plugin Sandbox
    participant AI as AI Prompt Guard
    participant Service as Upstream Microservice

    Client->>Gate: HTTP Request / POST /v1/ai/prompt
    Gate->>Auth: Validate JWT / SPIFFE SVID Token
    Auth-->>Gate: Token Validated (Claims + Tenant Context)
    Gate->>WASM: Execute Request Transformer (WASM)
    WASM-->>Gate: Transformed Headers & Body
    Gate->>AI: Evaluate Prompt Injection & PII Redaction
    AI-->>Gate: Sanitized Prompt & Risk Score (Passed)
    Gate->>Service: Forward Request (mTLS + Retrying Transport)
    Service-->>Gate: Response Stream (200 OK)
    Gate->>WASM: Execute Response Transformer (WASM)
    WASM-->>Gate: Final Formatted Payload
    Gate-->>Client: Streamed HTTP Response + X-Token-Cost

Ecosystem Cross-Module Integration

Pranor Gate acts as the front door for the entire Pranor platform, seamlessly interfacing with core infrastructure services:

  • Pranor Auth: Automatically verifies incoming JWT signatures, SAML claims, and SPIFFE/SPIRE x509 workload identities (PRANOR_JWT_SECRET).
  • Pranor Secret: Dynamically fetches and auto-rotates TLS server certificates and client mTLS credentials without restarting the proxy.
  • Pranor Trace: Generates W3C-compliant traceparent OpenTelemetry headers, emitting distributed trace spans for every proxied request.
  • Pranor Console: Streams real-time throughput, p99 latency histograms, and active WASM plugin health metrics directly to the control plane dashboard.
  • Pranor Vault: Pulls dynamic S3-backed JSON route configurations and uploads recorded JSONL traffic replay logs.

Installation & Deployment

Binary

cd pranor/gate
go build -o pranor-gate .
./pranor-gate

Docker

docker run -p 8080:8080 ghcr.io/vyuvaraj/pranor-gate:latest

Docker Compose

services:
  gate:
    image: ghcr.io/vyuvaraj/pranor-gate:latest
    ports:
      - "8080:8080"
    volumes:
      - ./config.json:/app/config.json
    environment:
      - PRANOR_JWT_SECRET=your-secret

As Part of Pranor Ecosystem

When running under the Pranor platform, Gate integrates automatically with Auth (JWT/mTLS), Secret (dynamic certificates), Trace (OTel spans), and Console (dashboard visibility). Configuration can be pulled from an S3-compatible store for centralized management.


Configuration

JSON Config (config.json)

{
  "addr": ":8080",
  "auth_token": "gateway-secret-token",
  "tls_cert": "",
  "tls_key": "",
  "routes": [
    {
      "prefix": "/api/v1/services",
      "target": "http://127.0.0.1:8081",
      "middleware": "uppercase",
      "rate_limit_rpm": 120,
      "cache_ttl_seconds": 60,
      "access_log": true
    },
    {
      "prefix": "/ai/v1",
      "target": "http://127.0.0.1:11434",
      "enable_semantic_cache": true,
      "enable_prompt_guard": true,
      "semantic_token_limit_per_min": 10000
    }
  ]
}

Environment Variables

VariableDefaultDescription
PRANOR_JWT_SECRETJWT signing key for token-based auth
PRANOR_AUTO_TLSfalseEnable Let's Encrypt auto-TLS
PRANOR_AUTO_TLS_DOMAINDomain for ACME certificate
PRANOR_CONFIG_S3_BUCKETS3 bucket for remote config
PRANOR_DISCOVERYService discovery endpoint
PRANOR_SECRET_URLPranor Secret service URL for dynamic certs
PRANOR_SECRET_API_KEYAPI key for Pranor Secret
PRANOR_SECRET_TENANT_IDdefaultTenant ID for secret lookup
PRANOR_GATE_LIMITS_REDIS_URLRedis URL for distributed rate limiting
PRANOR_REGISTRYhttps://registry.pranor.orgWASM middleware registry URL
PRANOR_CLUSTERdefaultCluster identifier for tenant policies
PRANOR_REGIONus-eastRegion identifier for tenant policies
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL

CLI Flags

FlagDefaultDescription
--configconfig.jsonPath to configuration file

CLI Subcommands

CommandDescription
pranor-gateStart the gateway server
pranor-gate dashboardLaunch terminal TUI traffic dashboard
pranor-gate replay --log FILE --middleware FILE.wasmReplay recorded traffic through WASM
pranor-gate replay --shadow --log FILE --target URLShadow diff replay against candidate backend
pranor-gate install <name>Install WASM middleware from registry
pranor-gate policy compile <file.policy> -o <file.wasm>Compile policy DSL to WASM

API Reference

Base URL: http://localhost:8080
API Version: /api/v1/ (recommended) or /api/ (legacy)

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor","version":"1.0.0"}

GET /readyz

Readiness probe. Same format as healthz.


GET /api/v1/routes

List all configured routes.

Response (200):

[
  {
    "prefix": "/api/v1/services",
    "target": "http://127.0.0.1:8081",
    "middleware": "uppercase",
    "rate_limit_rpm": 120
  }
]

POST /api/v1/routes

Register or update a route dynamically.

Request:

{
  "prefix": "/api/v2/users",
  "target": "http://users-service:8080",
  "rate_limit_rpm": 200,
  "cache_ttl_seconds": 30,
  "ip_allowlist": ["10.0.0.0/8"]
}

Response (200):

Route registered successfully

DELETE /api/v1/routes?prefix=/api/v2/users

Remove a route.

Response (200):

Route deleted successfully

POST /api/v1/admin/middleware/

Register a WASM middleware plugin at runtime.

Request: Raw .wasm binary as request body.

Response (200):

WASM Middleware auth-check compiled and registered

GET /api/v1/admin/connections

List active backend connections.

Response (200):

{
  "http://127.0.0.1:8081": 5,
  "http://127.0.0.1:8082": 2
}

DELETE /api/v1/admin/cache?prefix=/api/v1/data

Invalidate response cache entries.

Response (200):

{
  "status": "success",
  "entries_invalidated": 12,
  "prefix": "/api/v1/data"
}

POST /api/v1/admin/policy/reload

Hot-reload the dynamic IAM policy schema.

Request (optional body): Policy schema JSON.

Response (200):

{"status": "success", "message": "Policy schema updated"}

POST /api/v1/admin/policy/revoke

Revoke all sessions for a user.

Request:

{"username": "compromised-user"}

Response (200):

{"status": "success", "message": "Session revoked for user compromised-user"}

GET /api/v1/admin/ai-billing

Retrieve AI token usage and cost metrics.

Response (200):

{
  "total_tokens": 1523400,
  "total_cost_usd": 4.57,
  "per_tenant": {
    "tenant-a": {"tokens": 800000, "cost_usd": 2.40}
  }
}

POST /api/v1/admin/ai-billing

Set per-tenant AI budget limits.

Request:

{
  "tenant_id": "tenant-a",
  "max_cost_per_day_usd": 10.00,
  "max_tokens_per_minute": 50000
}

GET /api/v1/admin/ai-cost-attribution

Per-route AI token and cost attribution dashboard.

Response (200):

{
  "routes": [
    {
      "prefix": "/ai/v1",
      "total_tokens": 500000,
      "total_cost_usd": 1.50,
      "estimated_savings": 0.30
    }
  ],
  "summary": {
    "total_cost_usd": 4.57,
    "total_tokens": 1523400,
    "estimated_savings": 0.91,
    "savings_percent": 16.6
  }
}

GET /api/v1/admin/metrics/ws

WebSocket endpoint streaming real-time gateway metrics (RPS, error rate, active connections).


POST /api/v1/admin/console/sync

Synchronize full route configuration from Pranor Console.

Request:

{"routes": [...]}

GET /api/v1/admin/console/sync

Get current gateway state snapshot (routes, connections, metrics).


POST /api/v1/gitops/webhook

Trigger a git pull + config reload for GitOps-managed configuration.

Response (200):

{
  "status": "success",
  "message": "GitOps config sync completed successfully",
  "git_output": "Already up to date."
}

POST /api/v1/routes/register

Register a route via the compiler connector (for Pranor Lang integration).


GET /api/docs

Embedded interactive API documentation page.

GET /api/docs/openapi.json

Auto-generated OpenAPI specification from current routes.


Routing & Traffic Management

Prefix-Based Matching

Routes are matched by longest-prefix on the request URL path. The first matching route wins.

Weighted Canary / Blue-Green Deployments

Distribute traffic between stable and canary targets by weight:

{
  "prefix": "/api/v1/orders",
  "targets_weighted": [
    {"url": "http://orders-v1:8080", "weight": 90},
    {"url": "http://orders-v2:8080", "weight": 10}
  ],
  "canary_auto_promote": true,
  "canary_promote_step": 10,
  "canary_promote_sec": 60,
  "canary_max_error_rate": 0.01
}

The canary engine automatically:

  1. Increments canary weight by canary_promote_step every canary_promote_sec seconds
  2. Monitors error rate on the canary target
  3. Rolls back to 100% stable if error rate exceeds canary_max_error_rate
  4. Disables auto-promotion once canary reaches 100%

Load Balancing

Multiple targets support round-robin and least-connections strategies:

{
  "prefix": "/api/v1/users",
  "targets": ["http://users-1:8080", "http://users-2:8080", "http://users-3:8080"],
  "load_balancer": "least_conn"
}

Circuit Breaker

Automatically opens when upstream error rate exceeds threshold, preventing cascade failures. Half-open state probes recovery.

Backpressure Control

Per-route concurrency limiting with queue overflow:

{
  "max_concurrent_requests": 100,
  "max_queue_size": 500,
  "queue_timeout_ms": 5000
}

Returns 503 Service Unavailable when queue is full, 504 Gateway Timeout on queue timeout.

Response Caching

{
  "cache_ttl_seconds": 60,
  "cache_methods": ["GET"]
}

WASM Plugin System

Architecture

WASM middlewares are compiled via wazero (pure-Go WebAssembly runtime, no CGO). Plugins receive the request, can transform headers/body, and return modified content.

Registering a Plugin

# From registry
pranor-gate install jwt-auth

# Upload directly
curl -X POST http://localhost:8080/api/v1/admin/middleware/my-filter \
  -H "Authorization: Bearer gateway-secret-token" \
  --data-binary @my-filter.wasm

Per-Route Assignment

{
  "prefix": "/api/v1/data",
  "middleware": "my-filter",
  "response_middleware": "response-transform"
}

WASM A/B Testing

Split traffic between different WASM middleware versions:

{
  "wasm_split": {
    "targets": [
      {"middleware_name": "filter-v1", "weight": 80},
      {"middleware_name": "filter-v2", "weight": 20}
    ]
  }
}

Policy DSL Compilation

Write human-readable policies and compile to WASM:

# auth.policy
allow GET /api/public/*
deny POST /api/admin/* if header.role == "viewer"
allow * * if header.x-internal == "true"
pranor-gate policy compile auth.policy -o auth.wasm

AI Guard & LLM Routing

Prompt Guard

Detects and blocks prompt injection attempts on AI-routed traffic:

{"prefix": "/ai/v1", "prompt_guard": true}

PII Redaction

Masks sensitive data (emails, SSN, credit cards) before forwarding to LLM backends:

{"prefix": "/ai/v1", "pii_redact": true}

Semantic Cache

Caches LLM responses and returns cached versions for semantically similar prompts (cosine similarity > 0.85):

{"prefix": "/ai/v1", "semantic_cache": true}

LLM Routing with Fallback

Route to a primary model with automatic fallback on low confidence:

{
  "llm_routing": {
    "primary": {"url": "http://ollama:11434", "model": "llama3"},
    "fallback": {"url": "https://api.openai.com", "model": "gpt-4"},
    "confidence_header": "X-Confidence",
    "min_confidence": 0.7
  }
}

Semantic Rate Limiting

Token-based rate limiting for LLM routes (tokens-per-minute rather than requests-per-minute):

{"semantic_rate_limit": true, "semantic_token_limit_per_min": 10000}

Prompt A/B Testing

Route different prompt templates to measure response quality.


Security

Bearer Token Auth

Set auth_token in config. All non-health endpoints require:

Authorization: Bearer gateway-secret-token

JWT Authentication

When PRANOR_JWT_SECRET is set, validates JWT Bearer tokens. Supports policy versioning — stale tokens get X-Token-Refresh: true header.

Dynamic Secret Fetching

Gate can fetch TLS certificates and JWT secrets dynamically from Pranor Secret at startup.

mTLS to Upstreams

Per-route client certificate for backend authentication:

{
  "client_cert_path": "/certs/client.crt",
  "client_key_path": "/certs/client.key",
  "root_ca_path": "/certs/backend-ca.crt"
}

Multi-Tenant API Keys

Per-key rate limits, route restrictions, and tenant isolation:

{"require_api_key": true, "allowed_tenants": ["tenant-a", "tenant-b"]}

IP Allowlist / Blocklist

{
  "ip_allowlist": ["10.0.0.0/8", "192.168.1.0/24"],
  "ip_blocklist": ["1.2.3.4"]
}

Request Body Size Limits

Per-route body size enforcement (default 10MB):

{"max_body_size": 5242880}

Session Revocation

Instant session revocation via admin API without waiting for token expiry.

Dynamic IAM Policy (ServPolicy)

Upload OPA-style policy schemas that Gate evaluates inline per request.


Observability

Metrics

MetricTypeDescription
total_requestsCounterTotal proxied requests
total_errorsCounterTotal upstream errors
request_rateGaugeRequests/second (1s window)
error_rateGaugeErrors/second (1s window)
active_connectionsGaugePer-target active connections

WebSocket Live Metrics

Connect to /api/v1/admin/metrics/ws for 1-second streaming metrics updates.

Access Logging

Structured JSONL access logs per route:

{
  "timestamp": "2026-01-15T10:00:00Z",
  "method": "GET",
  "path": "/api/v1/users/123",
  "status": 200,
  "latency_ms": 42,
  "client_ip": "10.0.1.5",
  "upstream": "http://users:8080"
}

OpenTelemetry Tracing

Every proxied request gets an OTel span with method, route, status code, and upstream latency.

Terminal Dashboard

pranor-gate dashboard

Live TUI showing real-time RPS, P99 latency, circuit breaker state, cache hit rate.


Client Libraries & CLI

cURL

# Register a route
curl -X POST http://localhost:8080/api/v1/routes \
  -H "Authorization: Bearer gateway-secret-token" \
  -H "Content-Type: application/json" \
  -d '{"prefix":"/api/v2/users","target":"http://users:8080","rate_limit_rpm":100}'

# Upload WASM middleware
curl -X POST http://localhost:8080/api/v1/admin/middleware/auth-check \
  -H "Authorization: Bearer gateway-secret-token" \
  --data-binary @auth-check.wasm

# Invalidate cache
curl -X DELETE "http://localhost:8080/api/v1/admin/cache?prefix=/api/v1/data" \
  -H "Authorization: Bearer gateway-secret-token"

Pranor CLI

pranor gate routes list
pranor gate routes add --prefix /api/v2 --target http://backend:8080 --rate-limit 100
pranor gate middleware install jwt-auth
pranor gate dashboard
pranor gate replay --log traffic.jsonl --middleware filter.wasm

Enterprise Edition

FeatureOSSEE
WASM plugin middleware
Rate limiting (local)
Rate limiting (Redis distributed)
Circuit breaker
Canary / Blue-Green deployments
AI Prompt Guard & PII Redaction
Semantic cache
SSE passthrough & WebSocket proxy
mTLS to upstreams
Let's Encrypt Auto-TLS
GitOps config sync
Traffic replay engine
AI token billing & budgets
Kernel eBPF XDP DDoS bypass (100Gbps)
Geo-IP latency anycast steering
GraphQL schema stitching & federation
SSL offloading (hardware acceleration)
AI self-defending WAF
Multi-cluster enterprise control plane

Operational Runbook

Route not matching / 502 Bad Gateway

  1. Check /api/v1/routes for the configured routes
  2. Verify the request path has the correct prefix
  3. Ensure the upstream target is reachable from the gateway
  4. Check circuit breaker state via metrics

High latency on specific route

  1. Check /api/v1/admin/connections for connection count
  2. Review backpressure settings — max_concurrent_requests may be too low
  3. Check if circuit breaker is in half-open state (probing slowly)
  4. Look at upstream health via WebSocket metrics stream

Rate limiting kicking in unexpectedly

  1. Verify rate_limit_rpm is set correctly on the route
  2. Check if Redis-based distributed limiting is configured — all instances share state
  3. Per-API-key limits may be more restrictive than route limits
  4. Review semantic token rate limits for AI routes

WASM middleware failing

  1. Check gateway logs for WASM compilation errors
  2. Use pranor-gate replay --log traffic.jsonl --middleware broken.wasm to test offline
  3. Verify WASM module exports the correct ABI functions
  4. Check if the middleware registry URL is reachable

Canary deployment not promoting

  1. Check error rate on canary target — exceeding canary_max_error_rate causes rollback
  2. Verify canary_auto_promote is true
  3. Ensure at least 3 requests have hit the canary (minimum sample for error rate calculation)
  4. Check canary_promote_sec interval — promotion may not have triggered yet

TLS certificate issues

  1. If using auto-TLS, ensure port 80 is accessible for HTTP challenge
  2. For Pranor Secret integration, verify PRANOR_SECRET_URL connectivity
  3. Check certificate paths in config for file-based TLS
  4. Review gateway startup logs for certificate loading errors

Versioning & Compatibility

  • API is versioned at /api/v1/
  • Legacy /api/ paths continue to work (internally mapped to v1)
  • Configuration format is backward-compatible across minor versions
  • WASM ABI is stable — plugins compiled for v1.0 work on all v1.x releases

Pranor Pulse — Async Event Broker & Message Queue

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/pulse
Default Ports: 8082 (HTTP), 61613 (STOMP)
License: AGPL-3.0 (OSS) / Enterprise License (EE with Raft, MirrorMaker, KMS Encryption)


Overview

Pranor Pulse is a multi-protocol message broker and event streaming platform that supports STOMP, Kafka wire protocol, and MQTT v5 simultaneously. It provides durable WAL-based persistence, WASM-powered message transforms, dead letter queues with intelligent triage, consumer groups, partitioned topics, priority queues, delayed/scheduled messages, schema validation, tiered cold storage offloading, and browser-native OPFS queue support.

Pranor Pulse can run as:

  • A standalone binary with zero external dependencies (WAL file-backed)
  • An integrated module within the Pranor ecosystem with mTLS, RBAC, OTel tracing, and Console visibility
  • A Kafka-compatible broker accepting native Kafka producer/consumer clients
  • A browser-embedded queue via OPFS for offline-first PWAs

Table of Contents


Key Features

FeatureDescription
Multi-ProtocolSTOMP 1.2, Kafka wire protocol, MQTT v5 — all on a single broker.
WAL PersistenceWrite-ahead log ensures zero message loss across restarts.
WASM TransformsPer-topic WebAssembly transform pipelines for filtering, enrichment, or routing.
Dead Letter QueuesAutomatic DLQ routing on transform failures with triage and requeue APIs.
Consumer GroupsRound-robin message dispatch across group members with rebalancing.
Partitioned TopicsFNV-1a key-based partitioning with partition-level subscribers.
Priority QueuesPriority-ordered message delivery — higher priority messages dispatched first.
Delayed MessagesSchedule message delivery N milliseconds in the future via TimeWheel.
Message DeduplicationIdempotent message-ID and producer-sequence-number dedup.
Schema RegistryPer-topic schema validation — reject non-conforming payloads at publish time.
Tiered StorageAutomatic offload of closed WAL segments to S3-compatible cold storage.
Message TTLPer-message expiry — expired messages route to DLQ instead of delivery.
Topic CompactionKey-based log compaction retaining only the latest value per key.
Wildcard SubscriptionsMQTT-style wildcard topics (sensors.*, events.#).
BackpressureQueue capacity limits with configurable overflow behavior.
Rate LimitingToken-bucket publish rate limiting per broker.
WebSocket SubscriptionsReal-time browser consumption via WebSocket upgrade.
SSE SubscriptionsServer-Sent Events stream for lightweight real-time consumption.
Offset ManagementConsumer group offset commit/fetch with replay-from-offset support.
Time-Based SeekSeek to a timestamp offset for event replay.
CDC (Change Data Capture)Database change event capture and publishing.
OPFS Browser QueueOffline-first browser queue using Origin Private File System.
Batch PublishMulti-message atomic publish in a single request.
DLQ AI TriageIntelligent DLQ classification and suggested remediation.

Architecture

graph TD
    subgraph Adapters ["Multi-Protocol Wire Interface"]
        STOMP["STOMP 1.2 Listener :61613"]
        Kafka["Kafka Wire Decoder :9092"]
        MQTT["MQTT v5 Broker :1883"]
        HTTP["HTTP REST API :8082"]
    end

    subgraph Core ["Core Event Streaming Broker"]
        Registry["Topic Registry and Wildcard Matcher"]
        Dedup["Idempotent Dedup Window"]
        Schema["Schema Compatibility Inspector"]
        WASM["WASM Transform Pipeline"]
        Dispatch["Partition and Consumer Group Dispatcher"]
    end

    subgraph Storage ["WAL and Tiered Persistence Engine"]
        WAL["Write-Ahead Log Engine"]
        DLQ["Dead-Letter Queue Storage"]
        ColdStore["S3 Cold Storage Offloader"]
    end

    subgraph Timers ["Delayed Delivery and Recovery"]
        TimeWheel["TimeWheel Delayed Scheduler"]
        OffsetStore["Consumer Group Offset Store"]
    end

    STOMP --> Registry
    Kafka --> Registry
    MQTT --> Registry
    HTTP --> Registry
    Registry --> Dedup
    Dedup --> Schema
    Schema --> WASM
    WASM --> Dispatch
    Dispatch --> WAL
    WAL --> DLQ
    WAL -.-> ColdStore
    TimeWheel -.-> Dispatch
    OffsetStore -.-> Dispatch

Event Streaming & Consumer Dispatch Sequence Flow

sequenceDiagram
    autonumber
    participant Producer as Event Producer (Kafka / STOMP / REST)
    participant Pulse as Pranor Pulse Broker Core
    participant Dedup as Sliding Dedup Window
    participant WASM as WASM Transform Sandbox
    participant WAL as Hardware AES-NI WAL Storage
    participant Consumer as Consumer Group Subscriber
    participant DLQ as Dead-Letter Queue (DLQ)

    Producer->>Pulse: Publish Event (Topic: "orders.created", Payload)
    Pulse->>Dedup: Verify Message ID & Producer Sequence Number
    Dedup-->>Pulse: Unique Payload (Passed)
    Pulse->>WASM: Execute Topic Transform Pipeline (WASM)
    alt Transform Succeeded
        WASM-->>Pulse: Enriched Event Payload
        Pulse->>WAL: Append Payload to Active WAL Segment
        WAL-->>Pulse: Log Offset Committed
        Pulse->>Consumer: Dispatch Event Payload via Consumer Group Round-Robin
        Consumer-->>Pulse: Acknowledge Event Commit (Offset Updated)
    else Transform Failed / Processing Expiry
        WASM-->>Pulse: Exception / Transform Error
        Pulse->>DLQ: Route Event Payload to Dead-Letter Queue
        DLQ-->>Pulse: DLQ Entry Logged & AI Triage Suggested
    end

Ecosystem Cross-Module Integration

Pranor Pulse serves as the primary asynchronous message bus across the Pranor platform:

  • Pranor Flow: Dispatches saga workflow execution steps, compensation triggers, and human-in-the-loop task events via Pulse topics.
  • Pranor Vault: Receives closed WAL segments offloaded automatically to S3 object buckets for long-term cold archive retention.
  • Pranor Trace: Propagates trace context headers across message boundaries, tracking event latency flamegraphs end-to-end.
  • Pranor Console: Provides real-time event throughput dashboards, consumer group rebalance monitors, and 1-click DLQ message replay UI.
  • Pranor Gate: Relays event streams to web clients via WebSocket upgrader and SSE stream passthrough.

Installation & Deployment

Binary

cd pranor/pulse
go build -o pranor-pulse .
./pranor-pulse

Docker

docker run -p 8082:8082 -p 61613:61613 ghcr.io/vyuvaraj/pranor-pulse:latest

Docker Compose

services:
  pulse:
    image: ghcr.io/vyuvaraj/pranor-pulse:latest
    ports:
      - "8082:8082"
      - "61613:61613"
    environment:
      - PRANOR_PULSE_WAL_PATH=/data/queue.wal
    volumes:
      - pulse-data:/data
volumes:
  pulse-data:

As Part of Pranor Ecosystem

When running under the Pranor platform, Pulse integrates automatically with Auth (JWT/mTLS), Trace (OTel spans), and Console (dashboard visibility). Multi-tenant topic namespacing is enforced automatically.


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_PULSE_WAL_PATHqueue.walPath to write-ahead log file
PRANOR_PULSE_PUBLISH_RATE100Token bucket publish rate (messages/sec)
PRANOR_PULSE_PUBLISH_CAPACITY100Token bucket burst capacity
PRANOR_PULSE_BACKPRESSURE_LIMIT1000Max messages in per-topic queue before backpressure
PRANOR_PULSE_S3_ENDPOINTS3 endpoint for cold storage offloading
PRANOR_PULSE_S3_BUCKETS3 bucket for WAL segment offload
PRANOR_PULSE_S3_TOKENS3 auth token for offloader
PRANOR_JWT_SECRETJWT signing key for token auth
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL
TLS_CERT_FILEPath to TLS certificate
TLS_KEY_FILEPath to TLS private key

STOMP Credentials

Default credentials (configured in code, overridable via ecosystem auth):

  • Username: admin
  • Password: secret

HTTP API Auth Token

Default: secret-token (standalone mode). In ecosystem mode, full JWT/mTLS auth chain is used.


API Reference

Base URL: http://localhost:8082
API Version: /api/v1/ (recommended) or /api/ (legacy)

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor","version":"1.0.0"}

GET /readyz

Readiness probe.


POST /api/v1/publish

Publish a message to a topic.

Request:

{
  "topic": "orders.created",
  "payload": "{\"order_id\":\"abc-123\",\"amount\":99.99}",
  "key": "abc-123",
  "priority": 5,
  "delay_ms": 0,
  "message_id": "msg-unique-001",
  "ttl_ms": 60000
}
FieldTypeRequiredDescription
topicstringDestination topic
payloadstringMessage content (JSON string)
keystringPartition key (FNV-1a hash for partition assignment)
priorityintHigher = dispatched first (default: 0)
delay_msintDelay delivery by N milliseconds
message_idstringUnique ID for deduplication
ttl_msintMessage expires after N ms (routes to DLQ)
producer_idstringProducer identity for sequence dedup
sequence_numberintMonotonic sequence for producer dedup

Response (200):

{
  "status": "success",
  "topic": "orders.created",
  "processed_payload": "{\"order_id\":\"abc-123\",\"amount\":99.99}"
}

Backpressure Response (503):

{
  "error": "queue capacity exceeded: backpressure active",
  "code": "ERR_BACKPRESSURE"
}

POST /api/v1/publish/batch

Publish multiple messages atomically.

Request:

{
  "messages": [
    {"topic": "events.user", "payload": "{\"action\":\"login\"}"},
    {"topic": "events.user", "payload": "{\"action\":\"page_view\"}"}
  ]
}

GET /api/v1/topics

List all topics with metadata.

Response (200):

{
  "topics": [
    {
      "name": "orders.created",
      "subscribers": 3,
      "partitions": 3,
      "has_transform": true,
      "dlq_topic": "orders.created.dlq"
    }
  ],
  "count": 1
}

POST /api/v1/topics/{topic}/transform

Register a WASM transform for a topic.

Request: Raw .wasm binary as request body.

Response (200):

WASM transform registered for topic orders.created

To clear a transform, send an empty body.


POST /api/v1/topics/{topic}/dlq

Register a Dead Letter Queue for a topic.

Request:

{"dlq_topic": "orders.created.dlq"}

GET /api/v1/topics/{topic}/dlq

List DLQ messages for a topic.

Response (200):

{
  "messages": [
    {
      "message_id": "dlq-1234567890",
      "source_topic": "orders.created",
      "original_payload": "{\"bad\":\"data\"}",
      "failure_reason": "WASM transform error: invalid field",
      "timestamp": 1706000000,
      "retry_count": 1
    }
  ],
  "total": 1,
  "dlq_topic": "orders.created.dlq"
}

GET /api/v1/topics/{topic}/dlq/summary

AI-powered DLQ analysis with failure pattern clustering.

GET /api/v1/topics/{topic}/dlq/triage

Intelligent DLQ triage with remediation suggestions.

POST /api/v1/topics/{topic}/dlq/requeue

Requeue a DLQ message (optionally patched) back to its source topic.

Request:

{"message_id": "dlq-1234567890", "payload": "{\"fixed\":\"data\"}"}

POST /api/v1/topics/{topic}/schema

Register a validation schema for a topic.

Request:

{"order_id": "string", "amount": "number", "status": "string"}

Messages that fail schema validation are rejected at publish time.


GET /api/v1/topics/{topic}/anomalies

Detect anomalous message patterns (spike detection, schema drift).


GET /api/v1/subscribe/

Subscribe via Server-Sent Events for real-time message consumption.

Response (text/event-stream):

data: {"order_id":"abc-123","amount":99.99}

data: {"order_id":"def-456","amount":45.00}

GET /ws/subscribe/

Subscribe via WebSocket for real-time bidirectional message consumption.


GET /api/v1/tail?topic=

Tail the latest N messages from a topic (useful for debugging).

Query Parameters:

ParamDefaultDescription
topicTopic to tail
n10Number of recent messages

GET /api/v1/stats

Broker statistics and metrics.

Response (200):

{
  "messages_published": 152340,
  "wasm_executions": 45000,
  "wasm_execution_errors": 12,
  "wasm_avg_duration_ns": 250000,
  "topics_count": 8,
  "wal_entries": 152340
}

GET /api/v1/stats/ws

WebSocket endpoint streaming real-time broker stats every second.


POST /api/v1/replay

Replay messages from a specific offset for a consumer group.

Request:

{
  "topic": "orders.created",
  "start_offset": 100,
  "group_name": "analytics-group"
}

Response (200):

{"replayed": 52}

POST /api/v1/replay/time

Seek to a timestamp-based offset.

Request:

{"topic": "orders.created", "timestamp": 1706000000000}

Response (200):

{"offset": 1523}

GET /api/v1/offsets

Get committed offsets for a consumer group.

POST /api/v1/offsets

Commit an offset for a consumer group.

Request:

{"group": "analytics", "topic": "orders.created", "offset": 1523}

GET /api/v1/consumers/lag

Get consumer group lag (difference between latest offset and committed offset).


POST /api/v1/topics/retention

Configure topic retention policy.


POST /api/v1/admin/offloader

Configure tiered storage offloader.

Request:

{
  "s3_endpoint": "http://vault:9000",
  "s3_bucket": "pulse-cold-storage",
  "s3_token": "auth-token"
}

GET /metrics

Prometheus-compatible metrics.

# HELP pranor_pulse_messages_published_total Total messages published
# TYPE pranor_pulse_messages_published_total counter
pranor_pulse_messages_published_total 152340

# HELP pranor_pulse_wasm_executions_total Total WASM transform executions
# TYPE pranor_pulse_wasm_executions_total counter
pranor_pulse_wasm_executions_total 45000

GET /api/v1/events/

Event sourcing API — list events with filtering.


POST /api/v1/sqlite/query

Query broker metadata via embedded SQLite interface.


Messaging Semantics

Publish/Subscribe (Fan-Out)

Every subscriber on a topic receives every message:

Producer → publish("events.user", msg)
  ├── Subscriber-A receives msg
  ├── Subscriber-B receives msg
  └── Subscriber-C receives msg

Consumer Groups (Competing Consumers)

Messages are round-robin dispatched to one member per group:

Producer → publish("orders", msg1)
  Group "processors":
    ├── Worker-1 receives msg1
    ├── Worker-2 receives msg2 (next message)
    └── Worker-3 receives msg3 (next message)

Partitioned Topics

Key-based partitioning ensures ordering per key:

publish("orders", key="customer-A", msg1) → Partition 0
publish("orders", key="customer-A", msg2) → Partition 0 (same key = same partition)
publish("orders", key="customer-B", msg3) → Partition 2 (different key)

Priority Queues

Messages with higher priority are dispatched first regardless of arrival order:

publish("tasks", payload="low", priority=1)
publish("tasks", payload="high", priority=10)
publish("tasks", payload="medium", priority=5)
→ Consumer receives: "high", "medium", "low"

Delayed Messages

Schedule delivery N milliseconds in the future:

publish("reminders", payload="Check order status", delay_ms=300000)
→ Message delivered after 5 minutes

The TimeWheel implementation provides 10ms resolution with O(1) scheduling.

Message Deduplication

Two dedup mechanisms:

  1. Message-ID dedup: Same message_id within 5-minute window is dropped
  2. Producer-sequence dedup: Per producer_id, any sequence_number ≤ last_seen is dropped

Message TTL / Expiry

Messages with ttl_ms expire and route to the DLQ instead of delivering to consumers:

publish("events", payload="time-sensitive", ttl_ms=5000)
→ If not consumed within 5s, routes to DLQ with reason "message TTL expired"

Topic Compaction

For compacted topics, only the latest message per key is retained:

publish("state", key="user-1", payload="v1")
publish("state", key="user-1", payload="v2")
publish("state", key="user-2", payload="v1")
→ Compacted state: {"user-1": "v2", "user-2": "v1"}

Wildcard Subscriptions

MQTT-style topic patterns:

  • * matches exactly one level: sensors.* matches sensors.temp but not sensors.temp.room1
  • # matches zero or more levels: events.# matches events, events.user, events.user.login

Dead Letter Queues

When a WASM transform fails, the original message routes to the registered DLQ topic with an envelope containing:

  • Original payload
  • Source topic
  • Failure reason
  • Message ID
  • Retry count

Protocol Support

STOMP 1.2 (Port 61613)

Full STOMP 1.2 implementation with username/password authentication. Compatible with any STOMP client (ActiveMQ clients, Spring Messaging, etc.).

import stomp
conn = stomp.Connection([('localhost', 61613)])
conn.connect('admin', 'secret', wait=True)
conn.subscribe('/topic/orders', id=1)
conn.send('/topic/orders', '{"order":"123"}')

Kafka Wire Protocol (Port 9092)

Native Kafka producer/consumer compatibility. Existing Kafka applications can point to Pulse without code changes.

MQTT v5 (Port 1883)

Full MQTT v5 support for IoT workloads — QoS levels, retained messages, topic aliases, and shared subscriptions.

HTTP REST API (Port 8082)

JSON-based publish/subscribe with SSE and WebSocket real-time delivery.

OPFS Browser Queue

Client-side JavaScript SDK using Origin Private File System for offline message queuing with automatic sync on reconnection.


Storage & Durability

Write-Ahead Log (WAL)

Every published message is appended to the WAL before acknowledgment. The WAL provides:

  • Crash recovery — replays unprocessed messages on restart
  • Segment rotation — closed segments can be offloaded to cold storage
  • Sequential I/O — optimized for throughput

Tiered Storage Offloading

Configure S3-compatible cold storage for WAL segment archival:

export PRANOR_PULSE_S3_ENDPOINT=http://vault:9000
export PRANOR_PULSE_S3_BUCKET=pulse-archive
export PRANOR_PULSE_S3_TOKEN=auth-token

When a WAL segment rotates, it's automatically uploaded to the configured S3 bucket.

Offset Persistence

Consumer group offsets are stored in-memory with WAL backing. Consumers can:

  • Commit offsets explicitly via API
  • Replay from any historical offset
  • Seek to a timestamp-based position

Security

Standalone Mode (API Token)

HTTP endpoints require:

Authorization: Bearer secret-token

STOMP connections authenticate with username/password.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem, the full middleware chain activates:

  1. OTel Tracing — every request gets a span
  2. Rate Limiting — per-client request throttling
  3. CORS — cross-origin handling
  4. Max Body Size — 10MB limit
  5. JWT Auth — validates Bearer tokens
  6. Tenant Isolation — topic namespacing (tenant:topic)

Multi-Tenant Isolation

Topics are automatically namespaced with tenant ID. Tenant A cannot see or publish to Tenant B's topics:

Tenant "acme" publishes to "orders" → stored as "acme:orders"
Tenant "acme" listing topics → only sees topics prefixed "acme:"

TLS Encryption

Enable TLS on both STOMP and HTTP listeners:

export TLS_CERT_FILE=/certs/pulse.crt
export TLS_KEY_FILE=/certs/pulse.key

Observability

Prometheus Metrics

MetricTypeDescription
pranor_pulse_messages_published_totalCounterTotal messages published
pranor_pulse_wasm_executions_totalCounterTotal WASM transform runs
pranor_pulse_wasm_errors_totalCounterWASM execution failures
pranor_pulse_wasm_duration_nsHistogramWASM transform latency
pranor_pulse_topics_countGaugeActive topic count
pranor_pulse_subscribers_countGaugeConnected subscriber count
pranor_pulse_dlq_messages_totalCounterMessages routed to DLQ

OpenTelemetry Tracing

Every publish operation generates an OTel span with:

  • messaging.system: pranor-pulse
  • messaging.destination: topic name
  • messaging.payload_len: payload size
  • Child spans for WASM transforms and DLQ routing

Real-time Stats WebSocket

Connect to /api/v1/stats/ws for streaming broker stats (1-second updates).

Embedded Web UI

Access /ui/ on the HTTP port for a management dashboard showing topics, subscribers, DLQ state, and real-time throughput graphs.

Grafana Dashboard

Import the bundled grafana_dashboard.json for a pre-built Pulse monitoring dashboard.


Client Libraries & SDKs

Go

import "github.com/vyuvaraj/pranor/pulse/sdks/go"

client := pulse.NewClient("http://localhost:8082", "secret-token")

// Publish
err := client.Publish("orders.created", `{"order_id":"abc"}`, pulse.WithPriority(5))

// Subscribe
ch, err := client.Subscribe("orders.created")
for msg := range ch {
    fmt.Println("Received:", msg)
}

Python (STOMP)

import stomp

class MyListener(stomp.ConnectionListener):
    def on_message(self, frame):
        print(f"Received: {frame.body}")

conn = stomp.Connection([('localhost', 61613)])
conn.set_listener('', MyListener())
conn.connect('admin', 'secret', wait=True)
conn.subscribe('/topic/orders.created', id=1, ack='auto')
conn.send('/topic/orders.created', '{"order_id":"abc-123"}')

TypeScript (WebSocket)

const ws = new WebSocket('ws://localhost:8082/ws/subscribe/orders.created');
ws.onmessage = (event) => {
  const order = JSON.parse(event.data);
  console.log('New order:', order);
};

cURL

# Publish
curl -X POST http://localhost:8082/api/v1/publish \
  -H "Authorization: Bearer secret-token" \
  -H "Content-Type: application/json" \
  -d '{"topic":"orders.created","payload":"{\"order_id\":\"abc\"}"}'

# List topics
curl http://localhost:8082/api/v1/topics \
  -H "Authorization: Bearer secret-token"

# Register WASM transform
curl -X POST http://localhost:8082/api/v1/topics/orders.created/transform \
  -H "Authorization: Bearer secret-token" \
  --data-binary @enrich.wasm

# Replay from offset
curl -X POST http://localhost:8082/api/v1/replay \
  -H "Authorization: Bearer secret-token" \
  -d '{"topic":"orders.created","start_offset":0,"group_name":"replay-group"}'

Pranor CLI

pranor pulse publish --topic orders.created --payload '{"id":"abc"}'
pranor pulse subscribe --topic orders.created
pranor pulse topics list
pranor pulse dlq list --topic orders.created
pranor pulse dlq requeue --topic orders.created --message-id dlq-123
pranor pulse replay --topic orders.created --offset 0 --group analytics

Enterprise Edition

FeatureOSSEE
STOMP / Kafka / MQTT protocols
WAL persistence & recovery
WASM transforms
Dead letter queues
Consumer groups & partitions
Priority queues & delayed messages
Message deduplication
Schema validation
Tiered S3 storage offload
WebSocket & SSE subscriptions
Topic compaction
OPFS browser queue
Raft consensus replication
Multi-region MirrorMaker sync
Hardware KMS/HSM payload encryption
Schema registry breaking change guard
Federated cross-cluster topic routing
Advanced DLQ AI triage & auto-remediation

Operational Runbook

Messages not being delivered

  1. Check /api/v1/topics to confirm the topic exists and has subscribers
  2. Verify the publisher is authenticated and targeting the correct tenant namespace
  3. Check for backpressure — if queue is full, publishes return 503
  4. Review WASM transform logs — transform failures route to DLQ silently
  5. Check dedup — same message_id within 5 minutes is dropped

DLQ filling up

  1. Check /api/v1/topics/{topic}/dlq/summary for failure pattern clusters
  2. Review the WASM transform for bugs — most DLQ entries come from transform errors
  3. Use /api/v1/topics/{topic}/dlq/triage for AI-suggested remediation
  4. Fix the transform, then requeue messages via /api/v1/topics/{topic}/dlq/requeue

High publish latency

  1. Check pranor_pulse_wasm_duration_ns — slow transforms add latency
  2. Review backpressure limit — increase PRANOR_PULSE_BACKPRESSURE_LIMIT if queue is healthy
  3. Check WAL disk I/O — WAL append is synchronous
  4. Verify S3 offloader isn't blocking rotation (network issues to cold storage)

Consumer group rebalancing

  1. Check subscriber count on the topic — new/removed consumers trigger rebalance
  2. Verify consumer heartbeats are active
  3. Review offset commits — stale offsets cause replay on rejoin

WAL recovery after crash

On restart, Pulse automatically:

  1. Opens the WAL file
  2. Recovers all non-expired entries
  3. Re-publishes them through the broker engine
  4. Resumes normal operation

No manual intervention required.

Tiered storage not offloading

  1. Verify S3 endpoint connectivity: curl $PRANOR_PULSE_S3_ENDPOINT/healthz
  2. Check S3 credentials and bucket existence
  3. WAL segments only offload on rotation — ensure enough write volume to trigger rotation
  4. Check broker logs for offloader errors

Versioning & Compatibility

  • HTTP API is versioned at /api/v1/
  • Legacy /api/ paths continue to work
  • STOMP protocol follows STOMP 1.2 specification
  • Kafka wire protocol maintains compatibility with Kafka 2.x+ clients
  • MQTT follows MQTT v5.0 specification
  • WAL format is forward-compatible within major versions

Pranor Vault — S3-Compatible Object Storage

Version: 2.0.0
Module Path: github.com/vyuvaraj/pranor/vault
Default Ports: 9000 (S3 API), 9001 (Admin Console)
License: AGPL-3.0 (OSS) / Enterprise License (EE with Multi-Region Replication, CoW Branching, Envelope Encryption)


Overview

Pranor Vault is a production-grade S3-compatible object storage engine with embedded vector search, time-travel versioning, erasure coding, bucket branching, WASM transform pipelines, tiered cold storage, and a full admin console. It implements the AWS S3 API specification enabling drop-in compatibility with existing S3 clients, SDKs, and tools.

Pranor Vault can run as:

  • A standalone daemon (pranor-vaultd) with zero external dependencies
  • An integrated module within the Pranor ecosystem with mTLS, RBAC, OTel tracing, and Console visibility
  • A Kubernetes-native store via CSI driver and Helm charts
  • A distributed cluster with Raft consensus, consistent hashing, and erasure coding

Table of Contents


Key Features

FeatureDescription
Full S3 APIGET, PUT, DELETE, HEAD, ListBuckets, ListObjects, Multipart Upload, S3 Select.
Vector SearchEmbedded HNSW index for semantic similarity search over stored objects.
Time-Travel VersioningAccess any historical version of an object — full version history with delete markers.
Erasure CodingReed-Solomon data/parity sharding across cluster nodes for fault tolerance.
Bucket BranchingCopy-on-Write (CoW) branch terabyte buckets instantly for sandbox development.
WASM PipelinesTransform objects in-flight using WebAssembly modules (resize, transcode, redact).
Tiered Cold StorageAutomatic lifecycle rules sweeping objects to cold storage tier.
Object Locking (WORM)Immutable object retention for compliance — legal hold and governance modes.
Bucket LifecycleConfigurable expiration and transition rules per bucket.
S3 SelectQuery object content with SQL (CSV, JSON, Parquet).
Event NotificationsWebhook and STOMP-based notifications on object create/delete events.
Batch OperationsBulk copy, delete, and tag operations across large object sets.
Object TaggingKey-value metadata tags on objects for classification and lifecycle filtering.
Geo-PlacementPer-bucket geographic data residency placement policies.
FederationCross-cluster bucket routing via pattern-based federation rules.
Rate LimitingPer-tenant token-bucket rate limiting with Retry-After headers.
SQL Metadata QueryQuery bucket metadata using SQL syntax.
Conversational QueryNatural language "ask" interface for semantic object discovery.
CSI DriverKubernetes Container Storage Interface for pod-mounted object storage.
Helm ChartsProduction Helm charts for Kubernetes deployment.
Access Audit LoggingStructured access logs stored in system-access-logs bucket.
Console Web UIBuilt-in admin console for bucket management and monitoring.
Static Site HostingServe any bucket as a static website with MIME detection and index fallback.

Architecture

graph TD
    subgraph API ["S3-Compatible API Layer"]
        S3["S3 REST API :9000"]
        Admin["Admin API :9001"]
        Console["Web Console /ui/"]
    end

    subgraph Auth ["Auth and RBAC"]
        SigV4["AWS Signature V4 Verification"]
        RBAC["Policy-Based Access Control"]
        RateLimit["Per-Tenant Rate Limiter"]
    end

    subgraph Engine ["Object Processing Engine"]
        S3Ops["S3 Operations Engine"]
        Vector["Vector Search HNSW Index"]
        WASMPipe["WASM Transform Pipeline"]
        Federation["Federation Router"]
    end

    subgraph Cluster ["Distributed Cluster Layer"]
        Raft["Raft Consensus Leader Election"]
        HashRing["Consistent Hash Ring Placement"]
        Erasure["Reed-Solomon Erasure Coding"]
        CRR["Cross-Region Replication"]
    end

    subgraph Storage ["Persistence Layer"]
        LocalStore["Content-Addressed Local Store"]
        Versioning["Version Metadata Engine"]
        ColdTier["S3 Cold Storage Tier"]
        WAL["Write-Ahead Log"]
    end

    S3 --> SigV4
    Admin --> SigV4
    Console --> SigV4
    SigV4 --> RBAC
    RBAC --> RateLimit
    RateLimit --> S3Ops
    RateLimit --> Vector
    RateLimit --> WASMPipe
    S3Ops --> Raft
    Raft --> HashRing
    HashRing --> Erasure
    Erasure --> LocalStore
    LocalStore --> Versioning
    LocalStore -.-> ColdTier
    Versioning --> WAL
    Federation -.-> CRR

Object Lifecycle Sequence Flow

sequenceDiagram
    autonumber
    participant Client as S3 Client
    participant Gate as S3 API Gateway
    participant Auth as SigV4 Auth Layer
    participant Engine as S3 Operations Engine
    participant Cluster as Cluster Placement
    participant Store as Storage Engine
    participant Notify as Event Notifier

    Client->>Gate: PUT /bucket/key (Object Upload)
    Gate->>Auth: Verify AWS Signature V4
    Auth-->>Gate: Authenticated (Access Key + Policy)
    Gate->>Engine: Process PutObject Request
    Engine->>Cluster: Determine Placement via Hash Ring
    Cluster->>Store: Write Object Data + Version Metadata
    Store-->>Cluster: Write Committed (ETag Generated)
    Cluster-->>Engine: Placement Confirmed
    Engine->>Notify: Emit s3:ObjectCreated Event
    Notify-->>Engine: Webhook Dispatched
    Engine-->>Gate: 200 OK (ETag, VersionId)
    Gate-->>Client: HTTP 200 with ETag Header

Ecosystem Cross-Module Integration

Pranor Vault serves as the primary data persistence layer across the Pranor platform:

  • Pranor Pulse: Receives closed WAL segments offloaded to S3 buckets for cold archive retention. Vault also emits object event notifications to Pulse topics.
  • Pranor Auth: Validates JWT tokens and enforces RBAC bucket policies. OIDC and LDAP integration for enterprise environments.
  • Pranor Trace: Every S3 operation generates an OTel span with trace context propagation across cluster nodes.
  • Pranor Console: Provides bucket management dashboard, storage capacity monitoring, and object browsing UI.
  • Pranor Hub: Uses Vault as the backing store for package artifacts (tarballs, WASM modules, metadata).
  • Pranor Secret: Fetches encryption keys for server-side object encryption (SSE-KMS mode).

Installation & Deployment

Binary

cd pranor/vault
CGO_ENABLED=0 go build -o pranor-vaultd ./cmd/pranor-vaultd
CGO_ENABLED=0 go build -o pranor-vault ./cmd/pranor-vault
./pranor-vaultd -port :9000 -admin-port :9001

Docker

docker run -p 9000:9000 -p 9001:9001 -v vault-data:/data \
  ghcr.io/vyuvaraj/pranor-vault:latest

Docker Compose

services:
  vault:
    image: ghcr.io/vyuvaraj/pranor-vault:latest
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - vault-data:/data
    environment:
      - AWS_ACCESS_KEY_ID=minioadmin
      - AWS_SECRET_ACCESS_KEY=minioadmin
volumes:
  vault-data:

Kubernetes (Helm)

helm install pranor-vault ./deploy/helm \
  --set storage.size=100Gi \
  --set replication.factor=3 \
  --set erasure.enabled=true

CSI Driver

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: pranor-vault-csi
provisioner: vault.csi.pranor.io
parameters:
  bucket: my-app-data
  endpoint: http://pranor-vault:9000

As Part of Pranor Ecosystem

When running under the Pranor platform, Vault integrates automatically with Auth (JWT/mTLS), Secret (encryption keys), Trace (OTel spans), Pulse (event notifications), and Console (dashboard visibility).


Configuration

JSON Config (config.json)

{
  "addr": ":9000",
  "admin_addr": ":9001",
  "data_dir": "./data",
  "enable_web_admin": true,
  "default_buckets": ["default-bucket"]
}

Environment Variables

VariableDefaultDescription
AWS_ACCESS_KEY_IDminioadminS3 access key for authentication
AWS_SECRET_ACCESS_KEYminioadminS3 secret key for authentication
PORT:9000S3 API listening port
ADMIN_PORT:9001Admin console listening port
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL
PRANOR_VAULT_DATA_DIR./dataStorage data directory

CLI Flags

FlagDefaultDescription
-port:9000S3 API listening port
-admin-port:9001Admin console listening port
-configconfig.jsonPath to configuration file
-versionShow version and exit

API Reference

S3-Compatible API (Port 9000)

Pranor Vault implements the AWS S3 REST API. All standard S3 clients work without modification.

Authentication: AWS Signature V4 (compatible with aws-cli, boto3, MinIO client).


GET / — List Buckets

<?xml version="1.0" encoding="UTF-8"?>
<ListAllMyBucketsResult>
  <Owner>
    <ID>pranor-vault-owner</ID>
    <DisplayName>Pranor Vault Admin</DisplayName>
  </Owner>
  <Buckets>
    <Bucket>
      <Name>my-bucket</Name>
      <CreationDate>2026-01-15T10:00:00Z</CreationDate>
    </Bucket>
  </Buckets>
</ListAllMyBucketsResult>

PUT /{bucket} — Create Bucket

aws s3 mb s3://my-bucket --endpoint-url http://localhost:9000

DELETE /{bucket} — Delete Bucket

aws s3 rb s3://my-bucket --endpoint-url http://localhost:9000

GET /{bucket} — List Objects

Query parameters: prefix, delimiter, max-keys, continuation-token

aws s3 ls s3://my-bucket/ --endpoint-url http://localhost:9000

PUT /{bucket}/{key} — Put Object

aws s3 cp ./file.txt s3://my-bucket/path/file.txt --endpoint-url http://localhost:9000

Response includes ETag and optional x-amz-version-id.


GET /{bucket}/{key} — Get Object

aws s3 cp s3://my-bucket/path/file.txt ./file.txt --endpoint-url http://localhost:9000

Query param ?versionId= retrieves a specific historical version.


DELETE /{bucket}/{key} — Delete Object

Creates a delete marker (versioned) or permanently removes (unversioned).


HEAD /{bucket}/{key} — Head Object

Returns metadata without body (Content-Type, Content-Length, ETag, version headers).


Multipart Upload

For large objects (>5MB recommended):

# Initiate
POST /{bucket}/{key}?uploads

# Upload parts
PUT /{bucket}/{key}?uploadId={id}&partNumber={n}

# Complete
POST /{bucket}/{key}?uploadId={id}

# Abort
DELETE /{bucket}/{key}?uploadId={id}

POST /{bucket}/{key}?select — S3 Select

Query object contents with SQL:

{
  "Expression": "SELECT s.name, s.age FROM S3Object s WHERE s.age > 30",
  "InputSerialization": {"JSON": {"Type": "LINES"}},
  "OutputSerialization": {"JSON": {}}
}

PUT /{bucket}?versioning — Enable Versioning

<VersioningConfiguration>
  <Status>Enabled</Status>
</VersioningConfiguration>

GET /{bucket}?versions — List Object Versions

Returns all versions including delete markers for time-travel access.


PUT /{bucket}/{key}?lock — Object Lock (WORM)

Enable immutable retention on an object.


PUT /{bucket}/{key}?tagging — Object Tagging

<Tagging>
  <TagSet>
    <Tag><Key>environment</Key><Value>production</Value></Tag>
  </TagSet>
</Tagging>

PUT /{bucket}?lifecycle — Bucket Lifecycle Rules

Configure expiration and tier transitions:

<LifecycleConfiguration>
  <Rule>
    <ID>expire-old-logs</ID>
    <Status>Enabled</Status>
    <Expiration><Days>90</Days></Expiration>
    <Filter><Prefix>logs/</Prefix></Filter>
  </Rule>
</LifecycleConfiguration>

PUT /{bucket}?cold-tier — Configure Cold Tier

Set up tiered storage for infrequently accessed objects.

POST /{bucket}?cold-tier&sweep — Run Cold Sweep

Manually trigger cold storage sweep for a bucket.


PUT /{bucket}?notification — Event Notifications

{
  "bucket": "uploads",
  "events": ["s3:ObjectCreated:*", "s3:ObjectRemoved:*"],
  "webhook": "https://myapp.com/hook"
}

PUT /{bucket}?triggers — Bucket Triggers

Configure WASM triggers that execute on object events.


PUT /{bucket}?geo-placement — Geo-Placement Policy

Set geographic data residency requirements per bucket.


POST /{bucket}?pipeline — WASM Pipeline

Execute a WASM transform pipeline on objects in a bucket.


POST /{bucket}/{key}?transform&target-key={output} — WASM Transform

Transform a single object using a registered WASM module.


POST /{bucket}?delete — Batch Delete

Delete multiple objects in a single request:

<Delete>
  <Object><Key>file1.txt</Key></Object>
  <Object><Key>file2.txt</Key></Object>
</Delete>

GET /{bucket}?ask={query} — Conversational Query

Natural language semantic search over bucket contents:

GET /my-bucket?ask=find+all+invoices+from+2024

GET /{bucket}?sql={query} — SQL Metadata Query

Query bucket metadata using SQL syntax.


Admin API (Port 9001)

GET /api/v1/health

{
  "status": "UP",
  "version": "2.0.0",
  "uptime_sec": 3600.5,
  "bucket_count": 5,
  "daemon": "pranor-vaultd"
}

GET /api/v1/buckets

List all bucket names.

["default-bucket", "uploads", "archive"]

POST /api/v1/buckets

Create a bucket.

{"name": "new-bucket"}

POST /api/v1/events/subscribe

Subscribe to bucket event webhooks.

{
  "bucket": "uploads",
  "events": ["s3:ObjectCreated:*"],
  "webhook": "https://myapp.com/hook"
}

GET /ui/

Built-in web console for bucket management, object browsing, and monitoring.


GET /metrics

Prometheus-compatible metrics endpoint.


POST /admin/backup/restore

Trigger a backup restore operation.

POST /admin/federation

Register a federation routing rule.

POST /admin/batch

Create a batch operations job (bulk copy, delete, tag).

GET /admin/batch/

Check batch job status.


POST /console/login

Authenticate to the web console.

POST /console/logout

End console session.

GET /console/session

Validate current console session.


S3 Compatibility

Supported Operations

OperationStatusNotes
ListBucketsFull support
CreateBucketFull support
DeleteBucketMust be empty
HeadBucketFull support
ListObjects (v1/v2)Prefix, delimiter, pagination
PutObjectWith ETag, versioning
GetObjectRange requests, version selection
DeleteObjectDelete markers for versioned buckets
HeadObjectFull metadata
CopyObjectCross-bucket copy
Multipart UploadInitiate, Upload Part, Complete, Abort
Object VersioningEnable/Suspend, list versions
Object TaggingPut, Get, Delete tags
Object Lock (WORM)Governance and compliance modes
Bucket LifecycleExpiration, transitions
S3 SelectSQL on JSON/CSV/Parquet
Batch DeleteMulti-object delete
Bucket NotificationsWebhook + STOMP
Pre-signed URLsStandard AWS signature

Compatible Clients

  • AWS CLIaws s3 --endpoint-url http://localhost:9000
  • boto3 (Python) — set endpoint_url parameter
  • MinIO Client (mc) — mc alias set vault http://localhost:9000 minioadmin minioadmin
  • Go AWS SDK — custom endpoint configuration
  • s3cmd — configure with Vault endpoint
  • rclone — S3-compatible provider

Storage Engine

Local Storage (Default)

Content-addressed object storage on the local filesystem. Objects are stored in a PebbleDB-backed engine with:

  • B-tree indexed metadata
  • Content-addressable deduplication
  • Atomic write guarantees
  • Crash-safe recovery

Erasure Coding

Reed-Solomon erasure coding distributes data across cluster nodes:

Default: 2 data shards + 1 parity shard

Any 2 of 3 shards can reconstruct the original object. Configured via:

NewGateway(store, auth, raftNode, clusterMgr, replicationFactor, erasureEnabled, dataShards, parityShards)

Consistent Hash Ring

Objects are placed on cluster nodes using a consistent hash ring. The ring determines:

  • Which nodes own a given object (bucket/key hash)
  • Replication targets (next N nodes on ring)
  • Request routing (proxy to owner if not local)

Raft Consensus

Leader election and log replication for strong consistency of bucket-level operations (create, delete, versioning config).

Time-Travel Versioning

When versioning is enabled, every PUT creates a new version. Previous versions remain accessible by versionId:

PUT /bucket/key → version v1
PUT /bucket/key → version v2 (v1 still accessible)
DELETE /bucket/key → delete marker (v1, v2 still accessible)
GET /bucket/key?versionId=v1 → returns original content

Cold Storage Tiering

Lifecycle rules automatically move infrequently accessed objects to a cold storage tier:

Hot tier (SSD/local) → 30 days → Cold tier (S3-compatible remote)

Security

AWS Signature V4 Authentication

Standard S3 authentication using access key / secret key pairs:

export AWS_ACCESS_KEY_ID=minioadmin
export AWS_SECRET_ACCESS_KEY=minioadmin

RBAC Authorization

Role-based access control with per-bucket and per-action policies. Evaluated after authentication.

Rate Limiting

Per-tenant token-bucket rate limiting:

X-Pranor-Vault-Namespace: tenant-a
→ Rate limited independently per tenant
→ 429 Too Many Requests with Retry-After header on exhaustion

Object Lock (WORM)

Immutable object retention for regulatory compliance:

  • Governance mode — privileged users can override
  • Compliance mode — no one can delete until retention expires
  • Legal hold — indefinite immutability flag

Access Audit Logging

Every S3 operation is logged to the system-access-logs bucket:

{
  "request_id": "trace-id-abc",
  "timestamp": "2026-01-15T10:00:00Z",
  "requester": "admin",
  "bucket": "uploads",
  "key": "data/file.csv",
  "operation": "GET",
  "source_ip": "10.0.1.5:54321",
  "status": 200
}

TLS / mTLS

Configure TLS for the S3 API endpoint. In ecosystem mode, mTLS is available for service-to-service communication.

Console Authentication

The web admin console has its own session-based login separate from S3 credentials.


Observability

Prometheus Metrics

MetricTypeDescription
pranor_vault_http_requests_totalCounterTotal S3 API requests (method, path, status)
pranor_vault_request_duration_secondsHistogramRequest latency distribution
pranor_vault_inflight_requestsGaugeCurrently processing requests
pranor_vault_objects_totalGaugeTotal stored objects
pranor_vault_storage_bytesGaugeTotal storage consumed

OpenTelemetry Tracing

Every S3 operation generates an OTel span with:

  • http.method, http.route, http.status_code
  • Trace ID propagation via traceparent header
  • Child spans for cluster operations, erasure coding, WASM transforms

Structured JSON Logging

All requests are logged with structured fields:

{
  "level": "INFO",
  "msg": "Request completed",
  "method": "PUT",
  "path": "/uploads/file.txt",
  "status": 200,
  "duration": "12.3ms",
  "trace_id": "abc123"
}

Web Console Dashboard

Access /ui/ on the admin port for real-time monitoring:

  • Bucket list with object counts
  • Upload/download throughput
  • Cluster node health
  • Storage capacity utilization

Client Libraries & CLI

AWS CLI

# Configure
aws configure
# Access Key: minioadmin
# Secret Key: minioadmin
# Region: us-east-1

# Create bucket
aws s3 mb s3://my-bucket --endpoint-url http://localhost:9000

# Upload
aws s3 cp ./data.csv s3://my-bucket/data/file.csv --endpoint-url http://localhost:9000

# Download
aws s3 cp s3://my-bucket/data/file.csv ./local.csv --endpoint-url http://localhost:9000

# List
aws s3 ls s3://my-bucket/ --endpoint-url http://localhost:9000

# Delete
aws s3 rm s3://my-bucket/data/file.csv --endpoint-url http://localhost:9000

# Sync directory
aws s3 sync ./local-dir s3://my-bucket/backup/ --endpoint-url http://localhost:9000

MinIO Client (mc)

mc alias set vault http://localhost:9000 minioadmin minioadmin
mc mb vault/my-bucket
mc cp ./file.txt vault/my-bucket/
mc ls vault/my-bucket/
mc cat vault/my-bucket/file.txt

Python (boto3)

import boto3

s3 = boto3.client('s3',
    endpoint_url='http://localhost:9000',
    aws_access_key_id='minioadmin',
    aws_secret_access_key='minioadmin'
)

# Create bucket
s3.create_bucket(Bucket='my-bucket')

# Upload
s3.put_object(Bucket='my-bucket', Key='data/file.json', Body=b'{"hello":"world"}')

# Download
response = s3.get_object(Bucket='my-bucket', Key='data/file.json')
content = response['Body'].read()

# List objects
response = s3.list_objects_v2(Bucket='my-bucket', Prefix='data/')
for obj in response.get('Contents', []):
    print(obj['Key'], obj['Size'])

# Vector search
response = s3.select_object_content(
    Bucket='my-bucket',
    Key='embeddings.jsonl',
    Expression="SELECT * FROM S3Object WHERE similarity > 0.8",
    ExpressionType='SQL',
    InputSerialization={'JSON': {'Type': 'LINES'}},
    OutputSerialization={'JSON': {}}
)

Go

import (
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

cfg, _ := config.LoadDefaultConfig(context.TODO(),
    config.WithEndpointResolver(aws.EndpointResolverFunc(
        func(service, region string) (aws.Endpoint, error) {
            return aws.Endpoint{URL: "http://localhost:9000"}, nil
        },
    )),
)

client := s3.NewFromConfig(cfg)
_, err := client.PutObject(context.TODO(), &s3.PutObjectInput{
    Bucket: aws.String("my-bucket"),
    Key:    aws.String("data/file.txt"),
    Body:   strings.NewReader("hello world"),
})

Pranor CLI

pranor vault buckets list
pranor vault buckets create my-bucket
pranor vault upload ./file.txt my-bucket/path/file.txt
pranor vault download my-bucket/path/file.txt ./local.txt
pranor vault ls my-bucket/path/
pranor vault bench --bucket test-bucket --objects 10000
pranor vault import --source s3://existing/data --target local-bucket
pranor vault serve-static --bucket my-site --port 3000

cURL (Direct S3 API)

# List buckets (requires proper AWS Sig V4 — simplified with mc or aws-cli)
curl http://localhost:9000/ \
  -H "Authorization: AWS4-HMAC-SHA256 ..."

# Health check (no auth required)
curl http://localhost:9000/healthz

Enterprise Edition

FeatureOSSEE
Full S3 API
Local storage engine
Object versioning & time-travel
Multipart upload
Object tagging
Bucket lifecycle rules
S3 Select (SQL queries)
WASM transform pipelines
Event notifications (webhook/STOMP)
Batch operations
Rate limiting
Prometheus metrics & OTel tracing
Console Web UI
CSI driver & Helm charts
Vector search (HNSW)
Federation routing
Static site hosting
Immutable object access audit trail
Active-active multi-region replication
Copy-on-Write (CoW) bucket branching
Sovereign client envelope encryption
Erasure coding cluster
Raft consensus replication
Geo-placement data residency

Operational Runbook

Object not found (404)

  1. Verify bucket exists: aws s3 ls --endpoint-url http://localhost:9000
  2. Check if object was deleted — list versions: GET /bucket?versions
  3. If versioned, retrieve by version ID: GET /bucket/key?versionId=v1
  4. Check federation rules — object may be on a remote cluster

Upload failing (403 Access Denied)

  1. Verify credentials: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
  2. Check RBAC policy allows the operation on this bucket
  3. Verify AWS Signature V4 is correctly computed (clock skew can cause failures)
  4. Check rate limiting — 429 means tenant budget exhausted

Cluster node offline

  1. Check /metrics for cluster health indicators
  2. Erasure coding tolerates parityShards node failures — data remains accessible
  3. The consistent hash ring automatically routes to surviving owners
  4. New writes target remaining healthy nodes
  5. When the node recovers, rebalancing syncs missed data

High latency on large objects

  1. Use multipart upload for objects > 5MB
  2. Check erasure coding overhead — encoding adds CPU time
  3. Verify cold tier sweep isn't running (blocks I/O during sweep)
  4. Review OTel traces for bottleneck identification

Storage capacity approaching limit

  1. Review lifecycle rules — ensure expiration is configured
  2. Run cold tier sweep: POST /bucket?cold-tier&sweep
  3. Check for orphaned multipart uploads: list and abort incomplete uploads
  4. Review object versioning — old versions consume space

Bucket deletion failing

  1. Bucket must be empty before deletion
  2. Use batch delete to remove all objects first
  3. Check for object lock (WORM) — locked objects cannot be deleted
  4. Verify no active multipart uploads on the bucket

Federation routing not working

  1. Check registered federation rules: GET /admin/federation
  2. Verify remote cluster is reachable from this node
  3. Pattern matching is prefix-based — verify bucket name matches rule
  4. Check auth credentials for cross-cluster communication

Console login issues

  1. Console auth is separate from S3 credentials
  2. Check session cookie validity
  3. Verify admin port (9001) is accessible
  4. Review console session endpoint: GET /console/session

Versioning & Compatibility

  • S3 API follows AWS S3 specification (2006-03-01 namespace)
  • Admin API is versioned at /api/v1/
  • Storage format is forward-compatible within major versions
  • Object data is portable — can be migrated via standard S3 tools
  • CSI driver follows CSI spec v1.x
  • Helm charts follow Helm 3 conventions

Pranor Chrono — Distributed Job Scheduler

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/chrono
Default Port: 8087
License: AGPL-3.0 (OSS) / Enterprise License (EE with smart scheduling & timezone DSL)


Overview

Pranor Chrono is the distributed, fault-tolerant job scheduling service for the Pranor ecosystem. It supports interval and cron scheduling, exactly-once semantics, DAG job chaining, Pranor cron-as-code declarations, persistent S3 job registries, leader election, retry policies with configurable backoff, and full OTel tracing.

Pranor Chrono can run as:

  • A standalone binary with single-node scheduling (no Redis required)
  • An integrated module within the Pranor ecosystem with distributed leader election, mTLS, and OTel tracing

Key Features

FeatureDescription
Interval & CronRun jobs at fixed intervals or standard 5-field cron patterns
Exactly-once semanticsRedis-based leader election ensures only one node fires each job
DAG Job ChainingMulti-step dependency graphs with topological sort execution
Cron-as-CodeDefine jobs in .pnr files with hot-reload on change
Retry PoliciesFixed, linear, or exponential backoff with jitter
Dead Letter QueueJobs exhausting retries are moved to DLQ for audit
S3 PersistenceJob registry and audit logs persisted to Pranor Vault S3
Leader ElectionRedis-based distributed lease ensures cluster-safe scheduling
OTel Tracingtraceparent headers propagated to all HTTP callbacks
Fan-out / Fan-inParallelize independent steps, synchronize at join points

Architecture

graph TD

    subgraph API ["🌐 Scheduler Control and Cron-as-Code"]
        CronAsCode["Pranor Language .pnr Watcher"]
        JobAPI["REST Scheduler API"]
    end

    subgraph SchedulerCore ["⚡ Distributed Timer and DAG Engine"]
        CronEvaluator["High-Precision Cron Evaluator"]
        LeaderLock["Pranor Lock Fencing Token Leader"]
        DAGRunner["DAG Topological Fan-Out and Join Engine"]
        HTTPDispatcher["HTTP Callback Dispatcher"]
    end

    subgraph History ["💾 Audit Trail and Vault Storage"]
        VaultS3["Pranor Vault S3 Job Registry and Audit Logs"]
        RetryEngine["Exponential Backoff Retry Engine"]
    end

    CronAsCode --> CronEvaluator
    JobAPI --> CronEvaluator
    CronEvaluator --> LeaderLock
    LeaderLock --> DAGRunner
    DAGRunner --> HTTPDispatcher
    HTTPDispatcher --> RetryEngine
    RetryEngine --> VaultS3

High-Precision Distributed Cron Trigger Sequence Flow

sequenceDiagram
    autonumber
    participant Chrono as Pranor Chrono Leader
    participant Lock as Pranor Lock Manager
    participant Service as Target Microservice
    participant Vault as Pranor Vault S3
    participant Trace as Pranor Trace

    Chrono->>Lock: Acquire Job Execution Lease (Key: "cron/cleanup-db")
    Lock-->>Chrono: Granted (Fencing Token = 2088)
    Note over Chrono: Evaluate Cron Expression & Trigger Sub-ms TimeWheel
    Chrono->>Service: POST /tasks/cleanup (Traceparent + Fencing Token)
    Service-->>Chrono: 200 OK (Task Completed in 140ms)
    Chrono->>Vault: Write Audit Execution Log (audit/cleanup-db_20260803.json)
    Chrono->>Trace: Emit OTel Span with Job Execution Metrics
    Chrono->>Lock: Release Job Lease (Token = 2088)

Ecosystem Cross-Module Integration

Pranor Chrono manages high-precision job scheduling across all platform services:

  • Pranor Lock: Uses exclusive fencing token leases to guarantee job callbacks execute on exactly one node during multi-replica deployments.
  • Pranor Vault: Persists serialized jobs.json configurations and append-only execution audit logs.
  • Pranor Flow: Triggers scheduled workflow sagas and periodic maintenance DAGs.
  • Pranor Trace: Emits OpenTelemetry trace spans with traceparent context headers for every dispatched cron job.

Installation & Deployment

Binary

cd pranor/chrono
go build -o pranor-chrono .
./pranor-chrono --addr :8087

Docker

docker run -p 8087:8087 ghcr.io/vyuvaraj/pranor-chrono:latest

With Redis Leader Election

./pranor-chrono --addr :8087 --redis-url redis://localhost:6379

As Part of Pranor Ecosystem

When running under the Pranor platform, Chrono integrates automatically with Lock (leader election), Vault (persistence), Trace (OTel spans), and Console (dashboard visibility).


Configuration

Environment Variables

VariableDefaultDescription
PORT8087HTTP listener port
REDIS_URLRedis URL for distributed leader election
REDIS_LOCK_KEYpranor-chrono:leader:lockRedis key for leader lease lock
REDIS_LEASE_DURATION15sLease duration for leader election
PRANOR_CHRONO_PRANOR_VAULT_URLPranor Vault URL for job persistence
PRANOR_CHRONO_PRANOR_VAULT_BUCKETpranor-chrono-jobsS3 bucket name for job registry
PRANOR_CHRONO_OTEL_ENDPOINTOpenTelemetry collector URL
PRANOR_CHRONO_PRANOR_FILES_DIRDirectory to watch for .pnr job definitions

YAML Config (chrono.yaml)

port: "8087"
redis_url: "redis://localhost:6379"
redis_lock_key: "pranor-chrono:leader:lock"
redis_lease_duration: "15s"
vault_url: "http://pranor-vault:7070"
vault_bucket: "pranor-chrono-jobs"
otel_endpoint: "http://pranor-trace:8090"
pnr_files_dir: "./jobs"

CLI Flags

FlagDefaultDescription
--addr:8087HTTP listening address
--redis-urlRedis URL for leader election
--redis-lock-keypranor-chrono:leader:lockRedis key for leader lease
--redis-lease-duration15sLeader lease duration

API Reference

Base URL: http://localhost:8087
API Version: /api/v1/ (recommended) or /api/ (legacy)

POST /api/v1/jobs

Create a scheduled job.

Request:

{
  "name": "health-check",
  "schedule": "30s",
  "callback_url": "http://myapp/health",
  "retry": {
    "max": 3,
    "backoff": "exponential"
  }
}

Response (201):

{
  "id": "job-abc-123",
  "name": "health-check",
  "schedule": "30s",
  "status": "active",
  "next_run": "2026-08-01T10:00:30Z"
}

GET /api/v1/jobs

List all jobs.

Response (200):

{
  "jobs": [
    {
      "id": "job-abc-123",
      "name": "health-check",
      "schedule": "30s",
      "status": "active",
      "last_run": "2026-08-01T10:00:00Z",
      "next_run": "2026-08-01T10:00:30Z"
    }
  ]
}

POST /api/v1/jobs/{id}/run

Trigger a job manually (ignores schedule).

Response (200):

{
  "status": "triggered",
  "execution_id": "exec-xyz-789"
}

POST /api/v1/dag

Define a DAG job chain.

Request:

{
  "name": "nightly-pipeline",
  "schedule": "0 2 * * *",
  "steps": [
    { "id": "extract", "callback_url": "http://etl/extract", "depends_on": [] },
    { "id": "transform", "callback_url": "http://etl/transform", "depends_on": ["extract"] },
    { "id": "load", "callback_url": "http://etl/load", "depends_on": ["transform"] }
  ]
}

Response (201):

{
  "id": "dag-001",
  "name": "nightly-pipeline",
  "status": "active",
  "step_count": 3
}

GET /api/v1/jobs/{id}/history

Execution history for a job.

Response (200):

{
  "executions": [
    {
      "id": "exec-001",
      "started_at": "2026-08-01T10:00:00Z",
      "duration_ms": 140,
      "status": "success",
      "http_status": 200
    }
  ]
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-chrono","version":"1.0.0"}

Security

Standalone Mode

In standalone mode, Pranor Chrono runs with single-node scheduling and no Redis dependency. No authentication is required.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem, the full middleware chain activates:

  1. OTel Tracing — every request gets a span
  2. Rate Limiting — per-client request throttling
  3. CORS — cross-origin request handling
  4. Max Body Size — 10MB request body limit
  5. JWT Auth — validates Bearer tokens against Pranor Auth
  6. Tenant Isolation — multi-tenant namespace enforcement

Job Callback Security

Job callbacks include:

  • traceparent header for distributed tracing
  • Fencing token from Pranor Lock leader lease
  • Optional bearer token for authenticated callbacks

Observability

Prometheus Metrics

MetricTypeDescription
pranor_chrono_jobs_activeGaugeCurrently registered active jobs
pranor_chrono_fires_totalCounterTotal job fires (labeled by job name, status)
pranor_chrono_execution_duration_msHistogramJob execution duration
pranor_chrono_retries_totalCounterTotal retry attempts
pranor_chrono_dlq_depthGaugeDead letter queue depth
pranor_chrono_leader_elections_totalCounterLeader election events

OpenTelemetry Tracing

Every job execution generates OTel spans:

  • chrono.schedule.evaluate — cron expression evaluation
  • chrono.job.dispatch — HTTP callback dispatch
  • chrono.job.retry — retry attempt
  • chrono.leader.acquire — leader lease acquisition

Logging

Structured JSON logs with fields: level, timestamp, trace_id, job_id, execution_id, status, duration_ms.


Enterprise Edition

FeatureOSSEE
Interval & cron scheduling
DAG job chaining
Leader election (Redis)
Retry policies
Cron-as-Code (.pnr)
S3 job persistence
OTel tracing
Smart scheduling (load-aware distribution)
Timezone-aware cron DSL
Multi-cluster job federation
AI-powered schedule optimization

Operational Runbook

Jobs not firing

  1. Check leader election — only the leader fires jobs. Verify Redis connectivity
  2. Review /api/v1/jobs to confirm job status is active
  3. Check pranor_chrono_leader_elections_total metric for frequent re-elections
  4. Verify callback URLs are reachable from the Chrono node
  5. Check REDIS_LEASE_DURATION isn't too short causing leader thrashing

DAG steps stuck in pending

  1. Check /api/v1/dag/{id} for step dependency resolution status
  2. Verify upstream step completed successfully (check execution history)
  3. Look for circular dependencies in step definitions
  4. Check if step callback URL is timing out

High retry rate

  1. Monitor pranor_chrono_retries_total metric by job name
  2. Check callback service health and response times
  3. Review backoff strategy — exponential with jitter prevents thundering herds
  4. Consider increasing timeout for slow callbacks
  5. Jobs exhausting retries move to DLQ — check DLQ depth

Leader election instability

  1. Monitor Redis connectivity and latency
  2. Check REDIS_LEASE_DURATION (default 15s) — too short causes flapping
  3. Verify clock synchronization between Chrono nodes
  4. Check network partitions between nodes and Redis

Pranor Auth — Identity & Access Management

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/auth
Default Port: 8098
License: AGPL-3.0 (OSS) / Enterprise License (EE with Adaptive MFA & Federation)


Overview

Pranor Auth is the centralized authentication, authorization, and identity management service for the Pranor ecosystem. It provides OAuth2/OIDC provider functionality, WebAuthn/FIDO2 passkey login, adaptive multi-factor authentication, JWT issuance with automatic key rotation, RBAC/ABAC policy enforcement, session management, and SCIM provisioning.

Pranor Auth can run as:

  • A standalone binary with local user store and JWT signing
  • An integrated module within the Pranor ecosystem with mTLS, OTel tracing, tenant isolation, and federated IdP support

Key Features

FeatureDescription
OAuth2/OIDC ProviderFull Authorization Code (PKCE), Client Credentials, Refresh Token flows with JWKS endpoint
WebAuthn/FIDO2 PasskeysHardware keys, biometric authenticators, cross-device synced passkeys
JWT Issuance & RotationRS256/ES256 signed tokens with automatic JWKS key rotation via KMS
Adaptive MFATOTP, SMS OTP, Email OTP, Magic Links with risk-based step-up challenges
RBAC/ABACHierarchical roles, granular permissions, tenant-scoped policy enforcement
Session ManagementSecure session tokens with rotation, device tracking, and bulk invalidation
Social LoginOAuth2 social provider integration (Google, GitHub, etc.)
Credential Stuffing DetectionReal-time detection of credential stuffing attacks
SCIM ProvisioningSCIM v2 user lifecycle management for enterprise directory sync
SPIFFE/SPIRE ExchangeWorkload identity attestation via short-lived x509 SVID certificates

Architecture

graph TD

    subgraph Clients ["🌐 Auth Ceremony Clients"]
        PasskeyClient["WebAuthn FIDO2 Passkey"]
        MFAClient["TOTP / SMS / Email OTP"]
        OIDCClient["OAuth2 / OIDC Client (PKCE)"]
    end

    subgraph Core ["⚡ Core Identity Engine"]
        SessionMgr["Session Manager and Rotation Engine"]
        AdaptiveMFA["Adaptive Risk-Based Step-Up MFA"]
        JWTProvider["JWT / OIDC Issuer (RS256 / JWKS)"]
        RBACEngine["Granular RBAC / ABAC Policy Engine"]
        SPIFFEExchange["SPIFFE/SPIRE SVID Token Exchanger"]
    end

    subgraph IdentityStores ["💾 Enterprise Identity Provider Federation"]
        FederatedIdP["IdP Mapper (Okta / Azure AD SAML)"]
        UserStore["User Credential Store"]
    end

    PasskeyClient --> SessionMgr
    MFAClient --> AdaptiveMFA
    OIDCClient --> JWTProvider
    SessionMgr --> UserStore
    AdaptiveMFA --> UserStore
    JWTProvider --> RBACEngine
    FederatedIdP --> SPIFFEExchange

Workload Identity Exchange & Authentication Sequence Flow

sequenceDiagram
    autonumber
    participant App as Client / Service Workload
    participant Gate as Pranor Gate Ingress
    participant Auth as Pranor Auth Engine
    participant IdP as Okta / Azure AD (SAML)
    participant SPIFFE as SPIFFE/SPIRE Issuer

    App->>Auth: POST /api/v1/auth/login (Passkey / OAuth2 PKCE)
    Auth->>IdP: Federated Identity Claim Exchange (SAML 2.0)
    IdP-->>Auth: SAML Assertion (User Roles & Group Claims)
    Auth->>SPIFFE: Issue Short-Lived x509 SVID Certificate
    SPIFFE-->>Auth: Signed SVID Workload Identity
    Auth-->>App: RS256 Signed JWT + SPIFFE SVID Certificate
    App->>Gate: Access API (JWT Header + SVID mTLS)
    Gate->>Auth: Introspect Token & Verify RBAC Claims
    Auth-->>Gate: Token Validated & Permissions Granted

Ecosystem Cross-Module Integration

Pranor Auth establishes zero-trust identity across all platform components:

  • Pranor Gate: Enforces route-level JWT signature checks, SAML attribute mapping, and SPIFFE/SPIRE workload authentication.
  • Pranor Secret: Uses authenticated user identities to authorize access to encrypted vault keys and environment secret maps.
  • Pranor Notify: Triggers multi-factor authentication (MFA) Email/SMS one-time passcodes during step-up login ceremonies.
  • Pranor Console: Managed via Auth RBAC roles, granting workspace administrators granular cluster control plane privileges.

Installation & Deployment

Binary

cd pranor/auth
go build -o pranor-auth .
./pranor-auth --port 8098

Docker

docker run -p 8098:8098 ghcr.io/vyuvaraj/pranor-auth:latest

As Part of Pranor Ecosystem

When running under the Pranor platform, Auth integrates automatically with Gate (JWT enforcement), Trace (OTel spans), Secret (key storage), and Console (dashboard visibility).


Configuration

Environment Variables

VariableDefaultDescription
PORT8098HTTP listener port
PRANOR_AUTH_JWT_ALGORITHMRS256JWT signing algorithm (RS256 or ES256)
PRANOR_AUTH_JWT_KEY_PATHPath to RSA/EC private key for JWT signing
PRANOR_AUTH_SESSION_SECRET32-byte secret for session token signing
PRANOR_AUTH_MFA_TOTP_ISSUERPranorTOTP issuer name shown in authenticator apps
PRANOR_AUTH_PRANOR_NOTIFY_URLPranor Notify URL for email/SMS OTP delivery
PRANOR_AUTH_OTEL_ENDPOINTOpenTelemetry collector URL
PRANOR_AUTH_KMS_ROTATION_INTERVAL24hKMS envelope key rotation interval

YAML Config (auth.yaml)

port: "8098"
jwt_algorithm: "RS256"
jwt_key_path: "/keys/auth-signing.pem"
session_secret: "32-byte-random-secret-here"
mfa_totp_issuer: "Pranor"
notify_url: "http://pranor-notify:8094"
otel_endpoint: "http://pranor-trace:8090"

CLI Flags

FlagDefaultDescription
--port8098HTTP listen port

API Reference

Base URL: http://localhost:8098
API Version: /api/v1/ (recommended) or /api/ (legacy)

POST /api/auth/register

Register a new user.

Request:

{
  "username": "alice",
  "password": "secure-password-123",
  "email": "alice@example.com"
}

Response (201):

{
  "status": "success",
  "user_id": "usr-abc-123",
  "message": "User registered successfully"
}

POST /api/auth/login

Authenticate a user and receive a JWT.

Request:

{
  "username": "alice",
  "password": "secure-password-123"
}

Response (200):

{
  "token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_at": "2026-08-01T11:00:00Z",
  "user_id": "usr-abc-123"
}

POST /api/auth/passkey/register/challenge

Begin WebAuthn passkey registration ceremony.

Request:

{
  "user_id": "usr-abc-123"
}

Response (200):

{
  "challenge": "base64-encoded-challenge",
  "rp": { "name": "Pranor", "id": "pranor.net" },
  "user": { "id": "usr-abc-123", "name": "alice" }
}

POST /api/auth/passkey/login/challenge

Begin WebAuthn authentication ceremony.

Request:

{
  "username": "alice"
}

Response (200):

{
  "challenge": "base64-encoded-challenge",
  "allowCredentials": [{ "id": "cred-xyz", "type": "public-key" }]
}

POST /api/auth/mfa/setup

Set up MFA for a user (TOTP, SMS, or Email).

Request:

{
  "user_id": "usr-abc-123",
  "method": "totp"
}

Response (200):

{
  "secret": "JBSWY3DPEHPK3PXP",
  "qr_code_url": "otpauth://totp/Pranor:alice?secret=JBSWY3DPEHPK3PXP&issuer=Pranor"
}

POST /api/auth/mfa/step-up

Request adaptive MFA step-up based on risk signals.

Request:

{
  "user_id": "usr-abc-123",
  "context": {
    "ip": "203.0.113.42",
    "device_fingerprint": "fp-new-device",
    "action": "high-value-transfer"
  }
}

Response (200):

{
  "step_up_required": true,
  "risk_score": 78,
  "required_factors": ["totp"],
  "reason": "new_device_detected"
}

GET /.well-known/jwks.json

JSON Web Key Set for token verification.

Response (200):

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "key-2026-08",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

POST /api/auth/sessions/revoke

Invalidate all sessions for a user.

Request:

{
  "user_id": "usr-abc-123"
}

Response (200):

{
  "status": "success",
  "revoked_count": 3
}

GET /healthz

Liveness probe.

{"status":"ok"}

Security

Standalone Mode

In standalone mode, Pranor Auth uses a local user store with bcrypt-hashed passwords and issues self-signed JWTs. Configure PRANOR_AUTH_SESSION_SECRET for session signing.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem, the full middleware chain activates:

  1. OTel Tracing — every request gets a span
  2. Rate Limiting — per-client request throttling
  3. CORS — cross-origin request handling
  4. Max Body Size — 10MB request body limit
  5. JWT Auth — validates Bearer tokens
  6. Token Revocation — checks revocation list
  7. Tenant Isolation — multi-tenant namespace enforcement

mTLS / SPIFFE

Enable mutual TLS for service-to-service authentication with SPIFFE SVID certificates. Auth issues short-lived x509 workload identities for zero-trust inter-service communication.

KMS Key Rotation

Background KMS envelope key rotation runs on a configurable schedule (default: 24h). JWKS endpoints serve both current and previous keys during rollover for zero-downtime rotation.


Observability

Prometheus Metrics

MetricTypeDescription
pranor_auth_logins_totalCounterTotal login attempts (labeled by method, status)
pranor_auth_mfa_challenges_totalCounterMFA challenges issued
pranor_auth_token_issued_totalCounterJWTs issued
pranor_auth_sessions_activeGaugeCurrently active sessions
pranor_auth_stuffing_blocks_totalCounterCredential stuffing attacks blocked

OpenTelemetry Tracing

Every authentication flow generates OTel spans:

  • auth.login — full login ceremony
  • auth.mfa.verify — MFA verification step
  • auth.token.issue — JWT generation
  • auth.passkey.ceremony — WebAuthn challenge/response

Logging

Structured JSON logs with fields: level, timestamp, trace_id, user_id, action, ip, risk_score.


Enterprise Edition

FeatureOSSEE
Local user store & JWT issuance
TOTP/Email/SMS MFA
WebAuthn/FIDO2 Passkeys
Session management & revocation
RBAC roles & permissions
Social login (OAuth2 providers)
SCIM v2 provisioning
Adaptive Risk-Based MFA Step-Up
Device Fingerprinting & Trusted Device Registry
Per-Tenant OIDC Federation (Okta, Azure AD, Google)
SPIFFE/SPIRE Workload Identity Exchange
Credential Stuffing Detection Engine

Operational Runbook

Users cannot log in

  1. Check /healthz endpoint is returning 200
  2. Verify JWT signing key is accessible (PRANOR_AUTH_JWT_KEY_PATH)
  3. Check logs for auth.login span errors
  4. If MFA is failing, verify Pranor Notify connectivity for OTP delivery
  5. Check rate limiter isn't blocking legitimate traffic

JWT tokens rejected by downstream services

  1. Verify JWKS endpoint (/.well-known/jwks.json) is accessible from downstream services
  2. Check if key rotation occurred — downstream services may be caching stale keys
  3. Ensure clock skew between Auth and consumer services is < 30 seconds
  4. Check token hasn't been explicitly revoked via /api/auth/sessions/revoke

High credential stuffing alerts

  1. Monitor pranor_auth_stuffing_blocks_total metric
  2. Review blocked IPs in logs
  3. Consider enabling adaptive MFA step-up for all logins from flagged IPs
  4. Integrate with upstream WAF for IP-level blocking

KMS key rotation failures

  1. Check KMS connectivity and credentials
  2. Verify rotation interval configuration (PRANOR_AUTH_KMS_ROTATION_INTERVAL)
  3. Monitor logs for kms.rotation errors
  4. Manual key rotation: POST /api/auth/rotate-keys

Pranor Cache — Distributed Caching Engine

Version: 0.1.0
Module Path: github.com/vyuvaraj/pranor/cache
Default Port: 8086
License: AGPL-3.0 (OSS) / Enterprise License (EE with TLS offload & SIMD vector cache)


Overview

Pranor Cache is a distributed, high-performance caching service for the Pranor ecosystem. It exposes a low-latency REST API backed by pluggable engines (in-memory or Redis) with native support for OpenTelemetry context propagation, read-through/write-behind database synchronization, key pattern invalidation, bloom filter guards, multi-region replication, and a Redis wire protocol adapter.

Pranor Cache can run as:

  • A standalone binary with zero external dependencies (in-memory engine)
  • An integrated module within the Pranor ecosystem with mTLS, OTel tracing, and multi-region sync

Key Features

FeatureDescription
Pluggable EnginesSwap transparently between thread-safe in-memory storage and Redis/Valkey clusters
TTL EvictionAutomatic background time-based pruning of expired cache keys
Key Pattern InvalidationDelete matching keys via wildcards and prefix matching
Read-Through CacheMisses auto-load from backend database and populate the cache
Write-Behind CacheWrites asynchronously update the backend database for eventual consistency
Multi-Region ReplicationForward mutations to peer cache nodes for global consistency
Bloom Filter GuardProbabilistic filter prevents unnecessary backend lookups on non-existent keys
Redis Wire ProtocolRESP-compatible adapter allows existing Redis clients to connect directly
SIMD Vector SimilarityAVX-512 accelerated cosine-distance vector cache for LLM embedding lookups
Multi-Tenant PoolsIsolated memory pools per tenant to prevent noisy-neighbor issues
OTel InstrumentationHit/miss/latency metrics exported via OpenTelemetry tracing context

Architecture

graph TD

    subgraph Interface ["🌐 Cache Access Protocol"]
        API["REST Cache Engine API"]
        RedisProto["Redis Wire Protocol Adapter"]
    end

    subgraph Core ["⚡ Core Cache Engine"]
        MemGrid["Thread-Safe In-Memory Data Grid"]
        SIMDVector["SIMD AVX-512 Vector Similarity Cache"]
        BloomFilter["Probabilistic Bloom Filter Guard"]
        MultiTenantPool["Multi-Tenant Isolation Memory Pool"]
    end

    subgraph Persistence ["💾 Pluggable Backends and DB Sync"]
        RedisCluster["Redis / Valkey Cluster"]
        ReadThrough["Read-Through and Write-Behind DB Sync"]
        ActiveMirror["Active-Active Multi-Cluster Sync"]
    end

    API --> MemGrid
    RedisProto --> MemGrid
    MemGrid --> SIMDVector
    SIMDVector --> BloomFilter
    BloomFilter --> MultiTenantPool
    MultiTenantPool --> RedisCluster
    MultiTenantPool --> ReadThrough
    MultiTenantPool -.-> ActiveMirror

Read-Through & SIMD Vector Cache Sequence Flow

sequenceDiagram
    autonumber
    participant App as Microservice / LLM Client
    participant Cache as Pranor Cache Engine
    participant SIMD as SIMD AVX-512 Vector Engine
    participant DB as Backend Database / S3 Store

    App->>Cache: GET /api/cache/prompt-embedding (Cosine Distance < 0.05)
    Cache->>SIMD: Search In-Memory Vector Cache via SIMD AVX-512
    alt Cache Hit (Vector Distance Match)
        SIMD-->>Cache: Cached LLM Response Payload
        Cache-->>App: 200 OK (Instant Cache Hit <50µs)
    else Cache Miss
        SIMD-->>Cache: Cache Miss / Entry Expired
        Cache->>DB: Read-Through Fetch from Backend Storage
        DB-->>Cache: Fresh Payload Data
        Cache->>Cache: Asynchronously Populate Cache Entry & Update Bloom Filter
        Cache-->>App: 200 OK (Read-Through Response)
    end

Ecosystem Cross-Module Integration

Pranor Cache provides sub-millisecond data acceleration across all platform components:

  • Pranor Gate: Accelerates semantic prompt caching and API response caching for high-frequency ingress routes.
  • Pranor Vault: Caches HNSW vector graph nodes and S3 object metadata in memory for sub-5ms query performance.
  • Pranor Auth: Stores active user session tokens, OAuth2 authorization grants, and rate-limiting counters.
  • Pranor Trace: Exports cache hit/miss ratio metrics, memory pool allocations, and latency exemplars via OpenTelemetry.

Installation & Deployment

Binary

cd pranor/cache
go build -o pranor-cache .
./pranor-cache --port 8086

Docker

docker run -p 8086:8086 ghcr.io/vyuvaraj/pranor-cache:latest

With Redis Backend

./pranor-cache --port 8086 --backend redis --redis-url redis://localhost:6379

As Part of Pranor Ecosystem

When running under the Pranor platform, Cache integrates automatically with Auth (JWT/mTLS), Trace (OTel spans), and Console (dashboard visibility).


Configuration

Environment Variables

VariableDefaultDescription
PORT8086HTTP Server port
REDIS_URLRedis cluster URL. Uses in-memory engine if unset
PRANOR_CACHE_BACKEND_DBBackend database URL for read-through & write-behind sync
PRANOR_CACHE_PEERSComma-separated peer URLs for multi-region replication
PRANOR_CACHE_TLS_CERTPath to TLS certificate for HTTPS
PRANOR_CACHE_TLS_KEYPath to TLS private key
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL

YAML Config (cache.yaml)

port: "8086"
backend: "memory"          # "memory" or "redis"
redis_url: "redis://localhost:6379"
backend_db: ""             # read-through DB endpoint
peers: []                  # peer cache nodes for replication
tls_cert: ""
tls_key: ""

CLI Flags

FlagDefaultDescription
--port8086HTTP listen port
--backendmemoryCache backend: memory or redis
--redis-urlredis://localhost:6379Redis connection URL
--versionPrint version and exit

API Reference

Base URL: http://localhost:8086

POST /api/cache

Set a cache entry.

Request:

{
  "key": "user:101",
  "value": { "name": "Alice", "role": "admin" },
  "ttl": "5m"
}

Response (200):

{
  "status": "success",
  "key": "user:101"
}

GET /api/cache/

Get a cache entry.

Response (200):

{
  "key": "user:101",
  "value": { "name": "Alice", "role": "admin" }
}

Response (404):

{
  "status": "not_found",
  "key": "user:101"
}

DELETE /api/cache/

Delete a specific cache entry.

Response (200):

{
  "status": "deleted",
  "key": "user:101"
}

DELETE /api/cache?pattern=

Invalidate keys by pattern. If no pattern is provided, clears the entire cache.

Response (200):

{
  "status": "success",
  "invalidated": 42
}

GET /health

Health probe showing cache readiness and connection status.

Response (200):

{"status":"UP","service":"pranor-cache","version":"0.1.0","backend":"memory"}

Security

Standalone Mode

In standalone mode, Pranor Cache runs without authentication. Suitable for development and testing.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem (detected automatically), the full middleware chain activates:

  1. OTel Tracing — every request gets a span
  2. Rate Limiting — per-client request throttling
  3. CORS — cross-origin request handling
  4. Max Body Size — 10MB request body limit
  5. JWT Auth — validates Bearer tokens against Pranor Auth
  6. Tenant Isolation — multi-tenant namespace enforcement

TLS

Enable HTTPS with TLS certificates:

tls_cert: "/certs/cache.crt"
tls_key: "/certs/cache.key"

TLS offload is an Enterprise feature that uses optimized kernel-bypass SSL termination.


Observability

Prometheus Metrics

MetricTypeDescription
pranor_cache_hits_totalCounterCache hit count
pranor_cache_misses_totalCounterCache miss count
pranor_cache_keys_activeGaugeCurrently stored keys
pranor_cache_evictions_totalCounterKeys evicted by TTL
pranor_cache_read_through_totalCounterRead-through backend fetches
pranor_cache_replication_lag_msHistogramPeer replication latency

OpenTelemetry Tracing

Every cache operation generates OTel spans:

  • cache.get — read operation with hit/miss attribute
  • cache.set — write operation with TTL
  • cache.delete — deletion/invalidation
  • cache.read_through — backend fetch on miss

Logging

Structured JSON logs with fields: level, timestamp, trace_id, operation, key, hit, latency_us.


Enterprise Edition

FeatureOSSEE
In-memory cache engine
Redis/Valkey backend
TTL eviction
Key pattern invalidation
Read-through / Write-behind
Multi-region peer replication
Bloom filter guard
TLS offload (kernel-bypass SSL)
SIMD AVX-512 vector similarity cache
Multi-tenant memory pool isolation
Redis wire protocol adapter
Active-active multi-cluster sync

Operational Runbook

High cache miss rate

  1. Check /health endpoint for backend connectivity
  2. Verify TTLs aren't too short for workload patterns
  3. Review bloom filter effectiveness — false positive rate should be < 1%
  4. If using read-through, check backend DB latency via pranor_cache_read_through_total
  5. Consider increasing memory allocation for the in-memory engine

Replication lag between regions

  1. Monitor pranor_cache_replication_lag_ms histogram
  2. Check network connectivity to peer nodes (PRANOR_CACHE_PEERS)
  3. Verify peer URLs are reachable and responding to health checks
  4. Consider reducing write volume if replication can't keep up

Memory pressure / OOM

  1. Check pranor_cache_keys_active gauge for key count growth
  2. Review TTL policies — ensure all entries have finite TTLs
  3. Use pattern invalidation to bulk-remove stale namespaces
  4. If using multi-tenant pools, check per-tenant quotas

Redis backend connection failures

  1. Verify REDIS_URL is correct and Redis is reachable
  2. Check Redis cluster health (CLUSTER INFO)
  3. Pranor Cache falls back to in-memory in standalone mode
  4. Monitor reconnection attempts in structured logs

Pranor Mesh — Intelligent Service Mesh

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/mesh
Default Port: 8089
License: AGPL-3.0 (OSS) / Enterprise License (EE with WireGuard & mTLS Attestation)


Overview

Pranor Mesh is the intelligent service mesh for the Pranor ecosystem, providing latency-aware Power-of-Two-Choices (P2C) load balancing, distributed rate limiting, live topology telemetry, circuit breaking, mTLS, and chaos fault injection — all without requiring sidecar proxies.

Pranor Mesh can run as:

  • A standalone binary providing load balancing and service discovery
  • An integrated module within the Pranor ecosystem with distributed rate limiting via Cache, topology push to Console, and mTLS via Auth

Key Features

FeatureDescription
P2C Load BalancingPower-of-Two-Choices with latency-aware backend selection
Locality PreferencePrefer backends in the same AZ before spilling to remote nodes
Distributed Rate LimitingGlobal rate limits via Pranor Cache token buckets
Circuit BreakingAutomatic circuit open/half-open/closed state per backend
Live TopologyReal-time service dependency graph pushed to Console
Chaos Fault InjectionLatency injection, error simulation, network partition
Health-aware RoutingUnhealthy backends excluded with exponential recovery probing
mTLSMutual TLS for encrypted service-to-service communication
Traffic Flow VisualizationEdges annotated with RPS, error rate, and p99 latency
MicrosegmentationeBPF L4/L7 policy enforcement between services

Architecture

graph TD

    subgraph ServiceTraffic ["🌐 Encrypted Service Connectivity"]
        ClientService["Client Service Pod / Host"]
        mTLSSidecar["mTLS Auto-Inject Sidecar Proxy"]
        WireGuardMesh["WireGuard Private Network Mesh Overlay"]
    end

    subgraph MeshCore ["⚡ Zero-Trust Control and Microsegmentation"]
        P2CRouter["Power-of-Two-Choices (P2C) Load Balancer"]
        Microseg["eBPF Layer 4/7 Microsegmentation Policy Engine"]
        BFTRaft["Byzantine Fault Tolerant (BFT) Raft Control Plane"]
        ChaosEngine["In-Situ Chaos Experiment Injector"]
    end

    subgraph PlatformSync ["💾 Ecosystem Sync and Observability"]
        CacheLimit["Pranor Cache Shared Token Bucket"]
        ConsoleTopology["Pranor Console Live Topology Emitter"]
    end

    ClientService --> mTLSSidecar
    mTLSSidecar --> WireGuardMesh
    WireGuardMesh --> P2CRouter
    P2CRouter --> Microseg
    Microseg --> BFTRaft
    BFTRaft --> ChaosEngine
    ChaosEngine --> CacheLimit
    ChaosEngine -.-> ConsoleTopology

Power-of-Two-Choices (P2C) Routing & Microsegmentation Sequence Flow

sequenceDiagram
    autonumber
    participant Caller as Caller Service A
    participant Mesh as Pranor Mesh Control Plane
    participant eBPF as eBPF Microsegmentation Guard
    participant Backend as Selected Target Service B

    Caller->>Mesh: POST /api/v1/route (Service B, Locality Zone: "us-east-1a")
    Mesh->>eBPF: Validate L4/L7 Zero-Trust Microsegmentation Policy
    eBPF-->>Mesh: Traffic Authorized (Policy Passed)
    Mesh->>Mesh: Pick 2 Random Candidate Endpoints & Evaluate p99 Latency (P2C)
    Mesh->>Backend: Route Mutual TLS Request (WireGuard Overlay)
    Backend-->>Mesh: Response Payload + Health Status
    Mesh-->>Caller: Selected Endpoint Response (Sub-millisecond Latency)

Ecosystem Cross-Module Integration

Pranor Mesh manages secure inter-service communication across all ecosystem components:

  • Pranor Gate: Acts as the external ingress target for Mesh WireGuard overlay tunnels and mTLS sidecar proxies.
  • Pranor Cache: Shares token bucket rate-limiting counters across all cluster Mesh nodes for global traffic shaping.
  • Pranor Auth: Enforces SPIFFE/SPIRE workload identities and mutual TLS (mTLS) certificate verification per service route.
  • Pranor Console: Renders live service topology dependency graphs, real-time latency heatmaps, and active chaos experiment controls.

Installation & Deployment

Binary

cd pranor/mesh
go build -o pranor-mesh .
./pranor-mesh --port 8089

Docker

docker run -p 8089:8089 ghcr.io/vyuvaraj/pranor-mesh:latest

With Distributed Rate Limiting

docker run -p 8089:8089 \
  -e PRANOR_MESH_PRANOR_CACHE_URL=http://pranor-cache:8086 \
  -e PRANOR_MESH_PRANOR_CONSOLE_WS_URL=ws://pranor-console:8083/ws/topology \
  ghcr.io/vyuvaraj/pranor-mesh:latest

As Part of Pranor Ecosystem

When running under the Pranor platform, Mesh integrates automatically with Cache (rate limiting), Console (topology), Auth (mTLS), and Trace (OTel spans).


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_MESH_PORT8089HTTP listener port
PRANOR_MESH_PRANOR_CACHE_URLPranor Cache URL for distributed rate limit state
PRANOR_MESH_PRANOR_CONSOLE_WS_URLPranor Console WebSocket URL for topology push
PRANOR_MESH_LOCALITY_ZONEAvailability zone for locality-preference routing
PRANOR_MESH_OTEL_ENDPOINTOpenTelemetry collector URL

YAML Config (mesh.yaml)

port: "8089"
cache_url: "http://pranor-cache:8086"
console_ws_url: "ws://pranor-console:8083/ws/topology"
locality_zone: "us-east-1a"
otel_endpoint: "http://pranor-trace:8090"
circuit_breaker:
  failure_threshold: 5
  recovery_timeout: "30s"

CLI Flags

FlagDefaultDescription
--port8089HTTP listen port

API Reference

Base URL: http://localhost:8089

POST /api/v1/services

Register a service endpoint.

Request:

{
  "name": "orders-api",
  "endpoints": ["http://orders-1:3000", "http://orders-2:3000", "http://orders-3:3000"],
  "locality_zone": "us-east-1a"
}

Response (201):

{
  "status": "registered",
  "service": "orders-api",
  "endpoint_count": 3
}

POST /api/v1/route

Route a request via P2C selection.

Request:

{
  "service": "orders-api",
  "caller_zone": "us-east-1a"
}

Response (200):

{
  "selected_endpoint": "http://orders-2:3000",
  "latency_p99_ms": 12,
  "locality_match": true
}

POST /api/v1/ratelimit/policy

Set rate limit policy for a service.

Request:

{
  "service": "orders-api",
  "requests_per_second": 500,
  "burst": 1000
}

Response (200):

{
  "status": "applied",
  "service": "orders-api"
}

POST /api/v1/chaos/inject

Inject a chaos fault.

Request:

{
  "target_service": "payments-api",
  "fault_type": "latency",
  "latency_ms": 200,
  "percentage": 30,
  "duration": "5m"
}

Response (201):

{
  "id": "exp-123",
  "status": "active",
  "expires_at": "2026-08-01T10:05:00Z"
}

GET /api/v1/topology

Current topology graph snapshot.

Response (200):

{
  "services": ["orders-api", "payments-api", "inventory-api"],
  "edges": [
    { "from": "orders-api", "to": "payments-api", "rps": 120, "p99_ms": 45 }
  ]
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-mesh","version":"1.0.0"}

Security

Standalone Mode

In standalone mode, Mesh provides unauthenticated load balancing and service discovery.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. mTLS — mutual TLS for all service-to-service traffic
  2. SPIFFE/SPIRE — workload identity attestation per service
  3. eBPF Microsegmentation — L4/L7 zero-trust policy enforcement
  4. WireGuard Overlay — encrypted mesh network between nodes
  5. Token-bucket rate limiting — global enforcement via Pranor Cache

Circuit Breaking

Mesh implements circuit breaking per backend:

  • Closed: Normal traffic flow
  • Open: All requests fast-fail (after failure threshold)
  • Half-Open: Limited probe requests to test recovery

Observability

Prometheus Metrics

MetricTypeDescription
pranor_mesh_routing_decisions_totalCounterTotal P2C routing decisions
pranor_mesh_rate_limit_hits_totalCounterRate limit rejections
pranor_mesh_chaos_faults_activeGaugeActive chaos experiments
pranor_mesh_circuit_breaker_stateGaugeCircuit state per backend (0=closed, 1=open, 2=half-open)
pranor_mesh_backend_latency_msHistogramBackend response latency
pranor_mesh_topology_edgesGaugeActive service-to-service edges

OpenTelemetry Tracing

Mesh emits spans for:

  • mesh.route — P2C routing decision
  • mesh.ratelimit.check — rate limit evaluation
  • mesh.chaos.inject — chaos fault injection
  • mesh.circuit.trip — circuit breaker state change

Logging

Structured JSON logs with fields: level, timestamp, trace_id, service, endpoint, latency_ms, action.


Enterprise Edition

FeatureOSSEE
P2C load balancing
Service registration & discovery
Locality-aware routing
Distributed rate limiting (via Cache)
Chaos fault injection
Circuit breaking
Live topology telemetry
WireGuard kernel tunnel mesh
SPIFFE/SPIRE mTLS workload attestation
eBPF L4/L7 microsegmentation
BFT Raft control plane

Operational Runbook

High tail latency on routed requests

  1. Check pranor_mesh_backend_latency_ms histogram for p99 spikes
  2. Review which backends are being selected — P2C should prefer faster ones
  3. Verify locality zone configuration matches actual deployment topology
  4. Check if circuit breaker is tripping on slow backends
  5. Look for active chaos experiments affecting the target service

Rate limiting blocking legitimate traffic

  1. Check pranor_mesh_rate_limit_hits_total for unexpected rejections
  2. Review rate limit policy: GET /api/v1/ratelimit/policy
  3. Verify Pranor Cache connectivity — rate limit state is shared globally
  4. Increase burst allowance if traffic is legitimately spiky

Topology graph missing services

  1. Verify services are registered: GET /api/v1/services
  2. Check Console WebSocket connectivity (PRANOR_MESH_PRANOR_CONSOLE_WS_URL)
  3. Ensure services are actually making calls through Mesh (not direct)
  4. Review Mesh logs for registration errors

Chaos experiment not auto-expiring

  1. Check experiment status: GET /api/v1/chaos/active
  2. Verify system clock is accurate (expiry is time-based)
  3. Manually abort: POST /api/v1/chaos/abort/{id}
  4. Review duration configuration in the inject request

Pranor Trace — Distributed Tracing & Continuous Profiling

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/trace
Default Port: 8090
License: AGPL-3.0 (OSS) / Enterprise License (EE with AI Anomaly Detection & SIEM Streaming)


Overview

Pranor Trace is the distributed tracing and continuous profiling service for the Pranor ecosystem. It ingests OTLP-format traces, assembles waterfall hierarchies, provides SLO burn rate alerting, delivers eBPF-powered flamegraph profiling with automatic OTel correlation, critical path analysis, and anomaly detection.

Pranor Trace can run as:

  • A standalone binary accepting OTLP/HTTP traces with in-memory storage
  • An integrated module within the Pranor ecosystem with eBPF profiling, Console integration, and SIEM streaming

Key Features

FeatureDescription
OTLP IngestionStandard /v1/traces endpoint compatible with all OpenTelemetry SDKs
Span ReassemblyGroups spans by trace ID, links parent-child relationships
Waterfall UIFull span waterfall with nested children and duration bars
SLO Burn RateDual-window burn rate alerting with error budget tracking
eBPF FlamegraphsKernel-level CPU/memory profiling without code instrumentation
Trace-to-FlamegraphCorrelate slow spans to flamegraph profiles
Critical Path AnalysisIdentify the longest-latency path across distributed traces
Prometheus ExemplarsOpenMetrics with trace exemplar links in histograms
Dependency MapAuto-discovered service call graph from trace data
Anomaly DetectionAI-powered latency anomaly baseline comparison

Architecture

graph TD

    subgraph Ingestion ["🌐 Telemetry Ingestion Layer"]
        OTLP["OTLP / gRPC / HTTP Collector"]
        eBPFProf["Kernel eBPF Continuous Profiler"]
    end

    subgraph Processing ["⚡ Span Reassembly and AI Engine"]
        Reassembly["Span Grouping and Trace ID Linker"]
        CriticalPath["Critical Path Evaluator"]
        AIAutoTune["Autonomous AI Anomaly Auto-Tuner"]
        SLOEngine["SLO Burn Rate Alerting Engine"]
    end

    subgraph Storage ["💾 In-Memory and SIEM Storage"]
        MemStore["In-Memory Evicting Trace Store"]
        SIEMStreamer["Encrypted SIEM Streamer"]
    end

    OTLP --> Reassembly
    eBPFProf --> Reassembly
    Reassembly --> CriticalPath
    CriticalPath --> AIAutoTune
    AIAutoTune --> SLOEngine
    SLOEngine --> MemStore
    MemStore -.-> SIEMStreamer

Telemetry Processing & Flamegraph Correlation Sequence Flow

sequenceDiagram
    autonumber
    participant SDK as Microservice OTLP SDK
    participant Trace as Pranor Trace Collector
    participant eBPF as Kernel eBPF Profiler
    participant AI as AI Anomaly Engine
    participant Console as Pranor Console UI

    SDK->>Trace: POST /v1/traces (Span Tree + TraceID: 0x9918)
    eBPF->>Trace: Push Kernel CPU Stack Samples
    Trace->>Trace: Group Spans by TraceID & Link Parent-Child Tree
    Trace->>AI: Evaluate Span Latency against Baseline
    alt Latency Anomaly Detected
        AI-->>Trace: Raise Burn Rate Alert & Identify Root-Cause Span
        Trace->>Console: Stream Correlated Flamegraph + Log Evidence
    else Standard Trace
        Trace-->>Console: Update Live Waterfall Graph & Dependency Map
    end

Ecosystem Cross-Module Integration

Pranor Trace serves as the central telemetry and observability hub across the Pranor ecosystem:

  • Pranor Gate: Ingests W3C traceparent headers, attributing gateway latency and AI prompt token costs to backend trace spans.
  • Pranor Flow: Captures individual workflow step execution spans, linking saga compensation steps to root trace IDs.
  • Pranor Console: Renders live interactive CPU flamegraphs, distributed service dependency graphs, and SLO burn rate dashboards.
  • Pranor Notify: Triggers incident notifications to PagerDuty or Slack when SLO burn rates exceed fast/slow window thresholds.

Installation & Deployment

Binary

cd pranor/trace
go build -o pranor-trace .
./pranor-trace --port 8090

Docker

docker run -p 8090:8090 ghcr.io/vyuvaraj/pranor-trace:latest

With eBPF Profiling

docker run -p 8090:8090 \
  --privileged \
  -e PRANOR_TRACE_EBPF_ENABLED=true \
  -e PRANOR_TRACE_MAX_TRACES=50000 \
  ghcr.io/vyuvaraj/pranor-trace:latest

As Part of Pranor Ecosystem

When running under the Pranor platform, Trace integrates automatically with all services via the PRANOR_OTLP_ENDPOINT env var. Console connects for waterfall rendering and flamegraph display.


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_TRACE_PORT8090HTTP listener port
PRANOR_TRACE_MAX_TRACES10000Max traces in memory before eviction
PRANOR_TRACE_EBPF_ENABLEDfalseEnable eBPF continuous profiling
PRANOR_TRACE_OTEL_EXPORTRe-export spans to another OTLP collector
PRANOR_TRACE_SLO_ALERT_WEBHOOKWebhook URL for SLO burn rate alerts

YAML Config (trace.yaml)

port: "8090"
max_traces: 50000
ebpf_enabled: true
otel_export: ""
slo_alert_webhook: "http://pranor-notify:8094/api/v1/send"

CLI Flags

FlagDefaultDescription
--port8090HTTP listen port

API Reference

Base URL: http://localhost:8090

POST /v1/traces

OTLP/HTTP trace ingestion (standard OpenTelemetry endpoint).

Request: Standard OTLP ExportTraceServiceRequest (protobuf or JSON).

Response (200):

{}

GET /api/v1/traces

List recent traces.

Query parameters: service, status, min_duration_ms, limit

Response (200):

{
  "traces": [
    {
      "trace_id": "abc123def456",
      "root_service": "orders-api",
      "root_operation": "POST /orders",
      "duration_ms": 234,
      "span_count": 8,
      "status": "ok",
      "started_at": "2026-08-01T10:00:00Z"
    }
  ]
}

GET /api/v1/traces/

Get full trace with span waterfall hierarchy.

Response (200):

{
  "trace_id": "abc123def456",
  "spans": [
    {
      "span_id": "span-001",
      "parent_span_id": null,
      "service": "orders-api",
      "operation": "POST /orders",
      "duration_ms": 234,
      "status": "ok",
      "children": [
        {
          "span_id": "span-002",
          "service": "payments-api",
          "operation": "charge",
          "duration_ms": 180
        }
      ]
    }
  ]
}

GET /api/v1/traces/{traceID}/critical-path

Critical path analysis for a trace.

Response (200):

{
  "trace_id": "abc123def456",
  "critical_path": [
    { "service": "orders-api", "operation": "POST /orders", "self_time_ms": 54 },
    { "service": "payments-api", "operation": "charge", "self_time_ms": 180 }
  ],
  "bottleneck": "payments-api"
}

POST /api/v1/slo

Define an SLO for a service.

Request:

{
  "service": "orders-api",
  "slo_name": "availability",
  "target_ratio": 0.999,
  "windows": [
    { "name": "fast", "duration": "1h", "burn_rate_threshold": 14.4 },
    { "name": "slow", "duration": "6h", "burn_rate_threshold": 6.0 }
  ]
}

Response (201):

{
  "status": "created",
  "slo_id": "slo-001"
}

GET /api/v1/slo/{service}/burn-rate

SLO burn rate for a service.

Response (200):

{
  "slo": "availability",
  "budget_remaining": 0.82,
  "burn_rate_1h": 2.1,
  "burn_rate_6h": 0.8,
  "alerting": false
}

GET /api/v1/flamegraph/

Latest eBPF flamegraph for a service.

Response (200): SVG or JSON flamegraph data.


GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-trace","version":"1.0.0"}

Security

Standalone Mode

In standalone mode, Trace accepts OTLP spans without authentication. Suitable for development and internal networks.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. JWT Auth — management APIs require Bearer token
  2. OTel ingestion/v1/traces can be optionally auth-gated
  3. Tenant Isolation — traces scoped per tenant
  4. SIEM Streaming — encrypted export to external SIEM systems
  5. Data Retention — configurable max traces with oldest-first eviction

eBPF Security

eBPF profiling requires --privileged Docker flag or CAP_SYS_ADMIN + CAP_BPF capabilities. In production, use a dedicated profiling sidecar with minimal permissions.


Observability

Prometheus Metrics

MetricTypeDescription
pranor_trace_spans_ingested_totalCounterTotal spans received
pranor_trace_traces_storedGaugeTraces currently in memory
pranor_trace_slo_burn_rateGaugeCurrent burn rate per service/SLO
pranor_trace_slo_alerts_fired_totalCounterSLO alert triggers
pranor_trace_flamegraph_samples_totalCountereBPF stack samples collected
pranor_trace_evictions_totalCounterTraces evicted from memory

OpenTelemetry Self-Telemetry

Trace emits its own spans for:

  • trace.ingest — span ingestion pipeline
  • trace.reassemble — trace ID grouping
  • trace.slo.evaluate — burn rate calculation
  • trace.flamegraph.correlate — span-to-flamegraph correlation

Logging

Structured JSON logs with fields: level, timestamp, trace_id, service, operation, duration_ms, alert.


Enterprise Edition

FeatureOSSEE
OTLP/HTTP trace ingestion
Span reassembly & waterfall
SLO burn rate alerting
Critical path analysis
Service dependency map
Prometheus exemplars
In-memory evicting store
eBPF flamegraph profiling
AI anomaly detection auto-tuner
Encrypted SIEM streaming
Trace-to-flamegraph correlation
Multi-cluster trace federation

Operational Runbook

Traces being evicted too quickly

  1. Check pranor_trace_traces_stored gauge vs PRANOR_TRACE_MAX_TRACES
  2. Increase PRANOR_TRACE_MAX_TRACES or add more memory
  3. Consider exporting to external storage via PRANOR_TRACE_OTEL_EXPORT
  4. Review if unnecessary high-cardinality spans are being ingested

SLO alerts firing incorrectly

  1. Check pranor_trace_slo_burn_rate metric for the service
  2. Verify SLO definition — is the target ratio correct?
  3. Review burn rate window configuration (fast: 1h, slow: 6h)
  4. Check if a deployment or incident caused a legitimate spike
  5. Adjust thresholds if alerting is too sensitive

eBPF profiling not producing data

  1. Verify PRANOR_TRACE_EBPF_ENABLED=true
  2. Check container has --privileged or necessary capabilities
  3. Verify kernel version supports BPF (Linux 4.15+)
  4. Check pranor_trace_flamegraph_samples_total metric
  5. Review logs for BPF program load errors

High span ingestion latency

  1. Monitor span ingestion rate vs processing capacity
  2. Check pranor_trace_spans_ingested_total rate
  3. If store is full, eviction adds overhead — increase capacity
  4. Consider sampling at the SDK level to reduce volume
  5. Review if SIEM streaming is creating backpressure

v2.0 OTLP Span Schema (std/trace)

In v2.0, Pranor Trace defines a canonical span name hierarchy and mandatory attributes for all ecosystem modules.

Canonical Span Names

ConstantSpan NameModule
SpanAgentExecutionpranor.agent_execution
SpanGateInspectpranor.gate.inspectgate
SpanGraphContextpranor.graph.contextgraph
SpanGraphCachepranor.graph.cachegraph
SpanGraphSQLpranor.graph.sqlgraph
SpanDecisionEvaluatepranor.decision.evaluatedecision
SpanDecisionAuthpranor.decision.authdecision
SpanDecisionBudgetpranor.decision.budgetdecision
SpanDecisionRiskpranor.decision.riskdecision
SpanDecisionRulespranor.decision.rulesdecision
SpanDecisionLearnpranor.decision.learndecision
SpanFlowSagapranor.flow.sagaflow
SpanFlowSteppranor.flow.stepflow
SpanLearnPredictpranor.learn.predictlearn

Mandatory Span Attributes

AttributeKeyDescription
Agent IDpranor.agent_idExecuting agent identifier
User IDpranor.user_idAuthenticated user
Tenant IDpranor.tenant_idTenant/org isolation
Request IDpranor.request_idCorrelation ID across modules
Modulepranor.moduleEmitting module name
Outcomepranor.outcomeALLOW / DENY / APPROVE / TRANSFORM / ERROR

Fault Contract

  • Span emission is best-effort and non-blocking (fire-and-forget goroutine)
  • Failed writes log a warning to stderr and continue — never on the critical path
  • OSS: JSON lines to stderr via stdoutEmitter; EE: full OTLP export to Pranor Trace collector
  • Attribute values truncated to 256 bytes per TruncateAttr(v string) string

Pranor Console — Unified Management Dashboard

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/console
Default Port: 8083
License: AGPL-3.0 (OSS) / Enterprise License (EE with AI Co-Pilot & Chaos Panel)


Overview

Pranor Console is the unified, premium management dashboard and observability console for the Pranor ecosystem. It provides a single pane of glass for managing all Pranor components — Gate, Pulse, Vault, Mesh, Deploy, Trace, Flow, and more — with a glassmorphic, real-time UI designed for power users. It features global search, chaos engineering controls, incident management, eBPF flamegraphs, and WebSocket-driven live telemetry.

Pranor Console can run as:

  • A standalone binary serving the web UI with manual service URL configuration
  • An integrated module within the Pranor ecosystem with auto-discovery, mTLS, and federated telemetry

Key Features

FeatureDescription
Single Pane of GlassManage the entire Pranor stack from one premium glassmorphic UI
Global ⌘K SearchFuzzy search across all resources — services, routes, queues, buckets, workflows
API Gateway ManagementLive route audits, WASM hot-swap, circuit breaker status board
Queue InspectorTopic browser, DLQ replay, consumer group lag dashboard
Storage InspectorBucket browser, vector index namespaces, branch management
eBPF FlamegraphsLive CPU/memory profiling from the kernel layer
SLO Burn RateReal-time error budget dashboards with fast/slow windows
Chaos EngineeringDesign, trigger, and monitor chaos experiments
Service TopologyInteractive dependency map with live traffic flow edges
Incident ManagerAlert rules, triage, severity management, resolution tracking
Environment ProvisionerOne-click isolated environments and branch previews
SQL WorkbenchInteractive query editor with schema exploration

Architecture

graph TD

    subgraph UserInterface ["🌐 Glassmorphic Web and TUI Interface"]
        SPA["React / WASM Glassmorphic SPA"]
        TUI["Terminal TUI Control Plane"]
        WSClient["WebSocket Live Telemetry Stream"]
    end

    subgraph BackendCore ["⚡ Central Control Plane Backend"]
        SearchEngine["Global Ecosystem ⌘K Indexer"]
        ChaosControl["Chaos Experiment Orchestrator"]
        IncidentEngine["Incident Triage and Alert Engine"]
        AIAssistant["Autonomous AI Co-Pilot"]
    end

    subgraph ServiceIntegrations ["💾 Platform Services Monitoring Hub"]
        GateSync["Pranor Gate API Sync"]
        PulseSync["Pranor Pulse Queue and DLQ Sync"]
        VaultSync["Pranor Vault Bucket and Vector Sync"]
        TraceSync["Pranor Trace and eBPF Flamegraph Sync"]
    end

    SPA --> SearchEngine
    TUI --> SearchEngine
    WSClient --> SearchEngine
    SearchEngine --> ChaosControl
    SearchEngine --> IncidentEngine
    SearchEngine --> AIAssistant
    AIAssistant --> GateSync
    AIAssistant --> PulseSync
    AIAssistant --> VaultSync
    AIAssistant --> TraceSync

Real-Time WebSocket Telemetry Stream & Global Search Sequence Flow

sequenceDiagram
    autonumber
    participant Admin as Cluster Operator / Web UI
    participant Console as Pranor Console Backend
    participant Gate as Pranor Gate / Pulse / Vault
    participant Trace as Pranor Trace Engine
    participant AI as Autonomous AI Co-Pilot

    Admin->>Console: Open Console Dashboard & Trigger ⌘K Search ("vector-index-01")
    Console->>Console: Index & Match Cross-Module Resources in Memory
    Console-->>Admin: Display Instant Search Matches (<5ms)
    Console->>Gate: Subscribe to Live WebSocket Metrics Stream (/ws/feeds)
    Gate-->>Console: Stream Throughput, Latency & Error Telemetry
    Console->>Trace: Query High-Burn SLO Spans & eBPF Flamegraphs
    Trace-->>Console: Correlated Flamegraph + Span Waterfall
    Console->>AI: Analyze Cluster Anomaly & Suggest Auto-Remediation
    AI-->>Admin: Render Remediation Action Card in Glassmorphic Panel

Ecosystem Cross-Module Integration

Pranor Console provides single-pane-of-glass management for all platform components:

  • Pranor Gate: Inspects dynamic HTTP routes, hot-swaps WASM security modules, and monitors AI token costs.
  • Pranor Pulse: Browses topics, tracks consumer group partition lag, and performs 1-click DLQ message triage.
  • Pranor Vault: Visualizes HNSW vector graph indexes, browses S3 buckets, and manages CoW bucket branches.
  • Pranor Trace: Renders interactive eBPF CPU flamegraphs, distributed service dependency maps, and SLO burn rate dashboards.

Installation & Deployment

Binary

cd pranor/console
go build -o pranor-console .
./pranor-console --port 8083

Docker

docker run -p 8083:8083 ghcr.io/vyuvaraj/pranor-console:latest

With Service Discovery

docker run -p 8083:8083 \
  -e PRANOR_CONSOLE_PRANOR_GATE_URL=http://pranor-gate:8080 \
  -e PRANOR_CONSOLE_PRANOR_PULSE_URL=http://pranor-pulse:9090 \
  -e PRANOR_CONSOLE_PRANOR_VAULT_URL=http://pranor-vault:7070 \
  -e PRANOR_CONSOLE_PRANOR_TRACE_URL=http://pranor-trace:8090 \
  -e PRANOR_CONSOLE_PRANOR_MESH_URL=http://pranor-mesh:8089 \
  ghcr.io/vyuvaraj/pranor-console:latest

As Part of Pranor Ecosystem

When running under the Pranor platform, Console auto-discovers all services via Mesh and displays the full topology.


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_CONSOLE_PORT8083HTTP port
PRANOR_CONSOLE_PRANOR_GATE_URLPranor Gate backend URL
PRANOR_CONSOLE_PRANOR_PULSE_URLPranor Pulse backend URL
PRANOR_CONSOLE_PRANOR_VAULT_URLPranor Vault backend URL
PRANOR_CONSOLE_PRANOR_TRACE_URLPranor Trace OTLP URL
PRANOR_CONSOLE_PRANOR_MESH_URLPranor Mesh backend URL
PRANOR_CONSOLE_AUTH_TOKENStatic admin auth token
PRANOR_CONSOLE_THEMEdarkDefault theme (dark, light, glassmorphism)

YAML Config (console.yaml)

port: "8083"
gate_url: "http://pranor-gate:8080"
pulse_url: "http://pranor-pulse:9090"
vault_url: "http://pranor-vault:7070"
trace_url: "http://pranor-trace:8090"
mesh_url: "http://pranor-mesh:8089"
auth_token: "admin-secret-token"
theme: "dark"

CLI Flags

FlagDefaultDescription
--port8083HTTP listen port

API Reference

Base URL: http://localhost:8083

GET /api/v1/search?q=

Global resource search (⌘K).

Response (200):

{
  "results": [
    { "type": "service", "name": "orders-api", "module": "mesh", "url": "/mesh/services/orders-api" },
    { "type": "route", "name": "/api/orders", "module": "gate", "url": "/gate/routes/api-orders" }
  ],
  "took_ms": 3
}

GET /api/v1/topology/graph

Live service topology graph data.

Response (200):

{
  "nodes": [
    { "id": "orders-api", "type": "service", "status": "healthy" },
    { "id": "payments-api", "type": "service", "status": "degraded" }
  ],
  "edges": [
    { "from": "orders-api", "to": "payments-api", "rps": 120, "error_rate": 0.02, "p99_ms": 45 }
  ]
}

POST /api/v1/chaos/experiments

Create a chaos experiment.

Request:

{
  "name": "latency-spike-test",
  "target_service": "payments-api",
  "fault_type": "latency",
  "latency_ms": 500,
  "percentage": 25,
  "duration": "5m"
}

Response (201):

{
  "id": "exp-001",
  "status": "active",
  "blast_radius": ["orders-api", "checkout-api"],
  "expires_at": "2026-08-01T10:05:00Z"
}

POST /api/v1/incidents

Create an incident.

Request:

{
  "title": "High error rate on payments-api",
  "severity": "P2",
  "services": ["payments-api"],
  "description": "Error rate exceeded 5% SLO threshold"
}

Response (201):

{
  "id": "inc-001",
  "status": "open",
  "created_at": "2026-08-01T10:00:00Z"
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-console","version":"1.0.0"}

Security

Standalone Mode

Set PRANOR_CONSOLE_AUTH_TOKEN for basic token authentication. Clients authenticate via:

Authorization: Bearer admin-secret-token

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem, Console integrates with Pranor Auth for RBAC-based access control:

  1. JWT Auth — validates Bearer tokens against Pranor Auth
  2. Role-based dashboard access — admins see all panels; operators see limited views
  3. Audit logging — all management actions logged with user identity
  4. mTLS — service-to-service communication encrypted

CORS

Console serves the SPA from a configurable origin. CORS headers allow the frontend to call backend APIs cross-origin.


Observability

Prometheus Metrics

MetricTypeDescription
pranor_console_active_sessionsGaugeActive WebSocket connections
pranor_console_search_latency_msHistogram⌘K search response time
pranor_console_chaos_experiments_activeGaugeRunning chaos experiments
pranor_console_incidents_openGaugeOpen incidents
pranor_console_ws_messages_totalCounterWebSocket messages received

OpenTelemetry Tracing

Console emits spans for:

  • console.search — global search queries
  • console.chaos.inject — chaos experiment triggers
  • console.topology.refresh — topology graph rebuilds

Logging

Structured JSON logs with fields: level, timestamp, user_id, action, module, latency_ms.


Enterprise Edition

FeatureOSSEE
Unified dashboard UI
Global ⌘K search
Service topology graph
SLO burn rate dashboards
Incident management
Queue inspector (DLQ replay)
Chaos engineering panel
eBPF flamegraph profiling
AI Co-Pilot auto-remediation
Environment provisioner
Custom keyboard shortcuts & themes
Multi-cluster federation view

Operational Runbook

WebSocket connections dropping

  1. Check pranor_console_active_sessions gauge for sudden drops
  2. Verify network stability between Console and downstream services
  3. Check if rate limiting is affecting WebSocket upgrade requests
  4. Review nginx/load balancer timeout settings for WebSocket connections
  5. Ensure Connection: Upgrade headers are not being stripped

Global search returning stale results

  1. Console indexes resources on startup and via WebSocket feeds
  2. Force re-index by restarting Console or triggering topology refresh
  3. Check connectivity to all configured service URLs
  4. Verify Mesh is reporting accurate service catalog

Chaos experiment not propagating

  1. Verify Pranor Mesh connectivity (PRANOR_CONSOLE_PRANOR_MESH_URL)
  2. Check experiment status via GET /api/v1/chaos/experiments/{id}
  3. Confirm target service is registered in Mesh service catalog
  4. Review blast radius preview before re-triggering

Dashboard panels blank or loading

  1. Check browser console for WebSocket connection errors
  2. Verify backend service URLs are correct and accessible
  3. Check auth token validity if using static token auth
  4. Review CORS configuration if frontend is served from a different origin

Pranor Pool — Database Connection Proxy

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/pool
Default Port: 8097
License: AGPL-3.0 (OSS) / Enterprise License (EE with pgvector accelerator & multi-dialect)


Overview

Pranor Pool is an intelligent, observable database connection pool manager for the Pranor ecosystem. It provides read/write splitting, connection health validation, leak detection, query telemetry, prepared statement caching, pool saturation alerting, and multi-dialect support for PostgreSQL, MySQL, and SQLite.

Pranor Pool can run as:

  • A standalone binary providing connection pooling for any PostgreSQL/MySQL application
  • An integrated module within the Pranor ecosystem with OTel tracing, Console dashboards, and Lock-coordinated DDL migrations

Key Features

FeatureDescription
Read/Write SplitAuto-routes SELECTs to replicas, writes to primary
Replica WeightingConfigurable traffic distribution across replicas
Transaction PinningAll queries within a transaction pinned to primary
Replica Lag AwarenessSkip replicas exceeding configurable lag threshold
Pre-checkout ValidationPing + validation query before handing connections to callers
Leak DetectionAge-based and activity-based detection with goroutine stack traces
Query AnalyticsPer-query p50/p75/p90/p99 latency histograms
Slow Query LoggerQueries exceeding threshold logged with full context
Prepared Statement CachePer-connection cache with automatic invalidation on schema change
Saturation AlertingPool utilization and wait queue depth alerts to Console

Architecture

graph TD

    subgraph AppCallers ["🌐 Microservice Connection Request"]
        App["Application Microservice Caller"]
        PoolClient["Pranor Pool Go/Python/Java Client"]
    end

    subgraph PoolCore ["⚡ Core Connection Routing and Health Engine"]
        RWRouter["Read/Write Query Router"]
        HealthCheck["Pre-Checkout Validation Engine"]
        LeakDetector["Connection Leak and Goroutine Stack Tracker"]
        StmtCache["Per-Connection Prepared Statement Cache"]
        VectorOffload["PostgreSQL pgvector Accelerator"]
    end

    subgraph DBClusters ["💾 Heterogeneous Relational DB Tier"]
        PrimaryDB["Primary RDBMS"]
        ReplicaPool["Weighted Replica Pool"]
    end

    App --> PoolClient
    PoolClient --> RWRouter
    RWRouter --> HealthCheck
    HealthCheck --> LeakDetector
    LeakDetector --> StmtCache
    StmtCache --> VectorOffload
    VectorOffload --> PrimaryDB
    VectorOffload --> ReplicaPool

Connection Checkout, Read/Write Split & Leak Detection Sequence Flow

sequenceDiagram
    autonumber
    participant App as Application Microservice
    participant Pool as Pranor Pool Manager
    participant Leak as Goroutine Leak Tracker
    participant Stmt as Prepared Statement Cache
    participant DB as Target RDBMS (Primary / Replica)

    App->>Pool: Checkout Connection (Query: "SELECT * FROM users WHERE id = $1")
    Pool->>Pool: Inspect SQL Query Type (Read Query -> Route to Replica Pool)
    Pool->>Leak: Register Goroutine Stack & Start 30s Max-Hold Timer
    Pool->>Stmt: Lookup Cached Prepared Statement ("stmt_users_by_id")
    Stmt-->>Pool: Prepared Statement Handle Ready
    Pool->>DB: Execute Query on Replica DB Instance
    DB-->>Pool: Query Result Set Returned (p99 latency: 1.2ms)
    Pool->>Leak: Cancel Max-Hold Leak Timer & Return Connection to Pool
    Pool-->>App: Connection Released & Stats Updated

Ecosystem Cross-Module Integration

Pranor Pool provides intelligent database proxying across the Pranor ecosystem:

  • Pranor Lock: Coordinates zero-downtime online DDL schema migrations, holding exclusive fencing token leases during migrations.
  • Pranor Trace: Annotates SQL queries with OpenTelemetry spans, recording query normalization histograms and slow query stack traces.
  • Pranor Vault: Connects seamlessly to PostgreSQL pgvector instances, managing connection pools for S3 vector metadata storage.
  • Pranor Console: Displays real-time database connection saturation heatmaps, active wait-queue depth, and 1-click connection leak reclaims.

Installation & Deployment

Binary

cd pranor/pool
go build -o pranor-pool .
./pranor-pool --port 8097

Docker

docker run -p 8097:8097 ghcr.io/vyuvaraj/pranor-pool:latest

With OTel and Console

docker run -p 8097:8097 \
  -e PRANOR_POOL_OTEL_ENDPOINT=http://pranor-trace:8090 \
  -e PRANOR_POOL_PRANOR_CONSOLE_URL=http://pranor-console:8083 \
  ghcr.io/vyuvaraj/pranor-pool:latest

As Part of Pranor Ecosystem

When running under the Pranor platform, Pool integrates automatically with Lock (DDL coordination), Trace (query spans), and Console (saturation dashboards).


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_POOL_PORT8097HTTP listener port
PRANOR_POOL_OTEL_ENDPOINTOpenTelemetry collector URL
PRANOR_POOL_PRANOR_CONSOLE_URLPranor Console URL for saturation alerts
PRANOR_POOL_DEFAULT_MAX_CONN25Default max connections per pool
PRANOR_POOL_LEAK_CHECK_INTERVAL30sHow often to run leak detection sweep

YAML Config (pool.yaml)

port: "8097"
otel_endpoint: "http://pranor-trace:8090"
console_url: "http://pranor-console:8083"
default_max_connections: 25
leak_check_interval: "30s"
slow_query_threshold_ms: 100

CLI Flags

FlagDefaultDescription
--port8097HTTP listen port

API Reference

Base URL: http://localhost:8097

POST /api/v1/pools

Create a connection pool.

Request:

{
  "name": "orders-db",
  "primary": "postgres://user:pass@primary:5432/orders",
  "replicas": [
    { "dsn": "postgres://user:pass@replica1:5432/orders", "weight": 70 },
    { "dsn": "postgres://user:pass@replica2:5432/orders", "weight": 30 }
  ],
  "max_connections": 50,
  "min_idle": 5,
  "validation_query": "SELECT 1",
  "max_checkout_duration": "30s",
  "slow_query_threshold_ms": 100
}

Response (201):

{
  "status": "created",
  "name": "orders-db",
  "max_connections": 50
}

GET /api/v1/pools/{name}/stats

Pool stats — utilization, wait queue, active connections.

Response (200):

{
  "name": "orders-db",
  "total": 50,
  "active": 38,
  "idle": 12,
  "wait_queue": 2,
  "utilization_pct": 76
}

GET /api/v1/pools/{name}/leaks

List detected connection leaks.

Response (200):

{
  "leaks": [
    {
      "conn_id": "conn-42",
      "held_since": "2026-08-01T10:00:00Z",
      "duration_s": 45,
      "goroutine": "main.go:84",
      "stack_trace": "goroutine 42 [running]:\nmain.handleOrder(...)"
    }
  ]
}

POST /api/v1/pools/{name}/reclaim

Force-reclaim all leaked connections.

Response (200):

{
  "status": "reclaimed",
  "reclaimed_count": 3
}

GET /api/v1/pools/{name}/query-stats

Per-query latency histograms.

Response (200):

{
  "queries": [
    {
      "signature": "SELECT * FROM orders WHERE id = ?",
      "p50_ms": 3,
      "p75_ms": 8,
      "p90_ms": 22,
      "p99_ms": 45,
      "count": 10234
    }
  ]
}

GET /api/v1/pools/{name}/slow-queries

Recent slow queries.

Response (200):

{
  "queries": [
    {
      "query": "SELECT * FROM orders JOIN items ON ...",
      "duration_ms": 340,
      "timestamp": "2026-08-01T10:01:30Z",
      "caller": "handlers.go:156"
    }
  ]
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-pool","version":"1.0.0"}

Security

Standalone Mode

In standalone mode, Pool provides unauthenticated connection pooling. DSN credentials are stored in memory only.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. JWT Auth — validates Bearer tokens for pool management API
  2. Tenant Isolation — pools scoped per tenant namespace
  3. OTel Tracing — every query generates a trace span
  4. Credential Injection — DSN passwords can be sourced from Pranor Secret

Connection Security

  • TLS to database — supports sslmode=require in PostgreSQL DSNs
  • Credential rotation — integrates with Pranor Secret for dynamic password rotation
  • No credential exposure — DSN passwords never exposed in API responses

Observability

Prometheus Metrics

MetricTypeDescription
pranor_pool_connections_activeGaugeCurrently checked-out connections
pranor_pool_connections_idleGaugeIdle connections in pool
pranor_pool_wait_queue_depthGaugeCallers waiting for a connection
pranor_pool_utilization_pctGaugePool utilization percentage
pranor_pool_query_duration_msHistogramQuery execution latency
pranor_pool_leaks_detected_totalCounterConnection leaks detected
pranor_pool_stmt_cache_hits_totalCounterPrepared statement cache hits
pranor_pool_slow_queries_totalCounterSlow queries logged

OpenTelemetry Tracing

Pool emits spans for:

  • pool.checkout — connection checkout with routing decision
  • pool.query — SQL query execution
  • pool.leak.detect — leak detection event
  • pool.health.validate — connection validation

Logging

Structured JSON logs with fields: level, timestamp, trace_id, pool, query_signature, duration_ms, connection_id.


Enterprise Edition

FeatureOSSEE
Connection pooling (PostgreSQL, MySQL, SQLite)
Read/write split routing
Replica weighting
Pre-checkout validation
Leak detection
Query analytics
Slow query logger
Prepared statement cache
Saturation alerting
PostgreSQL pgvector accelerator
Multi-dialect federation (cross-DB routing)
AI query optimization advisor
Connection pool sharding

Operational Runbook

Pool saturation (high utilization)

  1. Check /api/v1/pools/{name}/stats for utilization percentage
  2. Monitor pranor_pool_wait_queue_depth — if growing, pool is undersized
  3. Increase max_connections in pool configuration
  4. Check for connection leaks: GET /api/v1/pools/{name}/leaks
  5. Force reclaim leaks: POST /api/v1/pools/{name}/reclaim

Connection leaks accumulating

  1. Monitor pranor_pool_leaks_detected_total metric
  2. Review leak stack traces: GET /api/v1/pools/{name}/leaks
  3. Identify code paths that checkout but don't release connections
  4. Reduce max_checkout_duration to catch leaks sooner
  5. Ensure all defer conn.Close() patterns are correct in application code

Replica lag causing stale reads

  1. Check replica lag via database metrics
  2. Configure lag threshold in pool — lagging replicas auto-excluded
  3. Monitor how many queries fall back to primary due to lag
  4. Consider adding more replicas or optimizing replication

Slow queries increasing

  1. Review /api/v1/pools/{name}/slow-queries for patterns
  2. Check pranor_pool_query_duration_ms histogram for p99 growth
  3. Use query normalization to identify expensive query signatures
  4. Work with DBA to add indexes or optimize queries
  5. Consider prepared statement cache to reduce parse overhead

Pranor Notify — Multi-Channel Notification Engine

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/notify
Default Port: 8094
License: AGPL-3.0 (OSS) / Enterprise License (EE with AI Deliverability & WebPush)


Overview

Pranor Notify is the transactional email, SMS, and push notification service for the Pranor ecosystem. It handles sending, receiving, bounce management, unsubscribe compliance (RFC 8058), DMARC/SPF/DKIM enforcement, inbound email routing, and provides a rich templating DSL with delivery analytics.

Pranor Notify can run as:

  • A standalone binary with SMTP relay configuration for email delivery
  • An integrated module within the Pranor ecosystem with multi-channel dispatch, OTel tracing, and Console analytics

Key Features

FeatureDescription
Transactional EmailREST API for HTML/plain text emails with attachments, CC/BCC
Template DSLVariable interpolation, conditionals, loops, partials, and layouts
SMTP RelayRoute via SendGrid, AWS SES, Mailgun, or custom SMTP
Inbound RoutingRoute incoming emails to HTTP webhooks based on rules
Bounce ManagementAuto-suppression list with hard/soft bounce classification
DMARC EnforcementSPF/DKIM/DMARC alignment checking and aggregate reports
RFC 8058 UnsubscribeOne-click unsubscribe headers on all bulk emails
SMS GatewayTwilio and multi-carrier SMS delivery
WebPush / APNsBrowser push and Apple Push Notification delivery
Delivery AnalyticsPer-campaign rates, opens, clicks, bounces, complaints
Suppression ListAutomatic and manual address suppression management

Architecture

graph TD

    subgraph ChannelAdapters ["🌐 Multi-Channel Notification Ingress"]
        EmailAPI["Transactional Email API"]
        PushAPI["WebPush and APNs Provider"]
        SMSAPI["Twilio and Multi-Carrier SMS Gateway"]
    end

    subgraph DispatchEngine ["⚡ Template and Deliverability Engine"]
        TemplateEngine["HTML / DSL Template Rendering Engine"]
        DMARCVal["DMARC / SPF / DKIM Inspector and Alignment"]
        SuppressionList["Automatic Bounce and Suppression Filter"]
        AIOptimizer["AI Deliverability and Send-Time Optimizer"]
    end

    subgraph Relays ["💾 Provider Relays and Analytics"]
        SMTPRelay["Outbound SMTP Relay Pool"]
        WebhookRouter["Inbound Webhook and RFC 8058 Unsubscribe Router"]
    end

    EmailAPI --> TemplateEngine
    PushAPI --> TemplateEngine
    SMSAPI --> TemplateEngine
    TemplateEngine --> DMARCVal
    DMARCVal --> SuppressionList
    SuppressionList --> AIOptimizer
    AIOptimizer --> SMTPRelay
    SMTPRelay --> WebhookRouter

Notification Dispatch & Bounce Suppression Sequence Flow

sequenceDiagram
    autonumber
    participant App as Application Microservice
    participant Notify as Pranor Notify Engine
    participant Suppression as Suppression List
    participant Template as DSL Template Renderer
    participant Gateway as SMTP / SMS / Push Gateway
    participant Analytics as Pranor Console Analytics

    App->>Notify: POST /api/v1/send/template (Template: "welcome-email", User Email)
    Notify->>Suppression: Check Address against Hard-Bounce Suppression List
    Suppression-->>Notify: Clean Record (Not Suppressed)
    Notify->>Template: Inject Payload Variables into DSL Template
    Template-->>Notify: Rendered HTML Body + List-Unsubscribe-Post Header
    Notify->>Gateway: Relay Encrypted Payload via Outbound SMTP / Push Gateway
    Gateway-->>Notify: Delivery Acknowledgment (Message ID: msg-7718)
    Notify->>Analytics: Push Delivery Telemetry & Open/Click Trackers

Ecosystem Cross-Module Integration

Pranor Notify delivers multi-channel communications across the Pranor platform:

  • Pranor Auth: Sends one-time password (OTP) codes for multi-factor authentication (MFA) step-up login challenges.
  • Pranor Trace: Annotates notification dispatch events with OpenTelemetry traces, recording deliverability latency flamegraphs.
  • Pranor Flow: Triggers customer communication steps in saga workflows (e.g., order confirmation emails, shipment SMS alerts).
  • Pranor Console: Renders live deliverability analytics, bounce rate histograms, and template editor UI.

Installation & Deployment

Binary

cd pranor/notify
go build -o pranor-notify .
./pranor-notify --port 8094

Docker

docker run -p 8094:8094 ghcr.io/vyuvaraj/pranor-notify:latest

With SMTP Configuration

docker run -p 8094:8094 \
  -e PRANOR_NOTIFY_SMTP_HOST=smtp.sendgrid.net \
  -e PRANOR_NOTIFY_SMTP_PORT=587 \
  -e PRANOR_NOTIFY_SMTP_USER=apikey \
  -e PRANOR_NOTIFY_SMTP_PASS=SG.xxxxx \
  -e PRANOR_NOTIFY_FROM_DOMAIN=yourapp.com \
  ghcr.io/vyuvaraj/pranor-notify:latest

As Part of Pranor Ecosystem

When running under the Pranor platform, Notify integrates automatically with Auth (MFA OTP), Trace (OTel spans), Flow (saga steps), and Console (analytics dashboard).


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_NOTIFY_PORT8094HTTP listener port
PRANOR_NOTIFY_SMTP_HOSTOutbound SMTP relay host
PRANOR_NOTIFY_SMTP_PORT587Outbound SMTP relay port
PRANOR_NOTIFY_SMTP_USERSMTP authentication username
PRANOR_NOTIFY_SMTP_PASSSMTP authentication password
PRANOR_NOTIFY_FROM_DOMAINDefault sending domain
PRANOR_NOTIFY_INBOUND_PORTSMTP port for inbound mail reception
PRANOR_NOTIFY_DMARC_ENABLEDtrueEnable DMARC enforcement
PRANOR_NOTIFY_OTEL_ENDPOINTOpenTelemetry collector URL

YAML Config (notify.yaml)

port: "8094"
smtp:
  host: "smtp.sendgrid.net"
  port: 587
  user: "apikey"
  pass: "SG.xxxxx"
from_domain: "yourapp.com"
inbound_port: 25
dmarc_enabled: true
otel_endpoint: "http://pranor-trace:8090"

CLI Flags

FlagDefaultDescription
--port8094HTTP listen port

API Reference

Base URL: http://localhost:8094

POST /api/v1/send

Send a transactional email.

Request:

{
  "to": "alice@example.com",
  "from": "noreply@yourapp.com",
  "subject": "Order Confirmation",
  "html": "<h1>Thanks for your order!</h1>",
  "text": "Thanks for your order!",
  "cc": ["admin@yourapp.com"],
  "attachments": []
}

Response (200):

{
  "status": "sent",
  "message_id": "msg-7718",
  "delivered_at": "2026-08-01T10:00:01Z"
}

POST /api/v1/send/template

Send using a named template.

Request:

{
  "template": "welcome-email",
  "to": "alice@example.com",
  "variables": {
    "user": { "name": "Alice", "verified": true }
  }
}

Response (200):

{
  "status": "sent",
  "message_id": "msg-7719",
  "template": "welcome-email"
}

POST /api/v1/templates

Create or update an email template.

Request:

{
  "name": "welcome-email",
  "subject": "Welcome, {{ user.name }}!",
  "html": "<h1>Welcome, {{ user.name }}!</h1>\n{% if user.verified %}<p>Verified.</p>{% endif %}"
}

Response (201):

{
  "status": "created",
  "name": "welcome-email"
}

GET /api/v1/suppression

List suppressed addresses.

Response (200):

{
  "addresses": [
    { "email": "bad@example.com", "reason": "hard_bounce", "suppressed_at": "2026-07-30T08:00:00Z" }
  ]
}

POST /api/v1/inbound/rules

Create an inbound routing rule.

Request:

{
  "name": "support-tickets",
  "match": { "to_pattern": "support@yourapp.com" },
  "forward_to": "http://helpdesk/api/tickets",
  "priority": 10
}

Response (201):

{
  "status": "created",
  "rule_id": "rule-001"
}

GET /api/v1/dmarc/report

Generate DMARC aggregate report.

Response (200):

{
  "period": "2026-07",
  "total_messages": 15420,
  "aligned": 15100,
  "failed_spf": 120,
  "failed_dkim": 200
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-notify","version":"1.0.0"}

Security

Standalone Mode

In standalone mode, Notify connects directly to a configured SMTP relay. No authentication required for API access.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. JWT Auth — validates Bearer tokens against Pranor Auth
  2. Rate Limiting — per-client send rate throttling
  3. DMARC Enforcement — incoming mail validated against SPF/DKIM/DMARC
  4. Suppression List — automatic blocking of bounced/complained addresses
  5. OTel Tracing — every send generates a trace span

Email Security

  • SPF alignment — validates sender IP against domain's SPF record
  • DKIM signing — signs outgoing emails with domain key
  • DMARC reporting — generates and sends RUA aggregate reports
  • TLS encryption — STARTTLS for all outbound SMTP connections

Observability

Prometheus Metrics

MetricTypeDescription
pranor_notify_sent_totalCounterEmails sent (labeled by channel, status)
pranor_notify_bounces_totalCounterBounce events (labeled by type: hard/soft)
pranor_notify_suppressed_totalCounterSuppressed sends (address on suppression list)
pranor_notify_delivery_latency_msHistogramTime to SMTP acknowledgment
pranor_notify_templates_activeGaugeRegistered templates
pranor_notify_inbound_routed_totalCounterInbound emails routed

OpenTelemetry Tracing

Notify emits spans for:

  • notify.send — email dispatch
  • notify.template.render — template rendering
  • notify.suppression.check — suppression list lookup
  • notify.dmarc.validate — DMARC alignment check
  • notify.inbound.route — inbound email routing

Logging

Structured JSON logs with fields: level, timestamp, trace_id, message_id, to, template, channel, status.


Enterprise Edition

FeatureOSSEE
Transactional email via SMTP
Template DSL (variables, conditionals, loops)
Bounce management & suppression
DMARC/SPF/DKIM enforcement
Inbound email routing
RFC 8058 one-click unsubscribe
Mailing list management
SMS gateway (Twilio, multi-carrier)
WebPush / APNs push notifications
AI deliverability & send-time optimizer
Delivery analytics dashboard
Per-recipient event tracking

Operational Runbook

Emails not being delivered

  1. Check SMTP relay connectivity (PRANOR_NOTIFY_SMTP_HOST)
  2. Verify SMTP credentials are correct
  3. Check suppression list — recipient may be suppressed
  4. Review DMARC/SPF/DKIM alignment for the sending domain
  5. Check pranor_notify_delivery_latency_ms for SMTP timeout issues

High bounce rate

  1. Monitor pranor_notify_bounces_total metric by type
  2. Hard bounces indicate invalid addresses — clean your list
  3. Soft bounces (mailbox full) will auto-retry with backoff
  4. Review suppression list growth: GET /api/v1/suppression
  5. Check domain reputation via external tools (Google Postmaster)

Inbound routing not matching

  1. List rules: GET /api/v1/inbound/rules
  2. Verify rule patterns match incoming email headers
  3. Check priority ordering — higher priority rules match first
  4. Verify the forward_to webhook URL is reachable
  5. Check inbound SMTP port is accessible (PRANOR_NOTIFY_INBOUND_PORT)

Template rendering errors

  1. Verify template exists: GET /api/v1/templates/{name}
  2. Check variable names match the payload structure
  3. Review DSL syntax for unclosed conditionals or loops
  4. Test with minimal variables to isolate the issue

Pranor Flow — DAG Workflow & Saga Orchestrator

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/flow
Default Port: 8096
License: AGPL-3.0 (OSS) / Enterprise License (EE with BFT Raft & Visual Designer)


Overview

Pranor Flow is a stateful, DAG-based workflow orchestrator and Saga compensation engine for the Pranor ecosystem. It supports durable execution with checkpointing, WASM step functions, sub-workflow composition, per-execution tracing, a Dead Letter Workflow Queue with manual retry, and automatic reverse compensation on failure.

Pranor Flow can run as:

  • A standalone binary with file-based checkpoint persistence
  • An integrated module within the Pranor ecosystem with OTel tracing, Pranor Lock leader election, and Console visual designer

Key Features

FeatureDescription
DAG OrchestrationMulti-step execution graphs with topological sort and parallel fan-out/fan-in
Saga CompensationAutomatic reverse compensation on failure — only completed steps are rolled back
Durable ExecutionWAL checkpoint persistence; resume from last successful step after restarts
WASM Step FunctionsSandboxed WASI-compliant WebAssembly step execution (Rust, C, Go)
Sub-workflow CompositionCompose workflows from reusable sub-workflows with recursive nesting
Dead Letter QueueFailed workflows moved to DLWQ with full context and manual retry
Step Output PropagationEach step's output becomes the next step's input
Conditional BranchingSkip steps based on upstream output conditions
AI Cost TrackingLLM token cost annotations on spans for AI workflow steps
Idempotent ReplaySkip already-completed steps on resume for safe replay

Architecture

graph TD

    subgraph API ["🌐 Workflow Control Interface"]
        Define["REST DAG Definition API"]
        Exec["Execution Manager API"]
    end

    subgraph Core ["⚡ Core Distributed Saga Orchestrator"]
        Topo["Topological Sort and Dependency Evaluator"]
        HTTPExec["HTTP / REST Step Executor"]
        WASMExec["WASM Sandbox Step Executor"]
        SagaComp["Saga Reverse Compensation Handler"]
    end

    subgraph Storage ["💾 Durable State Persistence"]
        WALStore["WAL Checkpoint Store"]
        DLWQ["Dead-Letter Workflow Queue"]
        BFTConsensus["BFT Raft State Consensus"]
    end

    Define --> Topo
    Exec --> Topo
    Topo --> HTTPExec
    Topo --> WASMExec
    HTTPExec --> WALStore
    WASMExec --> WALStore
    WALStore -.->|On Failure| SagaComp
    SagaComp -.->|Max Retries Exhausted| DLWQ
    WALStore -.-> BFTConsensus

Saga Execution & Compensation Sequence Flow

sequenceDiagram
    autonumber
    participant Client as Client Application
    participant Flow as Pranor Flow Orchestrator
    participant Inventory as Inventory Service
    participant Payment as Payment Gateway
    participant Shipping as Shipping Service
    participant WAL as WAL Checkpoint Store

    Client->>Flow: Execute Workflow (Order Checkout DAG)
    Flow->>Inventory: Step 1: POST /inventory/reserve
    Inventory-->>Flow: 200 OK (Reserved)
    Flow->>WAL: Checkpoint Step 1 Completed
    Flow->>Payment: Step 2: POST /payment/charge
    Payment-->>Flow: 500 Internal Error (Payment Failed)
    Flow->>WAL: Log Step 2 Execution Failure
    Note over Flow,Inventory: Trigger Reverse Compensation Rollback
    Flow->>Inventory: Compensate Step 1: POST /inventory/release
    Inventory-->>Flow: 200 OK (Inventory Unreserved)
    Flow->>WAL: Saga Rollback Completed
    Flow-->>Client: Workflow Execution Failed (Compensated)

Ecosystem Cross-Module Integration

Pranor Flow acts as the primary saga orchestrator across the Pranor ecosystem:

  • Pranor Pulse: Dispatches asynchronous event triggers and listens to topic completions during long-running saga steps.
  • Pranor Trace: Annotates every workflow execution and individual step with W3C traceparent headers, tracking LLM token costs and latency flamegraphs.
  • Pranor Lock: Acquires distributed fencing token leases to ensure saga execution steps are evaluated by a single leader node during failover.
  • Pranor Console: Provides a visual DAG designer, live workflow step progress tracking, and 1-click DLQ retry controls.

Installation & Deployment

Binary

cd pranor/flow
go build -o pranor-flow .
./pranor-flow --port 8096

Docker

docker run -p 8096:8096 \
  -v flow-data:/data \
  ghcr.io/vyuvaraj/pranor-flow:latest

With Checkpoint Persistence

./pranor-flow --port 8096 --checkpoint-dir /data/checkpoints

As Part of Pranor Ecosystem

When running under the Pranor platform, Flow integrates automatically with Lock (leader election), Trace (OTel spans), Console (visual designer), and Pulse (event triggers).


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_FLOW_PORT8096HTTP listener port
PRANOR_FLOW_CHECKPOINT_DIR./checkpointsDirectory for workflow state checkpoint files
PRANOR_FLOW_OTEL_ENDPOINTOpenTelemetry collector URL
PRANOR_FLOW_WASM_MODULES_DIR./wasmDirectory for WASM step module files
PRANOR_FLOW_DLQ_MAX_SIZE1000Max workflows retained in DLQ

YAML Config (flow.yaml)

port: "8096"
checkpoint_dir: "/data/checkpoints"
otel_endpoint: "http://pranor-trace:8090"
wasm_modules_dir: "./wasm"
dlq_max_size: 1000

CLI Flags

FlagDefaultDescription
--port8096HTTP listen port
--checkpoint-dir./checkpointsCheckpoint persistence directory

API Reference

Base URL: http://localhost:8096

POST /api/workflows/define

Define a new DAG workflow.

Request:

{
  "name": "order-fulfillment",
  "steps": [
    {
      "id": "reserve-inventory",
      "type": "http",
      "url": "http://inventory/reserve",
      "depends_on": [],
      "compensate_url": "http://inventory/release"
    },
    {
      "id": "charge-payment",
      "type": "http",
      "url": "http://payments/charge",
      "depends_on": ["reserve-inventory"],
      "compensate_url": "http://payments/refund"
    },
    {
      "id": "notify-customer",
      "type": "http",
      "url": "http://notifications/send",
      "depends_on": ["charge-payment"]
    }
  ]
}

Response (201):

{
  "id": "wf-def-001",
  "name": "order-fulfillment",
  "step_count": 3,
  "status": "registered"
}

POST /api/workflows/execute

Execute a workflow instance.

Request:

{
  "workflow": "order-fulfillment",
  "input": { "order_id": "ord-123", "amount": 99.99 }
}

Response (200):

{
  "instance_id": "wf-abc-001",
  "status": "running",
  "started_at": "2026-08-01T10:00:00Z"
}

GET /api/workflows/instances/

Get execution status and step logs.

Response (200):

{
  "instance_id": "wf-abc-001",
  "workflow": "order-fulfillment",
  "status": "completed",
  "steps": [
    { "id": "reserve-inventory", "status": "success", "duration_ms": 45 },
    { "id": "charge-payment", "status": "success", "duration_ms": 230 },
    { "id": "notify-customer", "status": "success", "duration_ms": 12 }
  ]
}

POST /api/workflows/resume

Resume a workflow from its last checkpoint.

Request:

{
  "instance_id": "wf-abc-001"
}

Response (200):

{
  "status": "resumed",
  "resumed_from_step": "charge-payment"
}

GET /api/workflows/dlq

Browse Dead Letter Workflow Queue.

Response (200):

{
  "workflows": [
    {
      "instance_id": "wf-xyz-002",
      "workflow": "order-fulfillment",
      "failed_step": "charge-payment",
      "error": "connection timeout",
      "failed_at": "2026-08-01T09:30:00Z"
    }
  ]
}

POST /api/workflows/dlq/{id}/retry

Retry a DLQ workflow.

Response (200):

{
  "status": "retrying",
  "instance_id": "wf-xyz-002"
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-flow","version":"1.0.0"}

Security

Standalone Mode

In standalone mode, Flow runs without authentication. Workflow callbacks are dispatched without auth headers.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. OTel Tracing — every request and step execution gets a span
  2. Rate Limiting — per-client request throttling
  3. JWT Auth — validates Bearer tokens against Pranor Auth
  4. Tenant Isolation — workflows scoped per tenant namespace
  5. Callback Auth — configurable bearer token forwarded to step URLs

WASM Sandbox Security

WASM steps execute in a sandboxed environment:

  • No filesystem access beyond stdin/stdout
  • Per-step execution timeout prevents runaway processes
  • Memory limits enforced per WASM module

Observability

Prometheus Metrics

MetricTypeDescription
pranor_flow_workflows_activeGaugeCurrently executing workflows
pranor_flow_steps_totalCounterTotal step executions (labeled by status)
pranor_flow_step_duration_msHistogramStep execution duration
pranor_flow_compensations_totalCounterSaga compensation events
pranor_flow_dlq_depthGaugeDead letter queue depth
pranor_flow_checkpoints_totalCounterCheckpoint writes

OpenTelemetry Tracing

Every workflow and step generates OTel spans:

  • flow.workflow.execute — root workflow span
  • flow.step.http — HTTP step execution
  • flow.step.wasm — WASM step execution
  • flow.saga.compensate — compensation rollback
  • flow.dlq.enqueue — DLQ enqueue event

Logging

Structured JSON logs with fields: level, timestamp, trace_id, instance_id, step_id, status, duration_ms.


Enterprise Edition

FeatureOSSEE
DAG workflow orchestration
Saga compensation
Checkpoint persistence
WASM step functions
Sub-workflow composition
Dead letter queue
OTel tracing
BFT Raft state consensus
Visual DAG designer UI
AI cost tracking per step
Multi-cluster workflow federation
Event-driven triggers (Pranor Pulse)

Operational Runbook

Workflow stuck in "running" state

  1. Check /api/workflows/instances/{id} for step-level status
  2. Identify which step is blocking — check its callback URL health
  3. If step timed out, the workflow may be waiting for checkpoint write
  4. Resume from checkpoint: POST /api/workflows/resume
  5. If stuck permanently, check disk space for checkpoint directory

Saga compensation failing

  1. Check compensate_url endpoints are reachable and returning 200
  2. Review logs for compensation step errors
  3. Compensations are best-effort — if they fail, manual intervention required
  4. Check pranor_flow_compensations_total metric for failure patterns

DLQ growing unbounded

  1. Monitor pranor_flow_dlq_depth gauge
  2. Review failed workflows in DLQ for common error patterns
  3. Fix root cause (downstream service, timeout, etc.)
  4. Retry workflows: POST /api/workflows/dlq/{id}/retry
  5. Adjust PRANOR_FLOW_DLQ_MAX_SIZE to prevent memory issues

WASM steps timing out

  1. Check PRANOR_FLOW_WASM_MODULES_DIR for module availability
  2. Review step timeout configuration in workflow definition
  3. Check WASM module for infinite loops or excessive memory allocation
  4. Monitor pranor_flow_step_duration_ms histogram for WASM steps

v2.0 AgentStep & Saga Engine

In v2.0, Pranor Flow extends with a Saga runner for governed AI agent step execution.

AgentStep Interface

type AgentStep interface {
    Execute(ctx context.Context, input StepInput) (StepOutput, error)
    Compensate(ctx context.Context, input StepInput) error
    Name() string
}

SagaConfig Defaults

FieldDefaultDescription
MaxSteps25Maximum steps before LimitPolicy triggers
StepTimeout30sPer-step execution timeout
TotalTimeout10mTotal saga timeout
OnStepLimitHitLimitPolicyCompensateAction when MaxSteps exceeded

Limit Policies

  • LimitPolicyCompensate: Automatically unwinds completed steps in reverse order
  • LimitPolicyPauseForHITL: Pauses and routes to HITL Approval Queue (EE: Slack/Teams/Email)

Compensation Contract

On step failure, Saga calls Compensate on all previously completed steps in reverse order. Partial compensation failures are recorded in SagaResult.CompensatedSteps but do not prevent the result from being returned.

HITL Approval Queue

The flow/pkg/hitl package provides an in-memory approval queue:

  • Submit(req ApprovalRequest) (string, error) — enqueue for review
  • Approve(id string, note string) error — mark approved
  • Reject(id string, reason string) error — mark rejected with reason
  • ListPending() []ApprovalRequest — list outstanding approvals

EE extends with Slack, Microsoft Teams, and Email integrations with SLA timer escalation.

Pranor Deploy — Deployment Orchestrator

Version: 0.1.0
Module Path: github.com/vyuvaraj/pranor/deploy
Default Port: 8085
License: AGPL-3.0 (OSS) / Enterprise License (EE with FinOps & DR Chaos Suite)


Overview

Pranor Deploy is the managed deployment platform and process orchestrator for the Pranor ecosystem. It provides PaaS-style service deployment, blue/green and canary strategies, per-branch preview environments, container isolation, ring-buffer log streaming, and deep integration with Pranor Gate for automatic routing registration.

Pranor Deploy can run as:

  • A standalone binary deploying processes with dynamic port allocation
  • An integrated module within the Pranor ecosystem with Gate route sync, OTel tracing, and container isolation

Key Features

FeatureDescription
PaaS Deployment APIDeploy services on demand via REST with automatic route registration
Blue/Green DeploymentAtomic zero-downtime traffic cutover with instant rollback
Canary DeploymentConfigurable traffic split with auto-rollback on error threshold
Preview EnvironmentsPer-branch ephemeral environments with unique subdomains
Container IsolationDocker/OCI container mode with resource limits and network isolation
Process ModeLightweight raw process execution for development
Ring-buffer LogsCapture stdout/stderr with streaming log API
Gate Auto-RegistrationDeployed services automatically get Pranor Gate routes
Health GateDeployments must pass health checks before traffic cutover
GitOps WebhooksTrigger deployments from Git push events

Architecture

graph TD

    subgraph Trigger ["🌐 Deployment Control API"]
        GitOps["GitOps Webhook and Branch Trigger"]
        DeployAPI["REST Deployment API"]
    end

    subgraph Orchestrator ["⚡ Core Deployment and FinOps Engine"]
        StrategyMgr["Deployment Strategy Manager"]
        FinOps["AI FinOps Cloud Cost Optimizer"]
        ChaosSuite["Automated DR Chaos Simulation Suite"]
        GateReg["Pranor Gate Route Auto-Registrar"]
    end

    subgraph IsolatedEnvs ["💾 Environment Provisioning and Artifacts"]
        ContainerIso["OCI / Docker Container Isolation Engine"]
        PreviewMgr["Ephemeral Preview Environment Provisioner"]
        AirgapHub["Air-Gapped Private Artifact Registry"]
    end

    GitOps --> StrategyMgr
    DeployAPI --> StrategyMgr
    StrategyMgr --> FinOps
    FinOps --> ChaosSuite
    ChaosSuite --> GateReg
    GateReg --> ContainerIso
    GateReg --> PreviewMgr
    ContainerIso -.-> AirgapHub

Canary Rollout & AI FinOps Promotion Sequence Flow

sequenceDiagram
    autonumber
    participant Developer as Developer / GitOps Pipeline
    participant Deploy as Pranor Deploy Engine
    participant FinOps as AI FinOps Optimizer
    participant Gate as Pranor Gate Ingress
    participant Pods as Canary / Blue-Green Pods

    Developer->>Deploy: POST /api/v1/deployments (Canary 10% Traffic)
    Deploy->>FinOps: Evaluate Node Allocation & Spot Instance Budgets
    FinOps-->>Deploy: Optimal Node Topology Approved
    Deploy->>Pods: Spin Up New Version (Canary Container Pods)
    Deploy->>Gate: Update Weighted Route (10% Canary, 90% Stable)
    Gate-->>Deploy: Traffic Splitting Active (Monitoring Latency/Errors)
    alt Error Rate < 0.01% & Health Check Passed
        Deploy->>Gate: Promote Canary to 100% Traffic (Cutover)
        Gate-->>Deploy: Full Production Cutover Complete
    else Latency Spike / Error Threshold Exceeded
        Deploy->>Gate: Immediate Auto-Rollback to 0% Canary
        Deploy-->>Developer: Deployment Aborted & Rollback Triggered
    end

Ecosystem Cross-Module Integration

Pranor Deploy automates release rollouts across all platform components:

  • Pranor Gate: Enforces zero-downtime weighted canary traffic splits, blue/green cutovers, and preview subdomain routing.
  • Pranor Hub: Pulls signed OCI container images, WebAssembly modules, and Helm charts for air-gapped deployments.
  • Pranor Trace: Monitors real-time error rate budgets and latency burn rates during progressive canary rollouts.
  • Pranor Console: Provides interactive multi-cluster deployment dashboards, 1-click rollback controls, and live container logs.

Installation & Deployment

Binary

cd pranor/deploy
go build -o pranor-deploy .
./pranor-deploy --port 8085

Docker

docker run -p 8085:8085 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/vyuvaraj/pranor-deploy:latest

With Pranor Gate Sync

./pranor-deploy --port 8085 --gateway http://pranor-gate:8080 --auth-token secret-token

As Part of Pranor Ecosystem

When running under the Pranor platform, Deploy integrates automatically with Gate (route sync), Hub (artifact pull), Trace (OTel spans), and Console (dashboard visibility).


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_DEPLOY_PORT8085HTTP listener port
PRANOR_DEPLOY_PRANOR_GATE_URLPranor Gate URL for route registration
PRANOR_DEPLOY_OTEL_ENDPOINTOpenTelemetry collector URL
PRANOR_DEPLOY_CONTAINER_RUNTIMEprocessprocess (raw) or docker (OCI container)
PRANOR_DEPLOY_PREVIEW_DOMAINBase domain for preview environments
PRANOR_DEPLOY_PREVIEW_TTL7dDefault preview environment TTL
PRANOR_DEPLOY_WORKDIR./.deploymentsDirectory for deployment artifacts

YAML Config (deploy.yaml)

port: "8085"
gateway_url: "http://pranor-gate:8080"
auth_token: "secret-token"
container_runtime: "docker"
preview_domain: "preview.pranor.net"
preview_ttl: "7d"
workdir: "./.deployments"
otel_endpoint: "http://pranor-trace:8090"

CLI Flags

FlagDefaultDescription
--port8085HTTP listen port
--workdir./.deploymentsDeployment working directory
--gatewayhttp://localhost:8080Pranor Gate URL
--auth-tokensecret-tokenAuth token for Gateway registration
--versionPrint version and exit

API Reference

Base URL: http://localhost:8085

POST /api/v1/deployments

Deploy a service.

Request:

{
  "service": "orders-api",
  "image": "ghcr.io/myorg/orders:v2.1.0",
  "strategy": "canary",
  "port": 3000,
  "canary_weight": 10,
  "auto_rollback_error_rate": 0.05
}

Response (201):

{
  "id": "dep-abc-123",
  "service": "orders-api",
  "strategy": "canary",
  "status": "deploying",
  "canary_weight": 10,
  "url": "http://orders-api:3000"
}

POST /api/v1/deployments/{id}/promote

Promote canary to higher traffic weight.

Request:

{
  "weight": 50
}

Response (200):

{
  "status": "promoted",
  "canary_weight": 50
}

POST /api/v1/deployments/{id}/rollback

Roll back to previous stable version.

Response (200):

{
  "status": "rolled_back",
  "restored_version": "v2.0.0"
}

POST /api/v1/deployments/{id}/cutover

Blue/Green: cut all traffic to new version.

Response (200):

{
  "status": "cutover_complete",
  "active_version": "green"
}

GET /api/v1/deployments/{id}/logs

Stream deployment logs from ring buffer.

Response (200):

{
  "lines": [
    "[2026-08-01 10:00:01] Server started on :3000",
    "[2026-08-01 10:00:02] Connected to database"
  ]
}

POST /api/v1/previews

Create a preview environment.

Request:

{
  "branch": "feature/new-checkout",
  "ttl": "7d"
}

Response (201):

{
  "id": "prev-001",
  "url": "https://feature-new-checkout.preview.pranor.net",
  "expires_at": "2026-08-08T10:00:00Z"
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-deploy","version":"0.1.0"}

Security

Standalone Mode

Configure --auth-token for Gateway registration authentication. Deploy endpoints are unauthenticated in standalone mode.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. JWT Auth — validates Bearer tokens against Pranor Auth
  2. RBAC enforcement — deployment permissions per service/environment
  3. Audit trail — every deploy, promote, rollback logged with operator identity
  4. Container isolation — network namespaces prevent cross-deployment access
  5. OTel Tracing — deployment lifecycle spans

Docker Socket Security

When using Docker runtime, Deploy requires access to the Docker socket. In production, use rootless Docker or configure appropriate socket permissions.


Observability

Prometheus Metrics

MetricTypeDescription
pranor_deploy_active_deploymentsGaugeCurrently running deployments
pranor_deploy_rollbacks_totalCounterTotal rollback events
pranor_deploy_canary_promotions_totalCounterCanary promotions
pranor_deploy_preview_environments_activeGaugeActive preview environments
pranor_deploy_error_rateGaugeCurrent canary error rate

OpenTelemetry Tracing

Every deployment generates OTel spans:

  • deploy.create — deployment initialization
  • deploy.health_check — health gate validation
  • deploy.cutover — traffic cutover event
  • deploy.rollback — rollback trigger

Logging

Structured JSON logs with fields: level, timestamp, trace_id, deployment_id, service, strategy, action.


Enterprise Edition

FeatureOSSEE
Direct deployment (process mode)
Blue/green deployment
Canary with auto-rollback
Preview environments
Docker container isolation
Gate route auto-registration
Ring-buffer log streaming
AI FinOps cost optimizer
Automated DR chaos simulation
Air-gapped private artifact registry
Multi-cluster deployment federation
GitOps webhook triggers

Operational Runbook

Deployment stuck in "deploying" state

  1. Check /api/v1/deployments/{id} for status details
  2. Verify container image is pullable (check registry credentials)
  3. Check health check endpoint of the deployed service
  4. Review deployment logs via /api/v1/deployments/{id}/logs
  5. If using Docker, check docker ps for container state

Canary auto-rollback triggered unexpectedly

  1. Check pranor_deploy_error_rate metric during the canary window
  2. Review the auto_rollback_error_rate threshold configuration
  3. Verify Trace/Gate are reporting accurate error rates (not false positives)
  4. Check if a downstream dependency caused the errors (not the canary itself)

Preview environments not cleaning up

  1. Check PRANOR_DEPLOY_PREVIEW_TTL configuration
  2. List active previews: GET /api/v1/previews
  3. Manually delete expired previews: DELETE /api/v1/previews/{id}
  4. Verify the cleanup background worker is running (check logs)

Gate route not registering after deploy

  1. Verify PRANOR_DEPLOY_PRANOR_GATE_URL is configured and reachable
  2. Check auth token matches between Deploy and Gate
  3. Review Deploy logs for route registration errors
  4. Manually verify route via Gate's route listing API

Pranor Tunnel — Secure Dev Tunneling

Version: 0.1.0
Module Path: github.com/vyuvaraj/pranor/tunnel
Default Port: 8443
License: AGPL-3.0 (OSS) / Enterprise License (EE with WireGuard E2E & Custom Domains)


Overview

Pranor Tunnel is a secure, instant tunneling service for exposing local services to the internet during development and testing. One command creates a public URL that forwards requests to your local machine via WebSocket multiplexing — ideal for webhook testing, OAuth callbacks, mobile app dev, and sharing work in progress.

Pranor Tunnel can run as:

  • A server (relay) accepting incoming public traffic and routing to connected clients
  • A client (daemon) running on developer machines, connecting to the relay and forwarding to localhost

Key Features

FeatureDescription
Subdomain RoutingEach tunnel gets a unique subdomain (e.g., myapp.pranor.net)
WebSocket MultiplexingBinary-framed streams over a single WebSocket connection
Request InspectionRing-buffer captures all requests/responses for debugging
Request ReplayReplay any captured request with one API call
JWT Auth GatingRequire valid JWT to open tunnel connections
Shareable URLsTime-limited shareable tunnel URLs with auto-expiry
Git Branch Auto-subdomainAutomatically derives subdomain from current Git branch
Multi-port TunnelingExpose multiple local ports with a single config file
Custom DomainsMap custom domains to tunnels (DNS CNAME)
OTel Propagationtraceparent headers forwarded through the tunnel
ReconnectionPersistent reconnect with exponential backoff and jitter

Architecture

graph TD

    subgraph ExternalIngress ["🌐 Public Webhook and Browser Ingress"]
        PublicClient["External Webhook Sender / Browser"]
        SubdomainRouter["Public Subdomain Ingress Router"]
    end

    subgraph TunnelServer ["⚡ Tunnel Multiplexer and Inspection Engine"]
        WSMux["WebSocket Connection Multiplexer"]
        Inspections["Ring-Buffer Request Capturer and Inspection"]
        E2EEncryption["Zero-Trust WireGuard E2E Encryption"]
        ReplayEngine["Request Replay Engine"]
    end

    subgraph LocalMachine ["💾 Private Local Workload"]
        TunnelClient["Pranor Tunnel Daemon CLI Client"]
        LocalSvc["Local Microservice / Webhook Receiver"]
    end

    PublicClient --> SubdomainRouter
    SubdomainRouter --> WSMux
    WSMux --> Inspections
    Inspections --> E2EEncryption
    E2EEncryption --> ReplayEngine
    ReplayEngine --> TunnelClient
    TunnelClient --> LocalSvc

Public Webhook Proxying & Request Replay Sequence Flow

sequenceDiagram
    autonumber
    participant External as Stripe / GitHub Webhook Sender
    participant Server as Pranor Tunnel Server
    participant Buffer as Inspection Ring Buffer
    participant Client as Pranor Tunnel Local CLI
    participant Local as Local Host Service (localhost:3000)

    External->>Server: POST https://myapp.pranor.net/webhooks (Stripe Signature Header)
    Server->>Buffer: Store Request Headers & Body Payload in Ring Buffer
    Server->>Client: Forward Stream Payload over Multiplexed WebSocket
    Client->>Local: HTTP POST http://localhost:3000/webhooks
    Local-->>Client: 200 OK (Processed locally)
    Client-->>Server: Forward Response Frame over WebSocket
    Server-->>External: 200 OK (Proxy Complete)
    Note over External,Local: Developer triggers manual 1-Click Request Replay
    Client->>Server: POST /api/v1/tunnels/{id}/replay/{reqID}
    Server->>Local: Replay Captured Request to Local Host

Ecosystem Cross-Module Integration

Pranor Tunnel provides secure localhost exposure across the Pranor platform:

  • Pranor Gate: Relays public HTTPS ingress routes into multiplexed WebSocket tunnels for dev preview environments.
  • Pranor Trace: Generates traceparent OpenTelemetry headers, tracing requests from public webhooks through tunnels into local code.
  • Pranor Deploy: Exposes ephemeral branch preview environments securely without public IP addresses.
  • Pranor Console: Renders the visual Request Inspector UI, enabling 1-click webhook replays and live packet inspection.

Installation & Deployment

Server (Self-hosted Relay)

cd pranor/tunnel
go build -o pranor-tunnel .
./pranor-tunnel server --port 8443 --domain pranor.net

Docker (Server)

docker run -p 8443:8443 \
  -e PRANOR_TUNNEL_DOMAIN=pranor.net \
  -e PRANOR_TUNNEL_JWT_SECRET=my-secret \
  ghcr.io/vyuvaraj/pranor-tunnel:latest server

Client (Local Machine)

# Install
go install github.com/vyuvaraj/pranor/tunnel@latest

# Expose local port 3000
pranor-tunnel client 3000 --relay ws://tunnel.pranor.net:8443/ws/connect --subdomain myapp

Multi-port Config File

# tunnel.yaml
relay: "ws://tunnel.pranor.net:8443/ws/connect"
token: "my-auth-token"
tunnels:
  - port: "3000"
    subdomain: "frontend"
  - port: "8080"
    subdomain: "api"
  - port: "5432"
    subdomain: "db-admin"
pranor-tunnel client --config tunnel.yaml

Configuration

Server Environment Variables

VariableDefaultDescription
PRANOR_TUNNEL_ADDR:8443Server listen address
PRANOR_TUNNEL_DOMAINlocalhostBase domain for subdomains
PRANOR_TUNNEL_JWT_SECRETJWT signing secret for auth gating
PRANOR_TUNNEL_MAX_RING_BUFFER100Max captured requests per tunnel
PRANOR_TUNNEL_OTEL_ENDPOINTOpenTelemetry collector URL
PRANOR_TUNNEL_TLS_CERTTLS certificate path
PRANOR_TUNNEL_TLS_KEYTLS key path

Client Environment Variables

VariableDefaultDescription
PRANOR_TUNNEL_RELAYws://localhost:8443/ws/connectRelay WebSocket URL
PRANOR_TUNNEL_TOKENAuthentication token

YAML Config (tunnel.yaml)

# Server config
addr: ":8443"
domain: "pranor.net"
jwt_secret: "my-secret"
max_ring_buffer: 100
tls_cert: "/certs/tunnel.crt"
tls_key: "/certs/tunnel.key"
otel_endpoint: "http://pranor-trace:8090"

CLI Flags (Server)

FlagDefaultDescription
--port, -p8443Listen port
--domain, -dlocalhostBase domain for subdomains

CLI Flags (Client)

FlagDefaultDescription
--relay, -rws://localhost:8443/ws/connectRelay WebSocket URL
--subdomain, -s(auto-generated)Requested subdomain
--custom-domain, -cCustom domain mapping
--token, -tAuthentication token
--inspect-port, -i4040Local inspection web UI port
--share-auth, -aBasic auth to protect public tunnel
--configPath to YAML config file

API Reference

Base URL: http://localhost:8443

POST /api/v1/tunnels

Create a new tunnel (server-side).

Request:

{
  "subdomain": "myapp",
  "target": "localhost:3000",
  "auth_required": true
}

Response (201):

{
  "id": "tun-abc-123",
  "url": "https://myapp.pranor.net",
  "status": "active",
  "created_at": "2026-08-01T10:00:00Z"
}

GET /api/v1/tunnels/{id}/requests

Browse captured requests from ring buffer.

Response (200):

{
  "requests": [
    {
      "id": "req-001",
      "method": "POST",
      "path": "/webhooks",
      "status": 200,
      "latency_ms": 43,
      "timestamp": "2026-08-01T10:01:00Z"
    }
  ]
}

POST /api/v1/tunnels/{id}/replay/

Replay a captured request to the local service.

Response (200):

{
  "status": "replayed",
  "response_status": 200,
  "latency_ms": 38
}

POST /api/v1/tunnels/{id}/share

Generate a shareable URL with expiry.

Request:

{
  "expires_in": "1h",
  "one_time": false
}

Response (200):

{
  "url": "https://myapp.pranor.net?token=xyz789",
  "expires_at": "2026-08-01T11:00:00Z"
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-tunnel","version":"0.1.0"}

GET /readyz

Readiness probe.

{"status":"UP","service":"pranor-tunnel","version":"0.1.0"}

Security

Authentication

  • JWT auth gating: Set PRANOR_TUNNEL_JWT_SECRET to require valid JWT for tunnel connections
  • API key: Pass a static token via --token flag or Authorization: Bearer <token> header
  • Basic auth protection: Use --share-auth usr:pwd to add HTTP Basic Auth to the public tunnel URL

Shareable URLs

  • Time-limited URLs with configurable expiry
  • One-time access tokens that invalidate after first use
  • Shareable links include embedded auth tokens

TLS

Configure TLS for encrypted public-facing connections:

  • Set PRANOR_TUNNEL_TLS_CERT and PRANOR_TUNNEL_TLS_KEY
  • Wildcard certificate recommended for *.pranor.net

DNS Configuration

Configure a wildcard DNS record: *.pranor.net → tunnel-server-ip


Observability

Prometheus Metrics

MetricTypeDescription
pranor_tunnel_active_connectionsGaugeActive WebSocket tunnel connections
pranor_tunnel_requests_proxied_totalCounterTotal requests forwarded
pranor_tunnel_request_latency_msHistogramEnd-to-end proxy latency
pranor_tunnel_reconnections_totalCounterClient reconnection events
pranor_tunnel_ring_buffer_sizeGaugeCaptured requests in buffer

OpenTelemetry Tracing

Tunnel propagates traceparent and tracestate headers through the tunnel. Additionally emits:

  • tunnel.proxy — request proxy span
  • tunnel.replay — request replay span
  • tunnel.connect — WebSocket connection establishment

Logging

Real-time request log in terminal client:

[2026-08-01 11:42:00] POST /webhook/payment    200  43ms
[2026-08-01 11:42:01] GET  /api/orders/123     200  12ms
[2026-08-01 11:42:03] POST /webhook/payment    500  89ms  ← error

Enterprise Edition

FeatureOSSEE
Subdomain-based routing
WebSocket multiplexing
Request inspection & replay
JWT / API key auth gating
Shareable URLs with expiry
Git branch auto-subdomain
Multi-port tunneling (config file)
Persistent reconnect with backoff
WireGuard end-to-end encryption
Custom domain mapping
Team tunnel sharing (RBAC)
Rate limiting per tunnel
Request throttling

Operational Runbook

Client cannot connect to relay

  1. Verify relay URL is correct (--relay ws://...)
  2. Check if JWT token is required and valid
  3. Verify network allows WebSocket connections (port 8443)
  4. Check if firewall/proxy is stripping Upgrade: websocket headers
  5. Try with explicit --subdomain to rule out auto-generation issues

Tunnel URL returning 502

  1. Verify local service is running on the specified port
  2. Check client terminal for connection errors
  3. Verify WebSocket connection is active (not reconnecting)
  4. Check ring buffer for request/response details
  5. Review local service logs for errors

Requests not appearing in inspection buffer

  1. Check PRANOR_TUNNEL_MAX_RING_BUFFER isn't set to 0
  2. Verify inspection port is accessible (default: 4040)
  3. Old requests may have been evicted (buffer is fixed-size ring)
  4. Ensure the request went through the tunnel (not direct)

Reconnection loop (client keeps disconnecting)

  1. Check server logs for auth rejection
  2. Verify token hasn't expired
  3. Check network stability between client and relay
  4. Review reconnection backoff settings (max retries, max delay)
  5. If the server restarted, subdomain may have been reassigned

Pranor Hub — Package Registry & Artifact Store

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/hub
Default Port: 8088
License: AGPL-3.0 (OSS) / Enterprise License (EE with OCI backend & Air-gapped Mirror)


Overview

Pranor Hub is the lightweight, S3-backed package registry and artifact store for the Pranor ecosystem. It provides package publishing, semver resolution, dependency graph analysis, Cosign supply-chain verification, JWT-authenticated publishing, and a built-in landing dashboard for browsing packages.

Pranor Hub can run as:

  • A standalone binary with S3-compatible storage backend
  • An integrated module within the Pranor ecosystem with Pranor Vault storage, Auth RBAC, and OCI container image support

Key Features

FeatureDescription
S3 / Pranor Vault BackendPackages stored as tarballs in S3-compatible storage
Semver ResolutionSemantic versioning with dependency tree resolution
Cosign VerificationSigstore supply-chain signature verification on publish
JWT AuthorizationToken-based authentication for package publishing
Dependency GraphResolve and visualize full dependency trees
Package SearchFull-text search across package names and metadata
Version HistoryBrowse all published versions per package
Landing DashboardBuilt-in web UI displaying packages, sizes, and versions
pranor.toml ManifestsStandard manifest format for package metadata
OCI BackendStore and distribute packages as OCI artifacts

Architecture

graph TD

    subgraph PackageClients ["🌐 CLI and Package Registry API"]
        CLI["pranor-cli Package Manager"]
        PublishAPI["REST Package Publishing API"]
        RegistryDash["Package Registry Landing UI"]
    end

    subgraph RegistryCore ["⚡ Package Resolver and Security Engine"]
        ManifestParser["pranor.toml Manifest Inspector"]
        DepResolver["Dependency Graph Resolver Engine"]
        CosignVerifier["Cosign / Sigstore Supply-Chain Verification"]
        JWTAuth["JWT Signature and Publisher Verifier"]
    end

    subgraph StorageLayer ["💾 S3 and Vault Package Store"]
        VaultStore["Pranor Vault S3 Bucket Tarball Storage"]
        ColdArchive["Air-Gapped Private Package Mirror"]
    end

    CLI --> ManifestParser
    PublishAPI --> ManifestParser
    RegistryDash --> ManifestParser
    ManifestParser --> DepResolver
    DepResolver --> CosignVerifier
    CosignVerifier --> JWTAuth
    JWTAuth --> VaultStore
    VaultStore -.-> ColdArchive

Package Publish & Dependency Resolution Sequence Flow

sequenceDiagram
    autonumber
    participant Developer as Module Developer
    participant Hub as Pranor Hub Registry
    participant Auth as Pranor Auth / Cosign
    participant Resolver as Dependency Tree Resolver
    participant Vault as Pranor Vault S3

    Developer->>Hub: POST /publish (Package Tarball + pranor.toml)
    Hub->>Auth: Verify JWT Token & Cosign Supply-Chain Signature
    Auth-->>Hub: Publisher Identity & Cryptographic Proof Verified
    Hub->>Resolver: Parse Manifest Dependencies & Resolve DAG Tree
    Resolver-->>Hub: Dependency Graph Validated (No Conflicts)
    Hub->>Vault: Store Package Tarball (packages/foo-1.2.0.tar.gz)
    Vault-->>Hub: S3 Blob Persisted
    Hub-->>Developer: Package Published Successfully

Ecosystem Cross-Module Integration

Pranor Hub acts as the official artifact and WebAssembly module registry for the Pranor platform:

  • Pranor Deploy: Pulls signed WebAssembly security modules, OCI container images, and deployment manifests during canary rollouts.
  • Pranor Gate: Downloads compiled WASM dynamic policy plugins published to Hub repositories.
  • Pranor Vault: Serves as the high-availability S3 storage backend for all published package tarballs and signatures.
  • Pranor Auth: Enforces RBAC permissions for organization-scoped package publishing and team access control.

Installation & Deployment

Binary

cd pranor/hub
go build -o pranor-hub .
./pranor-hub --addr :8088 --s3-endpoint http://localhost:9000

Docker

docker run -p 8088:8088 ghcr.io/vyuvaraj/pranor-hub:latest

With Pranor Vault Storage

./pranor-hub --addr :8088 \
  --s3-endpoint http://pranor-vault:7070 \
  --s3-access-key admin \
  --s3-secret-key admin123

As Part of Pranor Ecosystem

When running under the Pranor platform, Hub integrates automatically with Vault (storage), Auth (RBAC), Deploy (artifact pull), and Gate (WASM module distribution).


Configuration

Environment Variables

VariableDefaultDescription
PORT8088HTTP server port
PRANOR_STORE_ENDPOINThttp://localhost:9000Pranor Vault or external S3 URL
PRANOR_STORE_ACCESS_KEYadminS3 access key
PRANOR_STORE_SECRET_KEYadmin123S3 secret key
PRANOR_JWT_SECRETJWT secret for publish authentication (disabled if unset)
PRANOR_HUB_OTEL_ENDPOINTOpenTelemetry collector URL

YAML Config (hub.yaml)

port: "8088"
store_endpoint: "http://pranor-vault:7070"
store_access_key: "admin"
store_secret_key: "admin123"
jwt_secret: "my-signing-secret"
otel_endpoint: "http://pranor-trace:8090"

CLI Flags

FlagDefaultDescription
--addr:8088HTTP listen address
--s3-endpointhttp://localhost:9000S3-compatible storage endpoint

API Reference

Base URL: http://localhost:8088
API Version: /api/v1/ (recommended) or /api/ (legacy)

POST /api/v1/publish

Publish a package tarball.

Headers:

  • Authorization: Bearer <jwt-token> (required if PRANOR_JWT_SECRET is set)
  • Content-Type: multipart/form-data

Request: Multipart upload with .tar.gz file containing pranor.toml manifest.

Response (201):

{
  "status": "published",
  "package": "my-module",
  "version": "1.2.0",
  "checksum": "sha256:abc123..."
}

GET /api/v1/packages

List all packages in the registry.

Response (200):

{
  "packages": [
    { "name": "my-module", "latest_version": "1.2.0", "published_at": "2026-08-01T10:00:00Z" },
    { "name": "utils-lib", "latest_version": "0.5.3", "published_at": "2026-07-28T14:30:00Z" }
  ]
}

GET /api/v1/packages/{name}/versions

List all versions of a package.

Response (200):

{
  "name": "my-module",
  "versions": ["1.0.0", "1.1.0", "1.2.0"]
}

GET /api/v1/packages/{name}/deps

Resolve dependency tree for the latest version.

Response (200):

{
  "package": "my-module",
  "version": "1.2.0",
  "dependencies": [
    { "name": "utils-lib", "version": ">=0.5.0", "resolved": "0.5.3" },
    { "name": "crypto-core", "version": "^2.0.0", "resolved": "2.1.1" }
  ]
}

GET /api/v1/packages/search?q=

Search packages by name or metadata.

Response (200):

{
  "results": [
    { "name": "my-module", "description": "Core utility module", "latest_version": "1.2.0" }
  ]
}

GET /packages/{name}.tar.gz

Download the latest version tarball.

GET /packages/{name}/{version}/{name}-{version}.tar.gz

Download a specific version tarball.


GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-hub","version":"1.0.0"}

Security

Standalone Mode

When PRANOR_JWT_SECRET is unset, publishing is unauthenticated. Set the JWT secret to require token authentication for all publish operations.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. JWT Auth — validates Bearer tokens against Pranor Auth
  2. Cosign Verification — supply-chain signature validation on published artifacts
  3. RBAC — organization-scoped publish permissions via Pranor Auth roles
  4. Artifact Signing — all published packages signed with Sigstore transparency log

Package Integrity

  • Packages are checksummed (SHA-256) on upload
  • Cosign signatures verify publisher identity and build provenance
  • Immutable versions — once published, a version cannot be overwritten

Observability

Prometheus Metrics

MetricTypeDescription
pranor_hub_packages_totalGaugeTotal registered packages
pranor_hub_publishes_totalCounterPublish events (labeled by status)
pranor_hub_downloads_totalCounterPackage downloads
pranor_hub_resolution_duration_msHistogramDependency resolution time
pranor_hub_storage_bytesGaugeTotal storage used

OpenTelemetry Tracing

Hub emits spans for:

  • hub.publish — package publication
  • hub.resolve — dependency tree resolution
  • hub.download — package download
  • hub.verify — Cosign signature verification

Logging

Structured JSON logs with fields: level, timestamp, trace_id, package, version, action, publisher.


Enterprise Edition

FeatureOSSEE
S3-backed package storage
Semver dependency resolution
JWT publish authentication
Package search
Landing dashboard UI
Cosign supply-chain verification
OCI container image backend
Air-gapped private package mirror
Organization-scoped RBAC publishing
Vulnerability scanning on publish
Package deprecation & yanking

Operational Runbook

Package publish failing with auth error

  1. Verify PRANOR_JWT_SECRET is configured correctly
  2. Check JWT token validity and expiration
  3. Ensure the publishing user has the correct RBAC role
  4. If using Cosign, verify the signing key is available

Dependency resolution failing

  1. Check if all declared dependencies exist in the registry
  2. Review version constraints in pranor.toml for conflicts
  3. Check for circular dependency chains
  4. Monitor pranor_hub_resolution_duration_ms for timeout issues

S3 storage backend unavailable

  1. Verify PRANOR_STORE_ENDPOINT connectivity
  2. Check S3 access key/secret key credentials
  3. Verify the target bucket exists and has correct permissions
  4. If using Pranor Vault, check Vault health endpoint

Slow package downloads

  1. Check S3 backend latency and throughput
  2. Review pranor_hub_downloads_total for traffic spikes
  3. Consider using a CDN or regional cache in front of Hub
  4. Verify network bandwidth between Hub and storage backend

Pranor Lock — Distributed Lock Manager

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/lock
Default Port: 8089
License: AGPL-3.0 (OSS) / Enterprise License (EE with Raft consensus)


Overview

Pranor Lock is a lightweight, production-grade distributed lock manager that provides lease-based mutual exclusion for coordinating access to shared resources across services. It supports exclusive and shared lock modes, priority-based wait queues, deadlock detection, fencing tokens, reentrant locks, real-time event streaming, and client heartbeat monitoring.

Pranor Lock can run as:

  • A standalone binary with zero external dependencies (memory or file-backed)
  • An integrated module within the Pranor ecosystem with mTLS, RBAC, and OTel tracing

Table of Contents


Key Features

FeatureDescription
Lease-based TTL locksEvery lock has an expiry. No permanent deadlocks from crashed clients.
Exclusive & Shared modesRead-write lock semantics. Multiple shared readers, single exclusive writer.
Fencing tokensMonotonically increasing tokens prevent stale clients from corrupting state.
Reentrant locksSame owner+client_id can re-acquire without blocking. Reentrancy count tracked.
Priority wait queuesWaiters are served in priority order. Higher priority clients jump the queue.
Deadlock detectionCycle detection in the wait-for graph prevents distributed deadlocks.
Blocking acquireOptional wait_ms parameter blocks until lock is available or timeout.
Real-time SSE eventsSubscribe to lock lifecycle events (released, expired) via Server-Sent Events.
Client heartbeatsDead client detection — locks auto-release when heartbeats stop.
File persistenceOptional file-backed storage survives process restarts.
Zombie lock alertsLogs a warning when locks are held longer than 5 seconds.
Prometheus metricsActive locks, waiter count, deadlock counter.

Architecture

graph TD
    classDef client fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#fff;
    classDef engine fill:#0f172a,stroke:#0d9488,stroke-width:2px,color:#fff;
    classDef storage fill:#1e1b4b,stroke:#6366f1,stroke-width:2px,color:#fff;
    classDef monitor fill:#1e293b,stroke:#64748b,stroke-width:1px,color:#fff;

    subgraph API ["🌐 Access & Stream Interface"]
        REST["HTTP REST API<br/><i>(Acquire / Release / Renew)</i>"] :::client
        Auth["Auth & Security Layer<br/><i>(mTLS / JWT / API Key)</i>"] :::client
        SSE["SSE Pub/Sub Stream<br/><i>(Real-Time Lock Events)</i>"] :::client
    end

    subgraph Core ["⚡ Core Distributed Lock Engine"]
        Reentrant["Reentrancy & Lease Engine<br/><i>(Exclusive & Shared Modes)</i>"] :::engine
        Fencing["Monotonic Fencing Token Generator"] :::engine
        Deadlock["Deadlock Cycle Detector<br/><i>(Wait-For Graph Evaluator)</i>"] :::engine
        Priority["Priority Wait Queue Manager"] :::engine
    end

    subgraph Backend ["💾 Persisted Lock Store"]
        MemStore["In-Memory Lock Store<br/><i>(Zero-Allocation)</i>"] :::storage
        FileStore["File-Backed Lease Store"] :::storage
        RaftStore["Raft Consensus Engine<br/><i>(Enterprise EE)</i>"] :::storage
    end

    subgraph Background ["⏱️ Background Monitors"]
        TTLCleaner["TTL Lease Evictor<br/><i>(500ms Sweep)</i>"] :::monitor
        Heartbeat["Client Heartbeat Monitor"] :::monitor
    end

    REST --> Auth
    Auth --> Reentrant
    Reentrant --> Fencing
    Fencing --> Deadlock
    Deadlock --> Priority
    Priority --> MemStore
    Priority --> FileStore
    Priority --> RaftStore
    TTLCleaner -.-> MemStore
    Heartbeat -.-> Reentrant
    Reentrant --> SSE

Lease Acquisition & Fencing Token Sequence Flow

sequenceDiagram
    autonumber
    participant Worker as Client / Worker Instance
    participant Lock as Pranor Lock Manager
    participant Deadlock as Deadlock Cycle Evaluator
    participant Storage as Raft / File Lock Store
    participant DB as Target Storage / Database

    Worker->>Lock: POST /api/locks/acquire (key="orders/process", duration_ms=10000)
    Lock->>Deadlock: Evaluate Wait-For Graph (Cycle Detection)
    Deadlock-->>Lock: Cycle Free (No Deadlock)
    Lock->>Storage: Issue Monotonic Fencing Token (Token=1042)
    Storage-->>Lock: Lock State Persisted & Lease TTL Set
    Lock-->>Worker: Lock Granted (Fencing Token = 1042)
    Worker->>DB: Write Record with Fencing Token = 1042
    DB-->>Worker: Write Validated (Token 1042 > Previous 1041)
    Worker->>Lock: POST /api/locks/renew (Heartbeat Keepalive)
    Lock-->>Worker: TTL Extended (10,000ms refreshed)
    Worker->>Lock: POST /api/locks/release (Fencing Token = 1042)
    Lock-->>Worker: Lock Released & Next Waiter Notified via SSE

Ecosystem Cross-Module Integration

Pranor Lock provides distributed synchronization across all core ecosystem components:

  • Pranor Chrono: Uses exclusive fencing token locks to ensure distributed cron jobs trigger on exactly one node during multi-replica deployments.
  • Pranor Flow: Manages saga execution state locks, preventing concurrent workers from processing duplicate saga compensation steps.
  • Pranor Pool: Coordinates online database DDL migrations, ensuring zero-downtime schema changes are executed by a single leader node.
  • Pranor Auth: Enforces single-session user login restrictions across clusters when configured in strict single-tenant security mode.
  • Pranor Trace: Emits lock contention metrics, wait-queue durations, and deadlock cycle detections directly to OpenTelemetry traces.

Installation & Deployment

Binary

cd pranor/lock
go build -o pranor-lock .
./pranor-lock --port 8089

Docker

docker run -p 8089:8089 ghcr.io/vyuvaraj/pranor-lock:latest

With Config File

./pranor-lock --config lock.yaml

As Part of Pranor Ecosystem

When running under the Pranor platform, Lock integrates automatically with Auth (JWT/mTLS), Trace (OTel spans), and Console (dashboard visibility).


Configuration

YAML Config (lock.yaml)

port: "8089"
backend: "file"          # "memory" or "file"
file_path: "leases.json" # Only used when backend is "file"
api_key: "your-secret"   # Optional: standalone API key auth
tls_cert: ""             # Path to TLS certificate
tls_key: ""              # Path to TLS private key
client_ca: ""            # Path to CA cert for mTLS client verification

Environment Variables

VariableDefaultDescription
PRANOR_LOCK_API_KEYAPI key for standalone auth
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL

CLI Flags

FlagDefaultDescription
--port8089HTTP listen port
--configPath to YAML config file

API Reference

Base URL: http://localhost:8089
API Version: /api/v1/ (recommended) or /api/ (legacy)

POST /api/locks/acquire

Acquire a distributed lock.

Request:

{
  "key": "orders/processing",
  "owner": "worker-1",
  "client_id": "instance-abc",
  "duration_ms": 30000,
  "wait_ms": 5000,
  "mode": "exclusive",
  "priority": 10
}
FieldTypeRequiredDescription
keystringLock identifier (namespace/resource)
ownerstringWho is requesting the lock
client_idstringInstance identifier (enables reentrancy)
duration_msintLease TTL in ms (default: 10000)
wait_msintBlock until lock available (0 = fail immediately)
modestring"exclusive" (default) or "shared"
priorityintHigher = served first in wait queue

Success Response (200):

{
  "status": "success",
  "lock": {
    "key": "orders/processing",
    "owner": "worker-1",
    "client_id": "instance-abc",
    "reentrancy_count": 1,
    "fencing_token": 42,
    "expires_at": "2026-08-01T10:00:30Z",
    "mode": "exclusive",
    "acquired_at": "2026-08-01T10:00:00Z"
  }
}

Conflict Response (409):

{
  "status": "failed",
  "message": "lock conflict: key \"orders/processing\" is held in mode \"exclusive\""
}

Deadlock Response (409):

{
  "status": "failed",
  "message": "deadlock detected: cycle in lock wait queue"
}

POST /api/locks/release

Release a held lock.

Request:

{
  "key": "orders/processing",
  "owner": "worker-1",
  "fencing_token": 42
}
FieldTypeRequiredDescription
keystringLock to release
ownerstringMust match the lock holder
fencing_tokenint64If provided, must match (prevents stale releases)

Response (200):

{
  "status": "success",
  "message": "Lock released successfully"
}

POST /api/locks/renew

Extend the lease of an active lock.

Request:

{
  "key": "orders/processing",
  "owner": "worker-1",
  "fencing_token": 42,
  "duration_ms": 30000
}

Response (200):

{
  "status": "success",
  "message": "Lock lease renewed successfully"
}

POST /api/locks/heartbeat

Ping to indicate client is alive. If heartbeats stop for >5s, all locks held by that client are auto-released.

Request:

{
  "client_id": "instance-abc"
}

Response (200):

{
  "status": "success"
}

GET /api/locks/observability

List all active locks with their waiters.

Response (200):

[
  {
    "key": "orders/processing",
    "owner": "worker-1",
    "fencing_token": 42,
    "expires_at": "2026-08-01T10:00:30Z",
    "waiters": ["worker-2", "worker-3"]
  }
]

GET /api/locks/metrics

Prometheus-compatible metrics endpoint.

Response (200 text/plain):

# HELP pranor_lock_active_locks Number of active locks currently held
# TYPE pranor_lock_active_locks gauge
pranor_lock_active_locks 3

# HELP pranor_lock_waiters_count Total number of clients waiting for locks
# TYPE pranor_lock_waiters_count gauge
pranor_lock_waiters_count 1

# HELP pranor_lock_deadlocks_total Total number of deadlocks detected
# TYPE pranor_lock_deadlocks_total counter
pranor_lock_deadlocks_total 0

GET /api/locks/subscribe

Server-Sent Events stream for real-time lock lifecycle events.

Response (text/event-stream):

: keep-alive

data: {"key":"orders/processing","action":"released"}

data: {"key":"inventory/update","action":"expired"}

Events:

  • released — lock explicitly released by owner
  • expired — lock TTL expired or client heartbeat timed out

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor","version":"1.0.0"}

GET /readyz

Readiness probe. Same format as healthz.


Lock Semantics

Exclusive Mode (Default)

Only one owner can hold the lock. All other acquire attempts either fail immediately or block (if wait_ms > 0).

Worker-1: acquire("key", exclusive) → ✓ granted
Worker-2: acquire("key", exclusive) → ✗ conflict (or blocks)
Worker-1: release("key") → ✓
Worker-2: (if waiting) → ✓ auto-granted

Shared Mode

Multiple owners can hold a shared lock simultaneously. Exclusive requests block until all shared locks are released.

Reader-1: acquire("key", shared) → ✓ granted
Reader-2: acquire("key", shared) → ✓ granted (concurrent)
Writer-1: acquire("key", exclusive) → ✗ blocks (shared locks active)
Reader-1: release → ✓
Reader-2: release → ✓
Writer-1: → ✓ auto-granted (all readers done)

Reentrancy

If the same owner + client_id acquires a lock they already hold, the reentrancy count increments. The lock is only fully released when the count reaches zero.

Worker-1: acquire("key") → reentrancy_count: 1
Worker-1: acquire("key") → reentrancy_count: 2 (no block)
Worker-1: release("key") → reentrancy_count: 1 (still held)
Worker-1: release("key") → reentrancy_count: 0 (fully released)

Fencing Tokens

Every lock acquisition generates a monotonically increasing fencing token. Downstream systems should validate the token to reject operations from stale lock holders:

Worker-1: acquire → fencing_token: 41
Worker-1: crashes, lock expires
Worker-2: acquire → fencing_token: 42
Worker-1: wakes up, tries write with token 41 → REJECTED
Worker-2: writes with token 42 → ACCEPTED

Deadlock Detection

When wait_ms > 0, the engine checks for cycles in the wait-for graph before queueing:

Worker-A holds Lock-X, waiting for Lock-Y
Worker-B holds Lock-Y, waiting for Lock-X
→ Cycle detected → "deadlock detected" error returned immediately

Priority Queue

When multiple waiters exist for a lock, they are served in descending priority order (higher number = higher priority):

Worker-A (priority: 1) waiting
Worker-B (priority: 10) waiting
Worker-C (priority: 5) waiting
Lock released → Worker-B gets it first

Storage Backends

InMemory (Default)

  • Zero configuration
  • All state in memory
  • Lost on restart
  • Best for: development, testing, ephemeral workloads

File-Backed

  • Persists leases to JSON file (leases.json)
  • Survives process restarts
  • Loads non-expired leases on startup
  • Best for: single-node production, edge deployments
backend: "file"
file_path: "/var/pranor/lock/leases.json"

Raft Consensus (Enterprise)

  • Multi-node replication
  • Strong consistency
  • Automatic leader election
  • Best for: production HA deployments

Security

Standalone Mode (API Key)

Set PRANOR_LOCK_API_KEY or configure in YAML. Clients authenticate via:

X-API-Key: your-secret

or:

Authorization: Bearer your-secret

Health endpoints (/healthz, /readyz) are unauthenticated.

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem (no API key configured), the full middleware chain activates:

  1. OTel Tracing — every request gets a span
  2. Rate Limiting — per-client request throttling
  3. CORS — cross-origin request handling
  4. Max Body Size — 10MB request body limit
  5. JWT Auth — validates Bearer tokens against Pranor Auth
  6. Tenant Isolation — multi-tenant namespace enforcement

mTLS

Enable mutual TLS for service-to-service authentication:

tls_cert: "/certs/lock.crt"
tls_key: "/certs/lock.key"
client_ca: "/certs/ca.crt"

Observability

Metrics

MetricTypeDescription
pranor_lock_active_locksGaugeCurrently held locks
pranor_lock_waiters_countGaugeClients waiting in queues
pranor_lock_deadlocks_totalCounterTotal deadlocks detected

Real-time Events (SSE)

Connect to /api/locks/subscribe for real-time lock state changes. Useful for building dashboards or triggering downstream workflows.

Zombie Lock Alerts

Locks held longer than 5 seconds generate a log warning:

[Warning] Zombie Lock Alert: Lock on "orders/processing" was held for 12.3s

Heartbeat Monitoring

If a client stops sending heartbeats for >5 seconds, all its locks are automatically released and an expired event is broadcast.


Client Libraries

Go (via Pranor Core)

import "github.com/vyuvaraj/pranor/core"

client := core.NewLockClient("http://localhost:8089", "your-api-key")
lock, err := client.Acquire("orders/processing", "worker-1", 30*time.Second)
defer client.Release(lock)

cURL

# Acquire
curl -X POST http://localhost:8089/api/v1/locks/acquire \
  -H "X-API-Key: your-secret" \
  -H "Content-Type: application/json" \
  -d '{"key":"my-resource","owner":"worker-1","duration_ms":30000}'

# Renew
curl -X POST http://localhost:8089/api/v1/locks/renew \
  -H "X-API-Key: your-secret" \
  -d '{"key":"my-resource","owner":"worker-1","duration_ms":30000}'

# Release
curl -X POST http://localhost:8089/api/v1/locks/release \
  -H "X-API-Key: your-secret" \
  -d '{"key":"my-resource","owner":"worker-1"}'

Pranor CLI

pranor lock acquire --key orders/processing --owner worker-1 --ttl 30s
pranor lock renew --key orders/processing --owner worker-1 --ttl 30s
pranor lock release --key orders/processing --owner worker-1
pranor lock list

Enterprise Edition

FeatureOSSEE
InMemory backend
File-backed persistence
API Key auth
Shared/Exclusive modes
Deadlock detection
Priority queues
SSE event stream
Client heartbeats
Raft consensus replication
Multi-node HA
Automatic failover

Operational Runbook

Lock stuck / not releasing

  1. Check /api/locks/observability for the lock state
  2. Verify the owner's heartbeat is active
  3. If owner is dead, wait for TTL expiry (or heartbeat timeout)
  4. As last resort, release manually via API with matching owner

High waiter count

  1. Check /api/locks/metrics for pranor_lock_waiters_count
  2. Identify hot keys via /api/locks/observability
  3. Consider:
    • Increasing lock TTL (reduce churn)
    • Switching to shared mode if readers dominate
    • Sharding the resource key

Deadlocks increasing

  1. Monitor pranor_lock_deadlocks_total
  2. Review client code for multi-key acquisition patterns
  3. Enforce consistent lock ordering across all services
  4. Consider using shorter TTLs so deadlocked chains resolve via expiry

Process restart (file backend)

On restart, the file store loads all non-expired leases from leases.json. Locks that expired during downtime are automatically cleaned up.


Versioning & Compatibility

  • API is versioned at /api/v1/
  • Legacy /api/ paths continue to work (internally rewritten to v1)
  • Fencing tokens are monotonically increasing and never reset (even across restarts with file backend)

Pranor Secret — Secret & Credential Management

Version: 1.0.0
Module Path: github.com/vyuvaraj/pranor/secret
Default Port: 8091
License: AGPL-3.0 (OSS) / Enterprise License (EE with HSM & Multi-Cloud KMS)


Overview

Pranor Secret is the centralized secrets, credentials, and configuration protection engine for the Pranor ecosystem. It provides tenant-isolated secret storage encrypted at rest using AES-256-GCM, Shamir secret splitting, dynamic injection into services, automatic rotation policies, and leak detection scanning.

Pranor Secret can run as:

  • A standalone binary with local encrypted file storage and a master key
  • An integrated module within the Pranor ecosystem with Pranor Core middleware, multi-tenant isolation, HSM integration, and dynamic rotation

Key Features

FeatureDescription
AES-256-GCM EncryptionAll secrets encrypted at rest with envelope encryption
Tenant IsolationSecrets organized per tenant with namespace enforcement
Shamir SplittingMaster key split across multiple key holders (2-of-3 quorum)
Dynamic InjectionServices retrieve secrets at runtime via API
Automatic RotationConfigurable TTL-based rotation with zero-downtime rollover
Leak DetectionScan codebases and logs for accidentally exposed secrets
KMS FederationMulti-cloud KMS sync (AWS KMS, GCP KMS, Azure Key Vault)
FIPS 140-3 HSMHardware security module adapter for key operations
Encrypted File StoreLocal persistence in encrypted secrets.enc file
Vault BackendOptional Pranor Vault encrypted key store

Architecture

graph TD

    subgraph Interface ["🌐 Secrets Access Protocol"]
        API["REST Secret Engine API"]
        CLI["secretctl Secret CLI"]
    end

    subgraph Core ["⚡ Cryptographic Key and Secret Engine"]
        AESGCM["AES-256-GCM Envelope Encryption Engine"]
        FIPS140["FIPS 140-3 Cryptographic HSM Adapter"]
        KMSFed["Multi-Cloud KMS Federation Sync"]
        MPC["Zero-Knowledge MPC Key Splitter"]
    end

    subgraph Persistence ["💾 Encrypted Secret Storage"]
        FileStore["Encrypted Local Store"]
        VaultStore["Pranor Vault Encrypted Key Store"]
    end

    API --> AESGCM
    CLI --> AESGCM
    AESGCM --> FIPS140
    FIPS140 --> KMSFed
    KMSFed --> MPC
    MPC --> FileStore
    MPC --> VaultStore

Cryptographic Secret Envelope & Key Unsealing Sequence Flow

sequenceDiagram
    autonumber
    participant App as Microservice / Gateway
    participant Secret as Pranor Secret Engine
    participant HSM as FIPS 140-3 Hardware HSM
    participant KMS as Multi-Cloud KMS Federation
    participant Store as Encrypted Secrets Store

    App->>Secret: GET /api/v1/secrets/database-password (X-Tenant-ID)
    Secret->>HSM: Unseal Envelope Master Key via FIPS 140-3 Module
    HSM->>KMS: Combine MPC Threshold Key Shares (2-of-3 quorum)
    KMS-->>Secret: Reconstructed Decryption Key
    Secret->>Store: Read Ciphertext Payload from secrets.enc
    Store-->>Secret: Encrypted Data Ciphertext + AES-GCM Nonce
    Secret->>Secret: Decrypt Payload in Memory-Isolated Buffer
    Secret-->>App: Plaintext Secret Value + Dynamic Rotation TTL

Ecosystem Cross-Module Integration

Pranor Secret provides master key management and secret protection across all Pranor modules:

  • Pranor Gate: Dynamically provisions and auto-rotates TLS server certificates and client mTLS credentials without restarting proxy instances.
  • Pranor Auth: Secures private RSA/ECDSA JWT signing keys, WebAuthn passkey seeds, and OIDC client secrets.
  • Pranor Vault: Stores client-side envelope encryption keys and S3 cloud storage access credentials.
  • Pranor Console: Renders the visual Secret Management Webview, unsealing vaults and inspecting rotation policies securely.

Installation & Deployment

Binary

cd pranor/secret
go build -o pranor-secret .
./pranor-secret --port 8091 --file secrets.enc

Docker

docker run -p 8091:8091 \
  -e PRANOR_SECRET_MASTER_KEY="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" \
  -v secret-data:/data \
  ghcr.io/vyuvaraj/pranor-secret:latest

With Master Key

export PRANOR_SECRET_MASTER_KEY="000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
./pranor-secret --port 8091 --file /data/secrets.enc

As Part of Pranor Ecosystem

When running under the Pranor platform, Secret integrates automatically with Auth (JWT key storage), Gate (TLS cert rotation), Console (secret management UI), and Core middleware (tenant isolation).


Configuration

Environment Variables

VariableDefaultDescription
PRANOR_SECRET_PORT8091HTTP listener port
PRANOR_SECRET_MASTER_KEY32-byte hex-encoded master encryption key
PRANOR_SECRET_FILEsecrets.encPath to encrypted secrets file
PRANOR_SECRET_ROTATION_INTERVALDefault rotation interval for secrets
PRANOR_SECRET_OTEL_ENDPOINTOpenTelemetry collector URL

YAML Config (secret.yaml)

port: "8091"
master_key: ""              # Set via env var for security
file: "/data/secrets.enc"
rotation_interval: "24h"
otel_endpoint: "http://pranor-trace:8090"

CLI Flags

FlagDefaultDescription
--port8091HTTP listen port
--filesecrets.encEncrypted secrets file path

API Reference

Base URL: http://localhost:8091

POST /api/v1/secrets

Set or update a secret.

Headers:

  • X-Tenant-ID: tenant-a
  • Authorization: Bearer <token>

Request:

{
  "key": "database-password",
  "value": "super-secret-passphrase"
}

Response (201):

{
  "key": "database-password",
  "status": "stored",
  "encrypted": true
}

GET /api/v1/secrets/

Retrieve a secret value.

Headers:

  • X-Tenant-ID: tenant-a
  • Authorization: Bearer <token>

Response (200):

{
  "key": "database-password",
  "value": "super-secret-passphrase"
}

GET /api/v1/secrets

List stored secret keys (values not exposed).

Response (200):

{
  "keys": ["database-password", "api-key-stripe", "jwt-signing-key"]
}

DELETE /api/v1/secrets/

Delete a secret.

Response (200):

{
  "status": "deleted",
  "key": "database-password"
}

GET /healthz

Liveness probe.

{"status":"UP","service":"pranor-secret","version":"1.0.0"}

Security

Standalone Mode

Provide a 32-byte hex-encoded master key via PRANOR_SECRET_MASTER_KEY. If unset, a temporary random key is generated at startup (secrets won't persist across restarts).

Ecosystem Mode (Full Auth Stack)

When running within the Pranor ecosystem:

  1. OTel Tracing — every secret access generates a span
  2. Rate Limiting — per-client request throttling
  3. JWT Auth — validates Bearer tokens against Pranor Auth
  4. Tenant Isolation — secrets scoped per X-Tenant-ID header
  5. Audit Logging — all read/write/delete operations logged

Encryption Details

  • Algorithm: AES-256-GCM (Galois/Counter Mode)
  • Nonce: Unique random nonce per encryption operation
  • Key derivation: Master key used for envelope encryption
  • Memory safety: Plaintext secrets held only in memory-isolated buffers, zeroed after use

Shamir Secret Splitting (EE)

Master key can be split into N shares with M-of-N threshold for unsealing:

  • Default: 2-of-3 quorum required to reconstruct master key
  • Key holders each possess one share
  • No single point of compromise

Observability

Prometheus Metrics

MetricTypeDescription
pranor_secret_reads_totalCounterSecret read operations
pranor_secret_writes_totalCounterSecret write operations
pranor_secret_deletes_totalCounterSecret delete operations
pranor_secret_rotations_totalCounterAutomatic rotation events
pranor_secret_keys_activeGaugeCurrently stored secrets
pranor_secret_decrypt_duration_msHistogramDecryption latency

OpenTelemetry Tracing

Secret emits spans for:

  • secret.read — secret retrieval (key name logged, value never logged)
  • secret.write — secret storage
  • secret.delete — secret deletion
  • secret.rotate — rotation event

Logging

Structured JSON logs with fields: level, timestamp, trace_id, tenant_id, key, action. Secret values are never logged.


Enterprise Edition

FeatureOSSEE
AES-256-GCM encrypted storage
Tenant-isolated secrets
REST API for CRUD
File-backed persistence
Graceful shutdown
Shamir secret splitting (2-of-N quorum)
FIPS 140-3 HSM adapter
Multi-cloud KMS federation (AWS/GCP/Azure)
Automatic rotation with zero-downtime rollover
Leak detection scanner
Dynamic injection into running services
Pranor Vault encrypted backend

Operational Runbook

Cannot decrypt secrets after restart

  1. Verify PRANOR_SECRET_MASTER_KEY is set correctly (same key as when secrets were written)
  2. If no master key was provided initially, secrets used a temporary key and are lost
  3. Check file permissions on secrets.enc
  4. Verify the secrets file isn't corrupted (check file size > 0)

Rotation failing

  1. Check pranor_secret_rotations_total metric for errors
  2. Verify rotation interval configuration
  3. Ensure services consuming rotated secrets are polling for updates
  4. Check OTel spans for secret.rotate errors

High decryption latency

  1. Monitor pranor_secret_decrypt_duration_ms histogram
  2. If using HSM, check HSM connectivity and load
  3. Consider caching decrypted values in-memory with short TTL
  4. Review concurrent access patterns — may need connection pooling to HSM

Suspected secret leak

  1. Enable leak detection scanner (EE feature)
  2. Rotate compromised secrets immediately via API
  3. Audit access logs for unauthorized reads (pranor_secret_reads_total)
  4. Review which services accessed the leaked secret via trace spans
  5. Invalidate downstream tokens/credentials that used the leaked secret

ExecutionContext (core/pkg/execctx)

Package: github.com/vyuvaraj/pranor/core/pkg/execctx
Introduced: Phase 91 (Sprint V2.91.1)


Overview

ExecutionContext is the canonical propagation structure passed through all HTTP routes, WASM plugins, database queries, and background tasks in Pranor v2.x. It unifies identity, policy context, budget circuit breakers, and correlation IDs into a single struct embedding context.Context.

Every request boundary across Gate, Graph, Decision, Flow, Learn, and Tools MUST accept and pass *execctx.ExecutionContext.


Type Definition

type ExecutionContext struct {
    context.Context

    // Identity & Context Propagation
    TenantID      string `json:"tenant_id"`       // mandatory tenant isolation ID
    AgentID       string `json:"agent_id"`        // executing agent ID
    UserID        string `json:"user_id"`         // authenticated user ID
    TraceID       string `json:"trace_id"`        // OTLP trace ID
    RequestID     string `json:"request_id"`      // request correlation ID
    ParentAgentID string `json:"parent_agent_id"` // parent agent ID if spawned in A2A delegation

    // Capability & Policy
    Capabilities  []string          `json:"capabilities"`   // authorized capability IDs
    PolicyContext map[string]string `json:"policy_context"` // arbitrary key-value policy tags

    // Budget Limits & Circuit Breakers
    RiskBudget   float64 `json:"risk_budget"`    // 0.0-1.0 (0.0 = zero risk allowed)
    TokenBudget  int     `json:"token_budget"`   // max LLM tokens allowed
    CostBudgetUS float64 `json:"cost_budget_us"` // max USD cost allowed

    // Metadata
    Metadata  map[string]string `json:"metadata"`
    CreatedAt time.Time         `json:"created_at"`
}

Key Functions & Builders

FunctionDescription
New(ctx, tenantID, agentID, userID)Creates a new ExecutionContext. TenantID is required.
FromHTTP(ctx, r)Extracts ExecutionContext from X-Pranor-* HTTP headers. Fails closed (ErrMissingTenantID) if missing.
ec.WithAgent(agentID)Returns a shallow copy with AgentID set to agentID and ParentAgentID set to old AgentID.
ec.WithCapability(capID)Returns a shallow copy with capID appended to Capabilities.
ec.WithPolicy(key, value)Returns a shallow copy with updated PolicyContext.
ec.WithBudget(risk, tokens, cost)Returns a shallow copy with updated budget limits.
ec.Validate()Returns ErrMissingTenantID if TenantID is empty.
ec.HasCapability(capID)Returns true if capID is in the authorized capabilities list.
ec.InjectHTTP(r)Writes X-Pranor-* headers to an outgoing HTTP request.

Propagation Protocol

HTTP Request (X-Pranor-Tenant-ID, X-Pranor-Agent-ID)
  ↓
Gate (execctx.FromHTTP)
  ↓
Capability Registry (ec.HasCapability)
  ↓
Decision & Graph (ec.RiskBudget, ec.TenantID)
  ↓
Flow & Tools (ec.InjectHTTP for downstream calls)

HTTP Propagation Headers

  • X-Pranor-Tenant-ID: Tenant isolation ID (Required)
  • X-Pranor-Agent-ID: Executing Agent ID
  • X-Pranor-User-ID: Authenticated User ID
  • X-Pranor-Trace-ID: Distributed Trace ID
  • X-Pranor-Request-ID: Correlation Request ID
  • X-Pranor-Parent-Agent-ID: Parent Agent ID for A2A delegation

Capability Registry (core/pkg/capability)

Package: github.com/vyuvaraj/pranor/core/pkg/capability
Introduced: Phase 91 (Sprint V2.91.2)


Overview

Capabilities in Pranor v2.x are first-class governed resources rather than opaque tool names. Each capability defines its schema, risk classification, required permissions, rate limits, blast radius, HITL approval requirements, and protocol binding.

The Capability Registry acts as the single source of truth for tool resolution and authorization before execution at the Gate.


Capability Schema

type RiskClass int

const (
    RiskLow      RiskClass = iota // Read-only, internal state
    RiskMedium                    // Writes to internal state
    RiskHigh                      // External API calls, financial actions
    RiskCritical                  // Destructive ops, PII, payments
)

type Protocol int

const (
    ProtocolMCP   Protocol = iota // Model Context Protocol
    ProtocolGRPC                  // gRPC sidecar
    ProtocolREST                  // HTTP REST API
    ProtocolWASM                  // WASM sandbox via wazero
    ProtocolNative                // Native Go in-process call
)

type Capability struct {
    ID             string           `json:"id"`              // e.g. "pool.query", "notify.send"
    Version        string           `json:"version"`         // semver e.g. "1.0.0"
    Name           string           `json:"name"`
    Description    string           `json:"description"`
    Schema         CapabilitySchema `json:"schema"`          // JSON schema input/output
    Risk           RiskClass        `json:"risk"`            // LOW, MEDIUM, HIGH, CRITICAL
    RequiredPerms  []string         `json:"required_perms"`
    AllowedAgents  []string         `json:"allowed_agents"`  // empty = all allowed
    AllowedTenants []string         `json:"allowed_tenants"` // empty = all allowed
    RateLimit      RateLimit        `json:"rate_limit"`      // reqs/min, burst
    BlastRadius    BlastRadius      `json:"blast_radius"`    // external API, DB writes, notifications
    RequiresHITL   bool             `json:"requires_hitl"`   // requires Human-In-The-Loop approval
    Protocol       Protocol         `json:"protocol"`        // MCP, GRPC, REST, WASM, NATIVE
    Endpoint       string           `json:"endpoint"`        // URI for remote/sidecar calls
}

Registry API

type Registry interface {
    Register(c Capability) error
    Lookup(id string) (Capability, error)
    ListAll() []Capability
    ListByAgent(agentID string) []Capability
    ListByTenant(tenantID string) []Capability
    Authorize(tenantID, agentID, capID string) error
    Unregister(id string) error
}
  • OSS Implementation: InMemoryRegistry (thread-safe sync.RWMutex, wildcard * matching for agent/tenant).
  • EE Implementation: Persistent registry backed by Pranor Vault with cross-datacenter synchronization.

Usage Example

import "github.com/vyuvaraj/pranor/core/pkg/capability"

// Register a capability
capability.Register(capability.Capability{
    ID:          "pool.query",
    Version:     "1.0.0",
    Name:        "Database Query",
    Risk:        capability.RiskLow,
    Protocol:    capability.ProtocolNative,
    BlastRadius: capability.BlastRadius{WritesDB: false},
})

// Authorize before execution
err := capability.Authorize("tenant-acme", "agent-analyst", "pool.query")
if err != nil {
    // Fails closed if unauthorized
}

Agent Identity & Registry (std/agent)

Module Path: github.com/vyuvaraj/pranor/agent
Introduced: Phase 91 (Sprint V2.91.5)


Overview

Pranor Agent (std/agent) elevates AI Agents from opaque scripts to first-class security principals. It provides a declarative AgentSpec registry, active AgentHandle tracking, and a thread-safe runtime state machine.


Runtime State Machine

An agent instance moves through deterministic state transitions:

stateDiagram-v2
    [*] --> IDLE
    IDLE --> RUNNING: Spawn
    RUNNING --> WAITING_TOOL: Tool Call
    WAITING_TOOL --> RUNNING: Tool Result
    RUNNING --> WAITING_HITL: Approval Needed
    WAITING_HITL --> RUNNING: Approved
    RUNNING --> SUSPENDED: Suspend
    SUSPENDED --> RUNNING: Resume
    RUNNING --> DONE: Complete
    RUNNING --> FAILED: Error
    DONE --> [*]
    FAILED --> [*]

Data Structures

type AgentState int

const (
    StateIdle AgentState = iota
    StateRunning
    StateWaitingTool
    StateWaitingHITL
    StateSuspended
    StateDone
    StateFailed
)

type AgentSpec struct {
    ID           string       `json:"id"`
    Name         string       `json:"name"`
    Version      string       `json:"version"`
    Description  string       `json:"description"`
    Capabilities []string     `json:"capabilities"` // Allowed capability IDs
    Memory       MemoryConfig `json:"memory"`
    Budget       BudgetConfig `json:"budget"`
}

type AgentHandle struct {
    Spec      AgentSpec
    State     AgentState
    SessionID string
    ExecCtx   *execctx.ExecutionContext
    UpdatedAt time.Time
}

AgentRegistry API

type AgentRegistry interface {
    Register(spec AgentSpec) error
    Lookup(agentID string) (AgentSpec, error)
    ListAll() []AgentSpec
    Spawn(ctx context.Context, ec *execctx.ExecutionContext, sessionID string) (*AgentHandle, error)
    UpdateState(handle *AgentHandle, state AgentState) error
    Suspend(handle *AgentHandle) error
    Resume(handle *AgentHandle) error
    Terminate(handle *AgentHandle, state AgentState) error
}

Usage Example

import (
    "context"
    "github.com/vyuvaraj/pranor/agent"
    "github.com/vyuvaraj/pranor/agent/api"
    "github.com/vyuvaraj/pranor/core/pkg/execctx"
)

// Register Agent Spec
agent.Register(api.AgentSpec{
    ID:           "support-bot",
    Name:         "Support Agent",
    Capabilities: []string{"pool.query", "notify.send"},
})

// Spawn instance bound to ExecutionContext
ec := execctx.New(ctx, "acme-corp", "support-bot", "user-123")
handle, err := agent.Spawn(ctx, ec, "session-88")

Agent-to-Agent Delegation Protocol (agent/pkg/a2a)

Package: github.com/vyuvaraj/pranor/agent/pkg/a2a
Introduced: Phase 93 (Sprint V2.93.3)


Overview

The A2A Delegation Protocol (agent/pkg/a2a) enables secure inter-agent task delegation. It enforces capability escalation prevention (child agents cannot inherit permissions beyond what the parent possesses) and handles automatic identity propagation.


Data Structures

type DelegationRequest struct {
	ChildAgentID          string         `json:"child_agent_id"`
	SubTaskPayload        map[string]any `json:"subtask_payload"`
	RequestedCapabilities []string       `json:"requested_capabilities"`
	RiskBudget            float64        `json:"risk_budget"`
	TokenBudget           int            `json:"token_budget"`
}

type DelegationResult struct {
	SessionID     string                   `json:"session_id"`
	Status        string                   `json:"status"` // "SUCCESS", "FAILED"
	OutputPayload map[string]any           `json:"output_payload"`
	TokensUsed    int                      `json:"tokens_used"`
	CostUSD       float64                  `json:"cost_usd"`
	ChildExecCtx  *execctx.ExecutionContext `json:"child_exec_ctx"`
}

Delegation Sequence

Parent Agent (AgentID: parent-1, Capabilities: [pool.query, notify.send])
  │
  ├── Delegate(child-1, RequestedCapabilities: [pool.query])
  │     ├── Check Escalation: pool.query ∈ parent capabilities? -> YES
  │     ├── Create Child ExecCtx: parentEC.WithAgent("child-1")
  │     │     (ParentAgentID: "parent-1", AgentID: "child-1")
  │     └── Execute Subtask -> SUCCESS
  │
  └── Delegate(child-2, RequestedCapabilities: [secret.delete])
        └── Check Escalation: secret.delete ∈ parent capabilities? -> NO
              └── Returns ErrCapabilityEscalationDenied (Fail-Closed)

Code Example

import "github.com/vyuvaraj/pranor/agent/pkg/a2a"

delegator := a2a.NewOSSDelegator()

res, err := delegator.Delegate(ctx, parentEC, a2a.DelegationRequest{
	ChildAgentID:          "sub-analyst",
	RequestedCapabilities: []string{"pool.query"},
	SubTaskPayload:        map[string]any{"query": "SELECT count(*) FROM orders"},
})
if err == a2a.ErrCapabilityEscalationDenied {
	// Child attempted to escalate permissions beyond parent
}

LLM Router (std/llm)

Module Path: github.com/vyuvaraj/pranor/llm
Introduced: Phase 91 (Sprint V2.91.3)


Overview

Pranor LLM (std/llm) provides a provider-agnostic model routing abstraction with fallback chains, semantic caching hooks, cost tracking, and CGO-free execution.


Key Interfaces

ChatProvider

Every LLM driver implements ChatProvider:

type ChatProvider interface {
    Chat(ctx context.Context, req ChatRequest) (ChatResponse, error)
    Name() string
    Models() []string
    HealthCheck(ctx context.Context) error
}

Router

type Router interface {
    Route(ctx context.Context, req ChatRequest) (ChatResponse, error)
    Register(p ChatProvider)
    SetFallbackChain(providerNames []string)
    HealthCheck(ctx context.Context) map[string]error
}

Data Structures

type Message struct {
    Role    string // RoleSystem, RoleUser, RoleAssistant, RoleTool
    Content string
    Name    string
}

type ChatRequest struct {
    Messages    []Message
    Model       string   // e.g. "gpt-4o", "claude-3-5-sonnet"
    MaxTokens   int
    Temperature float64
    Stream      bool
    BudgetMs    int64    // Latency budget in ms
}

type ChatResponse struct {
    Content      string
    FinishReason FinishReason // FinishStop, FinishLength, FinishToolCall, FinishFiltered
    InputTokens  int
    OutputTokens int
    TotalTokens  int
    CostUSD      float64
    LatencyMs    int64
    Provider     string
    Model        string
}

Drivers & OSS vs. EE Split

ProviderTypeDescription
EchoProviderOSSTest stub echoing the last input message
HTTPProviderOSSGeneric OpenAI-compatible REST API driver
OpenAIEEFull OpenAI API driver with streaming & function calling via gRPC sidecar
AnthropicEEClaude 3.5 Sonnet/Haiku driver via gRPC sidecar
GeminiEEGoogle Gemini 1.5 Pro/Flash driver via gRPC sidecar
OllamaEELocal vLLM/Ollama driver via IPC socket

Code Example

import (
    "context"
    "github.com/vyuvaraj/pranor/llm"
    "github.com/vyuvaraj/pranor/llm/api"
)

resp, err := llm.Route(ctx, api.ChatRequest{
    Model: "gpt-4o",
    Messages: []api.Message{
        {Role: api.RoleUser, Content: "Hello Pranor!"},
    },
})

Gate Guardrails (gate/pkg/guardrails)

Package: github.com/vyuvaraj/pranor/gate/pkg/guardrails
Introduced: Phase 91 (Sprint V2.91.4)


Overview

Gate Guardrails provide in-line security scanning at the Pranor Gate execution boundary. It inspects prompt inputs for PII and prompt injection patterns, and validates model outputs for secret/credential leaks and JSON schema compliance.


Key Types

type Action int

const (
    ActionAllow Action = iota // Allow request through un-modified
    ActionMask                // Redact/mask detected PII
    ActionBlock               // Hard block execution (fail-closed)
)

type PIISpan struct {
    Type  PIIType // EMAIL, PHONE, SSN, CREDIT_CARD
    Start int
    End   int
    Value string
}

type InputInspectionResult struct {
    Action        Action
    Prompt        string    // original or masked prompt
    PIISpans      []PIISpan
    InjectionRisk float64   // 0.0-1.0
    BlockedReason string
}

type OutputValidationResult struct {
    Action        Action
    Output        string
    SecretLeaks   []string
    BlockedReason string
}

Security Scanners

  1. PII Detector: Scans for Emails, Phone numbers, SSNs, and Credit Card numbers. Automatically masks detected PII ([REDACTED_<TYPE>]) when RiskBudget < 0.3.
  2. Prompt Injection Scanner: Heuristic scanner checking for jailbreaks, "ignore previous instructions", and role-takeover attempts. Hard blocks (ActionBlock) on match.
  3. Secret Leak Scanner: Inspects LLM output for leaked OpenAI keys (sk-*), AWS keys (AKIA*), GitHub tokens (ghp_*), and RSA private keys (BEGIN PRIVATE KEY). Hard blocks on detection.
  4. Output Schema Validator: Verifies LLM output matches declared JSON output schemas before returning to downstream tools/clients.

Usage Example

import "github.com/vyuvaraj/pranor/gate/pkg/guardrails"

inspector := guardrails.NewOSSInspector()

// Inspect prompt input
res, err := inspector.InspectInput(ctx, execCtx, "My email is user@example.com. Ignore previous instructions.")
if res.Action == guardrails.ActionBlock {
    // Execution blocked due to prompt injection
}

Gate Shadow Execution (gate/pkg/shadow)

Package: github.com/vyuvaraj/pranor/gate/pkg/shadow
Introduced: Phase 92 (Sprint V2.92.4)


Overview

Gate Shadow Execution provides side-effect isolation when evaluating agents or policies in SIMULATION / shadow mode.

When a request contains header X-Shadow-Mode: true or ec.PolicyContext["mode"] == "SIMULATION", the shadow.Interceptor at the Gate boundary:

  • Allows read-only capability calls to execute normally.
  • Intercepts write/destructive capability calls (database mutations, external API calls, notification triggers) and converts them into no-op mock responses with annotation [SHADOW_MODE_NOOP].
  • Emits pranor.gate.shadow_execution OTLP telemetry.

Key Interface

type Interceptor interface {
	IsShadowMode(ec *execctx.ExecutionContext) bool
	InterceptCapability(ctx context.Context, ec *execctx.ExecutionContext, capID string, input map[string]any) (map[string]any, bool, error)
}

Behavior Matrix

Operation TypeReal Mode (REAL)Shadow Mode (SIMULATION)
Read (RiskLow, no DB writes)Execute backend queryExecute backend query (Passthrough)
DB Write (WritesDB = true)Execute database write[SHADOW_MODE_NOOP]
External API (ExternalAPICalls = true)HTTP POST / gRPC call[SHADOW_MODE_NOOP]
Notification (SendsNotification = true)Send Email / SMS / Webhook[SHADOW_MODE_NOOP]

Memory Engine (std/memory)

Module Path: github.com/vyuvaraj/pranor/memory
Introduced: Phase 92 (Sprint V2.92.1)


Overview

Pranor Memory (std/memory) provides governed working and episodic memory for AI agents, operating without external database dependencies.

  • Working Memory: Volatile, in-session scratchpad scoped to (TenantID, AgentID, SessionID).
  • Episodic Memory: Cross-session memory recall storing conversation turns and tool outputs with time-decay and keyword relevance scoring algorithms.

Key Interfaces

type WorkingMemory interface {
	Set(ctx context.Context, ec *execctx.ExecutionContext, sessionID, key string, value any) error
	Get(ctx context.Context, ec *execctx.ExecutionContext, sessionID, key string) (any, bool, error)
	Delete(ctx context.Context, ec *execctx.ExecutionContext, sessionID, key string) error
	Flush(ctx context.Context, ec *execctx.ExecutionContext, sessionID string) error
}

type EpisodicMemory interface {
	StoreEpisode(ctx context.Context, ec *execctx.ExecutionContext, sessionID, role, content string, tags []string) (MemoryEntry, error)
	Recall(ctx context.Context, ec *execctx.ExecutionContext, query string, topK int) ([]MemoryEntry, error)
	Purge(ctx context.Context, ec *execctx.ExecutionContext) error
}

Data Structures

type MemoryEntry struct {
	ID        string    `json:"id"`
	TenantID  string    `json:"tenant_id"`
	AgentID   string    `json:"agent_id"`
	SessionID string    `json:"session_id"`
	Content   string    `json:"content"`
	Role      string    `json:"role"` // "user", "assistant", "tool"
	Tags      []string  `json:"tags"`
	CreatedAt time.Time `json:"created_at"`
	Score     float64   `json:"score"` // Computed relevance score during recall
}

Relevance & Time-Decay Scoring Algorithm

During Recall(ctx, ec, query, topK), memory entries are filtered by ec.TenantID and ec.AgentID (ensuring tenant isolation), then scored:

$$\text{Score} = \text{KeywordMatchCount} \times \left( \frac{1.0}{1.0 + \text{HoursSinceCreation}} \right)$$

Entries are returned sorted by Score descending.


Code Example

import (
	"github.com/vyuvaraj/pranor/memory"
)

// Working Memory Scratchpad
wm := memory.Working()
_ = wm.Set(ctx, ec, sessionID, "current_step", "parsing_invoice")

// Episodic Recall
em := memory.Episodic()
entries, _ := em.Recall(ctx, ec, "invoice payment", 5)

Pranor Graph — Entity Context Layer

Version: 2.0.0-dev
Module Path: github.com/vyuvaraj/pranor/graph
License: AGPL-3.0 (OSS) / EE


Overview

Pranor Graph provides a virtual entity context assembly layer linking Pranor Pool, Cache, and Vault. It is part of the v2.0 AI Execution Fabric.


Key Features

TierLatencySourceDescription
Hot tier<2msIn-memoryLocal memory cache for ultra-fast context retrieval
Warm tier~10-50msSQL virtual joinDatabase queries joining structured data
Cold tier>50msRaw fallbackS3/Vault unstructured data fallback

Architecture

graph TD
    Query["Context Query"]
    Hot["Hot Tier (In-Memory Cache)"]
    Warm["Warm Tier (SQL Virtual Join)"]
    Cold["Cold Tier (Vault Raw Fallback)"]
    
    Query --> Hot
    Hot -.->|Miss| Warm
    Warm -.->|Miss| Cold

Fail-closed Contract

Pranor Graph guarantees a fail-closed contract: it returns ErrGraphContextUnavailable on all-tier exhaustion to ensure AI models never receive partial context.


API Reference

GraphProvider Interface

type GraphProvider interface {
    Query(ctx context.Context, q ContextQuery) (ContextResult, error)
    Invalidate(ctx context.Context, entityID, tenantID string) error
    HealthCheck(ctx context.Context) error
}

Types

ContextQuery Struct representing a query to assemble context for an entity.

ContextResult Struct returning the assembled entity context payload.


Zero-CGO constraint

CGO_ENABLED=0, all EE features are implemented via a gRPC sidecar.


Quick Start

provider := graph.NewProvider(cfg)
ctx := context.Background()

result, err := provider.Query(ctx, graph.ContextQuery{
    EntityID: "user_123",
    TenantID: "tenant_456",
})
if err != nil {
    // Fails closed on exhaustion
    log.Fatal(err)
}
fmt.Println(result)

Enterprise Edition

FeatureOSSEE
In-memory hot cache
SQL stub
Cross-datacenter sync
RBAC isolation
Distributed invalidation

Pranor Decision — AI Governance Engine

Version: 2.0.0-dev
Module Path: github.com/vyuvaraj/pranor/decision
License: AGPL-3.0 (OSS) / EE


Overview

Pranor Decision provides a Governed AI execution decision layer with a 6-level veto ladder. It ensures safe and predictable AI operations.


Key Features

  • 6-Level Priority Veto Ladder
  • SIMULATION Mode: Counterfactual evaluation without committing state
  • Fault Contracts

6-Level Priority Veto Ladder

LevelNameModuleHard/SoftEffect
1AuthdecisionHardDENY blocks all subsequent levels
2BudgetdecisionHardDENY on cost/token overflow
3RiskdecisionSoftAPPROVE/DENY from risk signals
4RulesdecisionSoftAPPROVE/DENY/TRANSFORM policy rules
5LearnlearnSoftAdvisory from ML predictor (skip on timeout)
6DefaultdecisionHardFinal ALLOW fallback

Fault Contract

  • Returns DENY if graph context is unavailable.
  • Learn level is skipped on ErrSidecarTimeout.

Types

DecisionRequest Input parameters containing context, agent info, and action intent.

DecisionResult Output containing the veto outcome, priority level hit, and metadata.


Quick Start

engine := decision.NewEngine(cfg)
ctx := context.Background()

// Standard execution
res, err := engine.Evaluate(ctx, decision.DecisionRequest{
    AgentID: "agent_88",
    Action:  "transfer_funds",
})

// Simulation mode
simRes, err := engine.Evaluate(ctx, decision.DecisionRequest{
    AgentID:   "agent_88",
    Action:    "transfer_funds",
    Simulate:  true, // Do not commit state
})

Enterprise Edition

FeatureOSSEE
Basic 6-level ladder
Simulation mode
Advanced Risk Models
Custom Rules Engine UI

Pranor Learn — ML Inference Provider

Version: 2.0.0-dev
Module Path: github.com/vyuvaraj/pranor/learn/api
License: AGPL-3.0 (OSS) / EE


Overview

Pranor Learn acts as a pluggable ML inference provider for the Decision Engine, powering the Level 5 Learn veto level.

The module is divided into three sub-modules:

  • learn/api: Shared interfaces and contracts.
  • learn/wasm: Wazero runner for WASM inference.
  • learn/sidecar: gRPC IPC sidecar for external models.

Zero-CGO Constraint

All Pranor Learn code enforces CGO_ENABLED=0. Complex ML inference is offloaded to the gRPC sidecar.


API Reference

Predictor Interface

type Predictor interface {
    Predict(ctx context.Context, in PredictInput) (PredictOutput, error)
    HealthCheck(ctx context.Context) error
}

Types

PredictInput Contains the features and context for inference, as well as BudgetMs for timeouts.

PredictOutput Contains the prediction result, confidence scores, and advisory actions.


Fault Contracts

  • Returns ErrSidecarTimeout if the gRPC sidecar exceeds BudgetMs.
  • Returns ErrModelBudgetExceeded for inference compute overruns.

Enterprise Edition

FeatureOSSEE
WASM runner
Stubs for sidecar✓ (Returns ErrEERequired in OSS)
GPU PyTorch/TabPFN pool

Pranor Eval — Agent Quality Scoring

Version: 2.0.0-dev
Module Path: github.com/vyuvaraj/pranor/eval
License: AGPL-3.0 (OSS) / EE


Overview

Pranor Eval is a trajectory-based quality scoring and replay framework for AI agents, allowing offline and online evaluation of AI behavior.


Key Features

  • 4 Evaluators: Accuracy, Latency, Cost, Safety
  • Soft-fail guarantee: A single evaluator panic/error degrades the score but doesn't abort the run.

Evaluators

NameMetricPass ThresholdDescription
AccuracyEvaluatorError-free span rate≥80%Validates agent output matches expected outcomes without internal errors.
LatencyEvaluatorTotal DurationMs vs BudgetMsWithin budgetEnsures execution completes within SLA timeouts.
CostEvaluatorSpan count vs MaxSpansWithin maxBounds agent exploration steps and LLM token usage.
SafetyEvaluatorDENY outcomes on critical modules0 violationsStrictly checks for security or policy vetoes.

API Reference

EvalEngine API

  • Register(evaluator Evaluator): Register a new evaluator.
  • Run(ctx context.Context, trajectory Trajectory) (EvalResult, error): Run evaluation on a trajectory.
  • Replay(ctx context.Context, id string) (Trajectory, error): Fetch and replay a previous run.

Trajectory Types

  • TrajectorySpan: Individual unit of execution.
  • Trajectory: Collection of spans representing an execution path.
  • EvalScore: Individual evaluator score.
  • EvalResult: Final aggregated result.

Quick Start

engine := eval.NewEvalEngine()
engine.Register(eval.NewAccuracyEvaluator())
engine.Register(eval.NewSafetyEvaluator())

trajectory := getAgentTrajectory("exec_123")
result, _ := engine.Run(context.Background(), trajectory)
fmt.Println("Score:", result.TotalScore)

Enterprise Edition

FeatureOSSEE
Local replay
CI/CD quality gate
Trace archive

Multi-Tenant Sandboxing & Rate Limiting (core/pkg/tenant)

Package: github.com/vyuvaraj/pranor/core/pkg/tenant
Introduced: Phase 93 (Sprint V2.93.2)


Overview

Pranor Tenant (core/pkg/tenant) enforces multi-tenant resource quotas, request rate limiting, and daily token/cost bounds to guarantee hard tenant isolation and prevent runaway billing or resource starvation.


Data Structures

type Quota struct {
	MaxRequestsPerMin   int     `json:"max_requests_per_min"`
	MaxConcurrentAgents int     `json:"max_concurrent_agents"`
	MaxTokensPerDay     int     `json:"max_tokens_per_day"`
	MaxCostUSDPerDay    float64 `json:"max_cost_usd_per_day"`
}

type UsageStats struct {
	RequestsThisMin int       `json:"requests_this_min"`
	ActiveAgents    int       `json:"active_agents"`
	TokensToday     int       `json:"tokens_today"`
	CostUSDToday    float64   `json:"cost_usd_today"`
	LastResetMinute time.Time `json:"last_reset_minute"`
	LastResetDay    time.Time `json:"last_reset_day"`
}

Enforcer API

type Enforcer interface {
	SetQuota(tenantID string, q Quota)
	GetQuota(tenantID string) (Quota, bool)
	Enforce(ec *execctx.ExecutionContext) error
	RecordUsage(ec *execctx.ExecutionContext, tokens int, costUSD float64) error
	ReleaseAgent(ec *execctx.ExecutionContext)
}
  • Enforce: Called at Gate ingress. Returns ErrTenantRateLimited if request rate or active agents exceed quota, or ErrTenantQuotaExceeded if daily token or cost limits are hit.
  • RecordUsage: Called post-execution to update daily token and USD cost counters.

Code Example

import "github.com/vyuvaraj/pranor/core/pkg/tenant"

enforcer := tenant.NewOSSEnforcer()
enforcer.SetQuota("tenant-acme", tenant.Quota{
	MaxRequestsPerMin:   60,
	MaxConcurrentAgents: 5,
	MaxTokensPerDay:     100000,
	MaxCostUSDPerDay:    10.00,
})

// Check quota before execution
if err := enforcer.Enforce(ec); err != nil {
	// Returns ErrTenantRateLimited or ErrTenantQuotaExceeded
}

agentctl Developer CLI (tools/agentctl)

Package: github.com/vyuvaraj/pranor/tools/agentctl
Introduced: Phase 92 (Sprint V2.92.3)


Overview

agentctl is the official developer CLI tool for inspecting, debugging, replaying, and simulating Pranor agent executions locally.


Commands & Usage

agentctl — Pranor Agent Developer CLI Tool

Commands:
  trace <session-id>           Print span waterfall trace summary
  replay <trajectory.json>     Replay trajectory & run quality evaluators
  budget [agent-id]            Display token & cost budget status
  policy simulate <req.json>   Dry-run Decision Engine policy simulation

Command Details

1. agentctl trace <session-id>

Prints formatted OTLP span waterfall telemetry for an active or recorded agent session:

$ agentctl trace sess-8910
=== Agent Execution Trace: sess-8910 ===
Span: pranor.agent_execution [ALLOW] 12ms
Span: pranor.gate.inspect      [ALLOW] 2ms
Span: pranor.decision.evaluate [APPROVE] 4ms

2. agentctl replay <trajectory.json>

Loads a recorded trajectory JSON file, re-emits its spans through eval.Replay, and executes registered quality evaluators (AccuracyEvaluator, LatencyEvaluator, CostEvaluator, SafetyEvaluator):

$ agentctl replay trajectory_prod.json
✓ Trajectory replayed: tr-001-replay (spans: 4)
Evaluation Result: OverallPass=true
  - accuracy: score=1.00 pass=true (4/4 spans without error)
  - latency: score=0.98 pass=true (90ms, budget 5000ms)

3. agentctl budget [agent-id]

Displays token and cost quota consumption:

$ agentctl budget support-bot
=== Budget Status for Agent: support-bot ===
Token Quotas   : 45,000 / 100,000 tokens (45% used)
Daily Cost     : $0.14 / $5.00 USD
Status         : OK

4. agentctl policy simulate <request.json>

Performs counterfactual policy evaluation using decision.Simulate without executing side effects or mutating backend state:

$ agentctl policy simulate req.json
=== Decision Engine Policy Simulation ===
Request        : AgentID=support-bot TenantID=acme-corp
Evaluated      : Priority 1 (Auth) -> PASS, Priority 2 (Budget) -> PASS
Outcome        : APPROVE (Simulation Mode - No Side Effects Committed)

Docker Deployment Guide

Run the full Pranor platform or individual modules using Docker Compose.

Quick Start — Full Platform

git clone https://github.com/vyuvaraj/pranor.git
cd pranor
docker compose up -d

This starts all modules:

ServicePortDescription
pranor-gate8080API Gateway
pranor-vault8081Object Storage (S3)
pranor-pulse8082Message Broker (STOMP)
pranor-console8083Dashboard UI
pranor-deploy8085Deployment Orchestrator
pranor-cache8086Cache Engine
pranor-chrono8087Job Scheduler
pranor-hub8088Package Registry
pranor-mesh8089Service Mesh
pranor-trace8090Tracing Collector
pranor-notify8094Notification Gateway
pranor-flow8096Workflow Engine
pranor-pool8097DB Connection Pool
pranor-auth8098Auth Provider
pranor-tunnel8443Dev Tunnel

Single Module

Run any module standalone:

# Just the API Gateway
docker run -p 8080:8080 ghcr.io/vyuvaraj/pranor-gate:latest

# Just the Object Storage
docker run -p 8081:8081 -v vault-data:/data ghcr.io/vyuvaraj/pranor-vault:latest

# Just the Message Broker
docker run -p 8082:8082 -p 61613:61613 ghcr.io/vyuvaraj/pranor-pulse:latest

Environment Variables

All modules accept:

VariableDescription
PRANOR_OTLP_ENDPOINTOpenTelemetry collector URL
PRANOR_DISCOVERYJSON map of module URLs for service discovery

Module-specific variables are documented in each module's docs.

Docker Compose (Production)

services:
  pranor-gate:
    image: ghcr.io/vyuvaraj/pranor-gate:latest
    ports:
      - "8080:8080"
    environment:
      - PRANOR_OTLP_ENDPOINT=http://pranor-trace:8090
    depends_on:
      pranor-trace:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:8080/healthz"]
      interval: 5s
      timeout: 3s
      retries: 5

  pranor-vault:
    image: ghcr.io/vyuvaraj/pranor-vault:latest
    ports:
      - "8081:8081"
    volumes:
      - vault-data:/data
    environment:
      - PRANOR_OTLP_ENDPOINT=http://pranor-trace:8090

  pranor-trace:
    image: ghcr.io/vyuvaraj/pranor-trace:latest
    ports:
      - "8090:8090"

networks:
  default:
    name: pranor-net

volumes:
  vault-data:

Health Checks

Every module exposes GET /healthz returning:

{"status": "UP", "service": "pranor", "version": "1.0.0"}

Observability

Connect all modules to Pranor Trace for distributed tracing:

PRANOR_OTLP_ENDPOINT=http://pranor-trace:8090

View traces in Pranor Console at http://localhost:8083 or forward to Jaeger/Grafana.

Next Steps

Kubernetes Deployment

Deploy Pranor modules to Kubernetes using Helm charts or raw manifests.

helm repo add pranor https://vyuvaraj.github.io/pranor/charts
helm install pranor-vault pranor/pranor-vault --namespace pranor --create-namespace
helm install pranor-gate pranor/pranor-gate --namespace pranor
helm install pranor-pulse pranor/pranor-pulse --namespace pranor

Minimal Manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pranor-gate
  namespace: pranor
spec:
  replicas: 2
  selector:
    matchLabels:
      app: pranor-gate
  template:
    metadata:
      labels:
        app: pranor-gate
    spec:
      containers:
      - name: pranor-gate
        image: ghcr.io/vyuvaraj/pranor-gate:latest
        ports:
        - containerPort: 8080
        env:
        - name: PRANOR_OTLP_ENDPOINT
          value: "http://pranor-trace:8090"
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: pranor-gate
  namespace: pranor
spec:
  selector:
    app: pranor-gate
  ports:
  - port: 8080
    targetPort: 8080
  type: ClusterIP

KEDA Auto-Scaling (Pranor Pulse)

Scale consumers based on message queue lag:

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: pranor-pulse-consumer
spec:
  scaleTargetRef:
    name: order-processor
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
  - type: external
    metadata:
      scalerAddress: pranor-pulse:8082
      topic: orders
      consumerGroup: processors
      lagThreshold: "100"

Service Discovery

Set PRANOR_DISCOVERY as a ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: pranor-discovery
data:
  PRANOR_DISCOVERY: |
    {
      "gate": "http://pranor-gate:8080",
      "vault": "http://pranor-vault:8081",
      "pulse": "http://pranor-pulse:8082",
      "cache": "http://pranor-cache:8086",
      "trace": "http://pranor-trace:8090",
      "auth": "http://pranor-auth:8098"
    }

Next Steps

Standalone Deployment

Run individual Pranor modules as native binaries without containers.

Build from Source

Each module can be built independently:

cd pranor/gate && go build -o pranor-gate .
cd pranor/vault && go build -o pranor-vault .
cd pranor/pulse && go build -o pranor-pulse .
cd pranor/trace && go build -o pranor-trace .
cd pranor/auth && go build -o pranor-auth .
cd pranor/cache && go build -o pranor-cache .

Run

# Start tracing first (other modules send traces here)
./pranor-trace --port 8090 &

# Start object storage
./pranor-vault --port 8081 --data-dir ./data &

# Start API gateway
./pranor-gate --port 8080 --config config.json &

# Start message broker
./pranor-pulse --port 8082 &

Unified Binary (pranord)

Run all modules in a single process:

cd pranor/platform
go build -o pranord .
./pranord --modules gate,vault,pulse,trace,auth,cache

systemd Service

[Unit]
Description=Pranor Gate API Gateway
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/pranor-gate --port 8080
Restart=always
RestartSec=5
Environment=PRANOR_OTLP_ENDPOINT=http://localhost:8090

[Install]
WantedBy=multi-user.target

Environment Setup

export PRANOR_HOME=/opt/pranor
export PRANOR_OTLP_ENDPOINT=http://localhost:8090
export PRANOR_DISCOVERY='{"gate":"http://localhost:8080","vault":"http://localhost:8081"}'

Next Steps

Integrations & Developer Tooling

Pranor seamlessly integrates with existing cloud-native infrastructure tools, CI/CD pipelines, observability platforms, and IDE containers.


1. Terraform Provider (terraform-provider-pranor)

Declaratively manage your Pranor cloud infrastructure using standard HCL configurations.

Configuration

terraform {
  required_providers {
    pranor = {
      source  = "vyuvaraj/pranor"
      version = "~> 1.0.0"
    }
  }
}

provider "pranor" {
  address = "http://localhost:8096"
  token   = var.pranor_admin_token
}

resource "pranor_bucket" "user_uploads" {
  name       = "user-uploads"
  versioning = true
}

resource "pranor_topic" "order_events" {
  name       = "orders.created"
  partitions = 4
}

resource "pranor_cron_job" "nightly_cleanup" {
  name     = "nightly-cleanup"
  schedule = "0 0 * * *"
  endpoint = "http://api-service:8080/internal/cleanup"
}

2. GitHub Action (pranor/deploy-action@v1)

Automate .pnr application compilation, artifact packaging, and zero-downtime blue/green deployment directly inside GitHub Actions workflows.

Workflow Example (.github/workflows/deploy.yml)

name: Pranor CI/CD Deployment

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Pranor Cluster
        uses: pranor/deploy-action@v1
        with:
          entrypoint: 'main.pnr'
          output-binary: 'app.pnr'
          deploy-target: 'docker'
          cluster-url: 'https://deploy.pranor.dev'
          api-token: ${{ secrets.PRANOR_DEPLOY_TOKEN }}
          environment: 'production'

3. Observability Integrations

Prometheus Remote Write Receiver (Pranor Trace)

Pranor Trace accepts Prometheus remote_write payloads natively. Point existing Prometheus server or agent scrapers directly to Pranor Trace:

# prometheus.yml
remote_write:
  - url: "http://pranor-trace:8087/api/v1/prom/remote_write"

OpenTelemetry Collector Exporter (Pranor Trace)

Export traces and metrics from the standard OpenTelemetry Collector to Pranor Trace via OTLP/HTTP:

# otel-collector-config.yaml
exporters:
  otlphttp/pranor:
    endpoint: "http://pranor-trace:8087"

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlphttp/pranor]

Grafana Data Source Plugin

Pranor Trace and Pranor Pulse provide a native Grafana datasource plugin for visualizing distributed traces, span latency distributions, and topic event metrics on Grafana dashboards.

  • Connection URL: http://localhost:8087 (Trace) or http://localhost:8083 (Pulse).

4. Onboarding & DX Automation

Interactive Quickstart Wizard (pranor quickstart)

Interactively scaffold new projects with optional module presets (REST API, Auth, Vault, Pulse events, Chrono jobs):

pranor quickstart

Infrastructure Health Diagnostics (pranor doctor)

Run comprehensive system health checks across ports, binary dependencies, Docker environment, and configuration validity:

pranor doctor

VS Code Dev Container & GitHub Codespaces Template

One-click cloud development container pre-configured with Go 1.22+, pranor compiler, pranor-lsp, and forwarded ports for pranord console (8096):

  • Open .devcontainer/devcontainer.json in VS Code or launch via GitHub Codespaces.

Architecture Overview

Pranor is a modular backend infrastructure engine. Each module runs independently or together as a unified platform.

System Diagram

                         ┌─────────────────────┐
                         │     Clients         │
                         │  (Web, Mobile, API) │
                         └──────────┬──────────┘
                                    │
                         ┌──────────▼──────────┐
                         │    Pranor Gate      │
                         │   API Gateway &     │
                         │   Ingress Router    │
                         └──────────┬──────────┘
                                    │
              ┌─────────────────────┼─────────────────────┐
              │                     │                     │
    ┌─────────▼────────┐  ┌────────▼────────┐  ┌────────▼────────┐
    │   Pranor Auth    │  │  Pranor Mesh    │  │  Pranor Cache   │
    │  Identity/RBAC   │  │ Service Discovery│  │  Redis/Memory   │
    └──────────────────┘  └────────┬────────┘  └─────────────────┘
                                   │
         ┌─────────────────────────┼─────────────────────────┐
         │                         │                         │
┌────────▼────────┐  ┌────────────▼────────────┐  ┌─────────▼────────┐
│  Your Services  │  │     Pranor Pulse        │  │   Pranor Vault   │
│  (.pnr files)   │  │  Async Event Broker     │  │  Object Storage  │
└────────┬────────┘  └────────────┬────────────┘  └──────────────────┘
         │                        │
         │            ┌───────────┼───────────┐
         │            │           │           │
┌────────▼───────┐ ┌──▼──┐ ┌─────▼─────┐ ┌───▼───┐
│ Pranor Chrono  │ │Flow │ │  Notify   │ │ Pool  │
│  Scheduler     │ │     │ │ Email/SMS │ │  DB   │
└────────────────┘ └─────┘ └───────────┘ └───────┘
         │
┌────────▼───────────────────────────────────┐
│              Pranor Trace                   │
│         Distributed Tracing (OTLP)         │
└────────────────────────────────────────────┘
         │
┌────────▼───────────────────────────────────┐
│            Pranor Console                   │
│       Observability Dashboard UI           │
└────────────────────────────────────────────┘

How Modules Connect

FromToProtocolPurpose
Gate → Servicespranor://HTTP/gRPC via MeshRoute requests to backends
Services → PulseSTOMP/TCPAsync messagingPublish events, consume queues
Services → VaultS3 HTTP APIObject storageStore files, vectors, configs
Services → CacheRedis protocolCachingTTL-based key-value cache
Services → PoolPostgreSQL wireDB proxyConnection pooling, read/write split
All → TraceOTLP HTTPTelemetrySpans, metrics, logs
Chrono → ServicesHTTP webhookSchedulingTrigger jobs on cron schedule
Flow → ServicesHTTPOrchestrationDAG workflow execution
Auth → GateJWT validationSecurityToken verification on every request

Module Independence

Each module is:

  • A standalone Go binary with zero external dependencies
  • Independently deployable (Docker, K8s, bare metal)
  • Horizontally scalable
  • Observable via standard OTLP

No module requires any other module to function. The Pranor language compiler orchestrates them together when running a unified .pnr service, but each works alone.

Data Flow Example

A typical request through the full platform:

  1. Client sends POST /api/orders to Gate (port 8080)
  2. Gate validates JWT via Auth, applies rate limiting
  3. Gate routes to your order service via Mesh discovery
  4. Your service writes order to Vault (S3 storage)
  5. Your service publishes order.created event to Pulse
  6. Chrono triggers a delayed notification job
  7. Notify sends confirmation email/SMS
  8. Trace captures the full request waterfall
  9. Console displays the trace in real-time

Next Steps

Security Architecture

Pranor implements defense-in-depth across all modules.

Authentication & Authorization

LayerMechanismModule
API clientsJWT (RS256/ES256) + OAuth2/OIDCAuth
Inter-servicemTLS with auto-rotating certificatesMesh
Admin APIsAPI key + RBACAll modules
Browser sessionsSecure cookies + MFA (TOTP/WebAuthn)Auth

Zero-Trust Model

Every request between modules is authenticated:

Client → Gate (JWT validation & Agent Security Chain)
       → Agent Firewall (Intent, Risk & HITL Approval)
       → Mesh (mTLS between services)
       → Target Service / Tool (Capability execution)

No module trusts another implicitly. Mesh provides workload identity via SPIFFE, while Gate enforces Agent Security Chains (Agent ID -> User ID -> Tenant ID -> Capability ID).

AI Agent Security & Governance

FeatureMechanismScope
AI Agent Security FirewallInspects tool call intents, arguments & risk scores (ALLOW/DENY/APPROVE/TRANSFORM)Gate
Agent Security ChainFirst-class Agent ID -> User ID -> Tenant ID -> Capability context propagationGate / Auth
Human-in-the-Loop (HITL)Asynchronous approval workflows (Agent -> Gate -> Approval -> Gate -> Tool)Gate
Trajectory Replay & SimulationReplays recorded trajectory steps to simulate & diff policy changesGate
Agent Blast-Radius & BudgetsSession-level and action-specific tool call rate limitsGate
Protocol-Agnostic ExposerExposes capabilities across MCP, gRPC, HTTP/REST, and WASMGate

Encryption

ScopeAlgorithmWhere
Data at restAES-256-GCMVault, Pulse
Data in transitTLS 1.3All inter-module traffic
Secrets storageAES-256-GCM + Shamir sharingSecret
Browser queueAES-256-GCM client-sidePulse (OPFS)
JWT signingRS256 or ES256Auth

Enterprise Security (EE)

FeatureDescription
FIPS 140-3 modeHSM-backed key management
Post-quantum cryptoX25519 + Kyber hybrid key exchange
Byzantine consensusBFT Raft for tamper-resistant clusters
eBPF XDP accelerationKernel-level packet filtering
Blind broker E2EEPulse broker never sees plaintext messages
Merkle audit ledgerTamper-evident append-only audit trail

RBAC Model

// Define roles in Auth
POST /api/v1/rbac/roles
{
  "name": "editor",
  "permissions": ["read:articles", "write:articles"]
}

// Assign to users
POST /api/v1/rbac/users/user-123/roles
{ "roles": ["editor"] }

Gate enforces RBAC policies on every routed request.

Secret Management

Pranor Secret provides:

  • Dynamic secret injection into processes
  • Shamir key splitting for master key unsealing
  • Automatic rotation with versioning
  • Leak detection scanning
pranor secret inject --env production -- ./my-service

Next Steps

Observability

Every Pranor module emits traces, metrics, and logs through OpenTelemetry.

Stack

Your Services → Pranor Trace (OTLP collector) → Pranor Console (dashboard)
                                              → Jaeger / Grafana (optional)

Distributed Tracing

All modules propagate W3C traceparent headers automatically. A single request generates a connected trace across Gate → Mesh → Service → Pulse → Vault.

Setup

Set one environment variable on every module:

PRANOR_OTLP_ENDPOINT=http://pranor-trace:8090

View Traces

Open Pranor Console at http://localhost:8083:

  • Waterfall trace view
  • Service dependency map
  • Latency percentiles (p50, p95, p99)
  • Error rate tracking
  • Trace search by ID, service, duration

Metrics

Every module exposes Prometheus-compatible metrics at GET /metrics:

MetricTypeDescription
pranor_http_requests_totalCounterTotal HTTP requests by route, method, status
pranor_http_duration_secondsHistogramRequest latency distribution
pranor_queue_messages_totalCounterMessages published/consumed (Pulse)
pranor_queue_consumer_lagGaugeConsumer group lag (Pulse)
pranor_cache_hits_totalCounterCache hit/miss ratio (Cache)
pranor_pool_connections_activeGaugeActive DB connections (Pool)
pranor_vault_objects_totalGaugeStored objects count (Vault)

Structured Logging

All modules emit JSON-structured logs with trace correlation:

{
  "level": "info",
  "msg": "request completed",
  "trace_id": "abc123def456",
  "span_id": "789xyz",
  "service": "pranor-gate",
  "duration_ms": 42,
  "status": 200
}

Alerting

Pranor Console supports SLO-based burn rate alerts:

  • Define SLOs (99.9% availability, p95 < 200ms)
  • Multi-window burn rate detection
  • Alert routing to Slack, email, PagerDuty

Health Checks

Every module exposes:

EndpointPurpose
GET /healthzLiveness (is the process running?)
GET /readyzReadiness (can it serve traffic?)
GET /metricsPrometheus metrics

Grafana Integration

Pranor Trace implements the Prometheus remote-write receiver protocol. Point your existing Grafana at:

Data Source: Prometheus
URL: http://pranor-trace:8090/api/v1/query

Next Steps

Complete Pranor Ecosystem Error Code Reference

This document provides an exhaustive, centralized index of all 140+ unique error codes used across Pranor microservices and language tools.

Every HTTP error response follows the standard format:

{
  "error": "Detailed description",
  "code": "ERR_EXAMPLE_CODE",
  "status": 400
}

Pranor Auth (9 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/auth service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/auth service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/auth service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/auth service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/auth service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/auth service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/auth service layer.
ERR_SESSION_REVOKEDDomain PolicyError triggered in pranor/auth service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/auth service layer.

Pranor Cache (6 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/cache service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/cache service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/cache service layer.
ERR_INVALID_PAYLOADClient ErrorError triggered in pranor/cache service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/cache service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/cache service layer.

Pranor Chrono (7 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_ADD_JOB_FAILEDServer ErrorError triggered in pranor/chrono service layer.
ERR_BAD_REQUESTClient ErrorError triggered in pranor/chrono service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/chrono service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/chrono service layer.
ERR_JOB_NOT_FOUNDDomain PolicyError triggered in pranor/chrono service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/chrono service layer.
ERR_TRIGGER_JOB_FAILEDServer ErrorError triggered in pranor/chrono service layer.

Pranor Console (40 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_ALERT_NOT_FOUNDDomain PolicyError triggered in pranor/console service layer.
ERR_BAD_REQUESTClient ErrorError triggered in pranor/console service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/console service layer.
ERR_CACHE_UNREACHABLEServer ErrorError triggered in pranor/console service layer.
ERR_CLOUD_UNREACHABLEServer ErrorError triggered in pranor/console service layer.
ERR_CONFIG_LOAD_FAILEDServer ErrorError triggered in pranor/console service layer.
ERR_CONFIG_SAVE_FAILEDServer ErrorError triggered in pranor/console service layer.
ERR_CREATE_REQUEST_FAILEDServer ErrorError triggered in pranor/console service layer.
ERR_CRON_UNREACHABLEServer ErrorError triggered in pranor/console service layer.
ERR_DEPLOYMENT_NOT_FOUNDDomain PolicyError triggered in pranor/console service layer.
ERR_EE_REQUIREDDomain PolicyError triggered in pranor/console service layer.
ERR_ENTERPRISE_REQUIREDDomain PolicyError triggered in pranor/console service layer.
ERR_FETCH_TRACE_FAILEDServer ErrorError triggered in pranor/console service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/console service layer.
ERR_INTERNALServer ErrorError triggered in pranor/console service layer.
ERR_INTERNAL_ERRORServer ErrorError triggered in pranor/console service layer.
ERR_INVALID_BODYClient ErrorError triggered in pranor/console service layer.
ERR_INVALID_ENVIRONMENTClient ErrorError triggered in pranor/console service layer.
ERR_INVALID_PAYLOADClient ErrorError triggered in pranor/console service layer.
ERR_INVALID_ROUTE_PAYLOADClient ErrorError triggered in pranor/console service layer.
ERR_INVALID_SPAN_FORMATClient ErrorError triggered in pranor/console service layer.
ERR_LOCK_CONNECTDomain PolicyError triggered in pranor/console service layer.
ERR_MESH_UNREACHABLEServer ErrorError triggered in pranor/console service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/console service layer.
ERR_MISSING_FIELDSClient ErrorError triggered in pranor/console service layer.
ERR_MISSING_IDClient ErrorError triggered in pranor/console service layer.
ERR_MISSING_PARAMClient ErrorError triggered in pranor/console service layer.
ERR_MISSING_TRACE_IDClient ErrorError triggered in pranor/console service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/console service layer.
ERR_PARSE_TRACE_FAILEDServer ErrorError triggered in pranor/console service layer.
ERR_REGISTRY_UNREACHABLEServer ErrorError triggered in pranor/console service layer.
ERR_ROUTE_NOT_FOUNDDomain PolicyError triggered in pranor/console service layer.
ERR_RUNBOOK_NOT_FOUNDDomain PolicyError triggered in pranor/console service layer.
ERR_SECRET_CONNECTDomain PolicyError triggered in pranor/console service layer.
ERR_TENANT_ID_REQUIREDDomain PolicyError triggered in pranor/console service layer.
ERR_TESTDomain PolicyError triggered in pranor/console service layer.
ERR_TRACE_ID_REQUIREDDomain PolicyError triggered in pranor/console service layer.
ERR_TRACE_NOT_FOUNDDomain PolicyError triggered in pranor/console service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/console service layer.
ERR_UNSUPPORTED_DRIVERDomain PolicyError triggered in pranor/console service layer.

Pranor Core (10 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_API_KEY_REQUIREDDomain PolicyError triggered in pranor/core service layer.
ERR_BAD_REQUESTClient ErrorError triggered in pranor/core service layer.
ERR_CHAOS_DROPPEDDomain PolicyError triggered in pranor/core service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/core service layer.
ERR_INVALID_TOKENClient ErrorError triggered in pranor/core service layer.
ERR_MISSING_AUTHClient ErrorError triggered in pranor/core service layer.
ERR_RATE_LIMIT_EXCEEDEDDomain PolicyError triggered in pranor/core service layer.
ERR_SCOPE_REQUIREDDomain PolicyError triggered in pranor/core service layer.
ERR_TENANT_MISMATCHDomain PolicyError triggered in pranor/core service layer.
ERR_VALIDATION_FAILEDServer ErrorError triggered in pranor/core service layer.

Pranor Deploy (8 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/deploy service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/deploy service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/deploy service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/deploy service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/deploy service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/deploy service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/deploy service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/deploy service layer.

Pranor Flow (8 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/flow service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/flow service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/flow service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/flow service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/flow service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/flow service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/flow service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/flow service layer.

Pranor Gate (36 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_ACCESS_DENIEDDomain PolicyError triggered in pranor/gate service layer.
ERR_AI_WAF_BLOCKEDDomain PolicyError triggered in pranor/gate service layer.
ERR_BACKPRESSURE_TIMEOUTDomain PolicyError triggered in pranor/gate service layer.
ERR_BAD_GATEWAYClient ErrorError triggered in pranor/gate service layer.
ERR_BAD_GATEWAY_TARGETClient ErrorError triggered in pranor/gate service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/gate service layer.
ERR_CIRCUIT_OPENDomain PolicyError triggered in pranor/gate service layer.
ERR_CONFIG_LOAD_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_CONFIG_SAVE_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_EE_REQUIREDDomain PolicyError triggered in pranor/gate service layer.
ERR_FORBIDDEN_ROUTEClient ErrorError triggered in pranor/gate service layer.
ERR_GO_PLUGIN_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/gate service layer.
ERR_INVALID_API_KEYClient ErrorError triggered in pranor/gate service layer.
ERR_INVALID_PATHClient ErrorError triggered in pranor/gate service layer.
ERR_INVALID_PAYLOADClient ErrorError triggered in pranor/gate service layer.
ERR_INVALID_ROUTE_PAYLOADClient ErrorError triggered in pranor/gate service layer.
ERR_IP_ACCESS_DENIEDDomain PolicyError triggered in pranor/gate service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/gate service layer.
ERR_MISSING_API_KEYClient ErrorError triggered in pranor/gate service layer.
ERR_POLICY_DENIEDDomain PolicyError triggered in pranor/gate service layer.
ERR_PROMPT_INJECTION_DETECTEDDomain PolicyError triggered in pranor/gate service layer.
ERR_QUEUE_BRIDGE_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_QUEUE_FULLDomain PolicyError triggered in pranor/gate service layer.
ERR_QUEUE_RESPONSE_ERRORDomain PolicyError triggered in pranor/gate service layer.
ERR_RATE_LIMIT_EXCEEDEDDomain PolicyError triggered in pranor/gate service layer.
ERR_ROUTE_NOT_FOUNDDomain PolicyError triggered in pranor/gate service layer.
ERR_SCHEMA_VALIDATION_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_TENANT_ACCESS_DENIEDDomain PolicyError triggered in pranor/gate service layer.
ERR_TENANT_POLICY_VIOLATIONDomain PolicyError triggered in pranor/gate service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/gate service layer.
ERR_VALIDATION_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_WASM_COMPILATION_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_WASM_MIDDLEWARE_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_WS_HIJACK_FAILEDServer ErrorError triggered in pranor/gate service layer.
ERR_WS_HIJACK_NOT_SUPPORTEDDomain PolicyError triggered in pranor/gate service layer.

Pranor Hub (26 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/hub service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/hub service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/hub service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/hub service layer.
ERR_INVALID_JWTClient ErrorError triggered in pranor/hub service layer.
ERR_INVALID_PACKAGE_VERSIONClient ErrorError triggered in pranor/hub service layer.
ERR_INVALID_PATHClient ErrorError triggered in pranor/hub service layer.
ERR_INVALID_PUBLIC_KEYClient ErrorError triggered in pranor/hub service layer.
ERR_INVALID_SCHEMAClient ErrorError triggered in pranor/hub service layer.
ERR_INVALID_SIGNATUREClient ErrorError triggered in pranor/hub service layer.
ERR_METADATA_UPLOAD_FAILEDServer ErrorError triggered in pranor/hub service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/hub service layer.
ERR_MISSING_FILENAMEClient ErrorError triggered in pranor/hub service layer.
ERR_MISSING_NAME_PARAMETERClient ErrorError triggered in pranor/hub service layer.
ERR_MISSING_SIGNATUREClient ErrorError triggered in pranor/hub service layer.
ERR_NAME_REQUIREDDomain PolicyError triggered in pranor/hub service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/hub service layer.
ERR_PACKAGE_NOT_FOUNDDomain PolicyError triggered in pranor/hub service layer.
ERR_PACKAGE_UPLOAD_FAILEDServer ErrorError triggered in pranor/hub service layer.
ERR_PROVENANCE_NOT_FOUNDDomain PolicyError triggered in pranor/hub service layer.
ERR_SCHEMA_NOT_FOUNDDomain PolicyError triggered in pranor/hub service layer.
ERR_SIGNATURE_UPLOAD_FAILEDServer ErrorError triggered in pranor/hub service layer.
ERR_SIGNATURE_VERIFICATION_FAILEDServer ErrorError triggered in pranor/hub service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/hub service layer.
ERR_VERSION_CONFLICTDomain PolicyError triggered in pranor/hub service layer.
ERR_VERSION_NOT_FOUNDDomain PolicyError triggered in pranor/hub service layer.

Pranor Lang (14 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_FORBIDDENClient ErrorError triggered in pranor/lang service layer.
ERR_RATE_LIMIT_EXCEEDEDDomain PolicyError triggered in pranor/lang service layer.
ERR_ROUTE_NOT_FOUNDDomain PolicyError triggered in pranor/lang service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/lang service layer.
SRV-E001Domain PolicyError triggered in pranor/lang service layer.
SRV-E002Domain PolicyError triggered in pranor/lang service layer.
SRV-E003Domain PolicyError triggered in pranor/lang service layer.
SRV-E004Domain PolicyError triggered in pranor/lang service layer.
SRV-E005Domain PolicyError triggered in pranor/lang service layer.
SRV-E006Domain PolicyError triggered in pranor/lang service layer.
SRV-E007Domain PolicyError triggered in pranor/lang service layer.
SRV-E008Domain PolicyError triggered in pranor/lang service layer.
SRV-E009Domain PolicyError triggered in pranor/lang service layer.
SRV-E010Domain PolicyError triggered in pranor/lang service layer.

Pranor Mesh (8 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/mesh service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/mesh service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/mesh service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/mesh service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/mesh service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/mesh service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/mesh service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/mesh service layer.

Pranor Notify (6 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/notify service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/notify service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/notify service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/notify service layer.
ERR_TEMPLATE_COMPILE_ERRORDomain PolicyError triggered in pranor/notify service layer.
ERR_UNSUPPORTED_CHANNELDomain PolicyError triggered in pranor/notify service layer.

Pranor Pool (9 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/pool service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/pool service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/pool service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/pool service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/pool service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/pool service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/pool service layer.
ERR_SERVICE_UNAVAILABLEDomain PolicyError triggered in pranor/pool service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/pool service layer.

Pranor Pulse (22 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/pulse service layer.
ERR_BAD_REQUEST_BODYClient ErrorError triggered in pranor/pulse service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/pulse service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/pulse service layer.
ERR_INVALID_PATHClient ErrorError triggered in pranor/pulse service layer.
ERR_INVALID_TOKENClient ErrorError triggered in pranor/pulse service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/pulse service layer.
ERR_MISSING_AUTH_HEADERClient ErrorError triggered in pranor/pulse service layer.
ERR_MISSING_DLQ_TOPICClient ErrorError triggered in pranor/pulse service layer.
ERR_MISSING_FIELDSClient ErrorError triggered in pranor/pulse service layer.
ERR_MISSING_PARAMETERSClient ErrorError triggered in pranor/pulse service layer.
ERR_MISSING_TOPICClient ErrorError triggered in pranor/pulse service layer.
ERR_MISSING_TOPIC_PARAMETERClient ErrorError triggered in pranor/pulse service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/pulse service layer.
ERR_QUERY_FAILEDServer ErrorError triggered in pranor/pulse service layer.
ERR_RATE_LIMIT_EXCEEDEDDomain PolicyError triggered in pranor/pulse service layer.
ERR_REPLAY_FAILEDServer ErrorError triggered in pranor/pulse service layer.
ERR_SEEK_FAILEDServer ErrorError triggered in pranor/pulse service layer.
ERR_SQLITE_UNAVAILABLEDomain PolicyError triggered in pranor/pulse service layer.
ERR_STREAMING_UNSUPPORTEDDomain PolicyError triggered in pranor/pulse service layer.
ERR_WASM_COMPILATION_FAILEDServer ErrorError triggered in pranor/pulse service layer.
ERR_WASM_TRANSFORM_FAILEDServer ErrorError triggered in pranor/pulse service layer.

Pranor Secret (5 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/secret service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/secret service layer.
ERR_INTERNALServer ErrorError triggered in pranor/secret service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/secret service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/secret service layer.

Pranor Trace (8 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/trace service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/trace service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/trace service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/trace service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/trace service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/trace service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/trace service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/trace service layer.

Pranor Tunnel (10 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_GATEWAYClient ErrorError triggered in pranor/tunnel service layer.
ERR_BAD_REQUESTClient ErrorError triggered in pranor/tunnel service layer.
ERR_CONFLICTDomain PolicyError triggered in pranor/tunnel service layer.
ERR_FORBIDDENClient ErrorError triggered in pranor/tunnel service layer.
ERR_GATEWAY_TIMEOUTDomain PolicyError triggered in pranor/tunnel service layer.
ERR_INTERNAL_SERVER_ERRORServer ErrorError triggered in pranor/tunnel service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/tunnel service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/tunnel service layer.
ERR_NOT_IMPLEMENTEDDomain PolicyError triggered in pranor/tunnel service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/tunnel service layer.

Pranor Vault (29 Error Codes)

Error CodeCategoryDescription / Typical Trigger
ERR_BAD_REQUESTClient ErrorError triggered in pranor/vault service layer.
ERR_CLUSTER_NOT_ENABLEDDomain PolicyError triggered in pranor/vault service layer.
ERR_INVALID_PATHClient ErrorError triggered in pranor/vault service layer.
ERR_INVALID_POLICYClient ErrorError triggered in pranor/vault service layer.
ERR_INVALID_REQUEST_BODYClient ErrorError triggered in pranor/vault service layer.
ERR_INVALID_STATEClient ErrorError triggered in pranor/vault service layer.
ERR_METHOD_NOT_ALLOWEDDomain PolicyError triggered in pranor/vault service layer.
ERR_MISSING_CODEClient ErrorError triggered in pranor/vault service layer.
ERR_MISSING_PARAMETERClient ErrorError triggered in pranor/vault service layer.
ERR_NOT_FOUNDDomain PolicyError triggered in pranor/vault service layer.
ERR_NOT_LEADERDomain PolicyError triggered in pranor/vault service layer.
ERR_OIDC_AUTH_URL_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_OIDC_NOT_CONFIGUREDDomain PolicyError triggered in pranor/vault service layer.
ERR_PLACEMENT_LOOKUP_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_POLICY_DELETE_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_POLICY_GET_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_POLICY_PUT_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_PRESIGNED_URL_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_RAFT_JOIN_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_RAFT_PROPOSE_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_SCHEMA_GET_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_SCHEMA_LIST_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_SCHEMA_NOT_FOUNDDomain PolicyError triggered in pranor/vault service layer.
ERR_SCHEMA_PUT_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_STORE_PUT_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_TOKEN_EXCHANGE_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_TOKEN_GENERATION_FAILEDServer ErrorError triggered in pranor/vault service layer.
ERR_UNAUTHORIZEDClient ErrorError triggered in pranor/vault service layer.
ERR_USER_INFO_FAILEDServer ErrorError triggered in pranor/vault service layer.

Pranor Enterprise Edition (EE)

Pranor EE extends the open-source single-binary platform with advanced security, compliance, multi-region high availability, and operational governance capabilities for enterprise engineering teams.


Detailed Enterprise & Open-Source Feature Comparison (By Module)

1. 🚪 Pranor Gate (API Gateway & Ingress Router)

FeatureCommunity OSSEnterprise EE
Ingress Proxy & WASM Middleware✅ Sub-millisecond HTTP/gRPC proxy & WASM hot-swap✅ Zero-downtime TLS hardware PCIe offloading
Kernel eBPF XDP DDoS Bypass100Gbps network packet filtering at Linux kernel level
AI Agent (MCP) Traffic & Prompt Guard✅ MCP JSON-RPC routing & token cost headersSemantic prompt firewall, PII redaction & injection guard
Hardware Accelerator & Bandwidth ShaperDirect PCIe GPU/TPU offloader & noisy-neighbor bandwidth shaper
Geo-IP Anycast & GraphQL FederationReal-time edge Anycast steering & GraphQL schema stitching
CRDT Rate Limiting & DR FailoverGlobal CRDT rate-limiting grid & 1-click active-passive DR
FeatureCommunity OSSEnterprise EE
AWS S3 API & HNSW Vector Search✅ Full S3 SDK compatibility & native HNSW vector search✅ Sovereign vector embedding index isolation
Zero-Knowledge Search & GDPR PurgeEncrypted homomorphic search & automated GDPR zeroization
Audit Trail & Geo-ReplicationImmutable access audit logs & active-active multi-region sync
CoW Branching & Masking / MPCInstant bucket branching, dynamic PII masking & MPC secret split
WORM Retention & Cold TieringSEC 17a-4 retention lock manager & Glacier automated tiering

3. ⚡ Pranor Pulse (Async Event Broker & Queue)

FeatureCommunity OSSEnterprise EE
Multi-Protocol Engine & DLQ Replay✅ Kafka, STOMP, MQTT decoders & 1-click DLQ replay✅ Dedicated per-tenant partition memory pool sharding
Exactly-Once 2PC Transaction CoordinatorTwo-Phase Commit transaction manager enforcing atomic publish
MirrorMaker v2 & Hardware WALCross-cloud event topic mirroring & zero-copy WAL encryption
Blind Broker Encryption & SIMD FilterEnd-to-end payload encryption & SIMD / AVX-512 event filter
Rebalance Tuning & Schema GuardAI consumer rebalance auto-tuning & breaking-change guard

4. 🔀 Pranor Flow & Deploy (Workflows & Fleet Orchestration)

FeatureCommunity OSSEnterprise EE
Durable Saga Orchestrator✅ Stateful transaction coordinator with compensation rollbacks✅ Visual workflow builder, step replay & Raft coordinator
Automated DR Chaos Simulation SuiteIn-situ chaos engineering testing cross-cloud failover SLAs
AI FinOps & Blue/Green PromotionCloud cost guardrails & zero-downtime blue/green cluster promotion

5. 📡 Pranor Trace & Console (Observability & Governance)

FeatureCommunity OSSEnterprise EE
OTLP Tracing & SQL Workbench✅ Full OTel span collector, flamegraphs & SQL workbench✅ Anomaly auto-remediation runbooks & tail trace sampling
AI Anomaly Auto-Tuner & SIEM StreamerSelf-learning anomaly baseline & SIEM audit log streamer
Regulatory WORM Log & ComplianceSEC Rule 17a-4 WORM vault & real-time compliance inspector
Incident Postmortem & VIP SupportAutomated postmortem synthesizer & 15-min emergency SLA support

6. 🔐 Pranor Auth, Secret, Core & Hub (Security & Identity)

FeatureCommunity OSSEnterprise EE
IAM & KMS Envelope Encryption✅ JWKS rotation, MFA, OAuth & KMS key rotation worker✅ Hardware HSM offloading & Vault Transit integration
Confidential Computing EnclaveHardware memory enclave (AMD SEV / Intel SGX) isolation
Multi-Cloud KMS Federation SyncKey synchronization across AWS KMS, Azure Key Vault & GCP KMS
Enterprise Identity & PasskeySCIM 2.0 provisioning, FIDO2/WebAuthn & IdP claim mapping
FIPS 140-3 & Post-Quantum SPIFFEFIPS 140-3 Level 3 engine, Kyber768 PQC & SPIFFE token exchange
Air-Gapped Private Artifact RegistryOffline package registry & RSA-4096 license key verifier

7. ⏰ Pranor Cache, Pool, Chrono, Tunnel & Mesh (Infrastructure)

FeatureCommunity OSSEnterprise EE
Raft KV Cache & Developer Tunnel✅ Distributed in-memory cache & multiplexed local tunnel✅ Sub-millisecond SIMD vector cache & zero-trust private relay
Zero-Downtime DB Schema MigrationOnline DDL schema migration proxy & replica failover coordinator
Smart Cron & Fencing Tokens✅ Mono-lock distributed cron execution with fencing tokens✅ AI off-peak cron window optimizer & multi-region fencing
Zero-Trust Mesh & Microsegmentation✅ Library-level sidecarless mTLS mesh & auto-discovery✅ Hardware TPM attestation, cross-VPC peering & L7 microsegmentation

Complete Interactive Features Matrix & Licensing

For the full interactive table listing all 137+ Community OSS and Enterprise EE capabilities with search filtering:

Enterprise features compile cleanly behind //go:build enterprise build tags into the standard single binary:

# Compile single binary with all Enterprise Edition capabilities enabled
go build -tags enterprise -o pranord ./cmd/pranord

For commercial licensing inquiries, pilot programs, or dedicated support contracts:


Enterprise Licensing & Edition Split

Pranor is distributed under a dual-licensing model designed for both open-source developers and enterprise organizations.


Edition Matrix

CapabilityOpen-Source Edition (OSS)Enterprise Edition (EE)
Core Monorepo Modules16 Modules Included16 Modules Included
LicenseApache 2.0 / MITCommercial Enterprise License
High Availability & ClusteringStandalone & Basic MeshActive-Active Multi-Region, Raft Consensus
Security & ComplianceTLS 1.3, JWT, RBACFIPS 140-3, HSM Key Unsealing, PQC (Kyber)
ObservabilityOTel Tracing, MetricseBPF Continuous Profiling, Flamegraphs
SupportCommunity (GitHub / Discord)24/7 SLA, Dedicated Solutions Engineer

Licensing Terms

Open-Source Edition (OSS)

The open-source components in github.com/vyuvaraj/pranor are available for free use, modification, and self-hosted deployment under standard open-source licenses.

Enterprise Edition (EE)

Enterprise overlay modules in github.com/vyuvaraj/pranor-ee require a commercial license key issued by Pranor Inc. Features are gated at compile time using Go build tags (//go:build enterprise).

Pranor Unified Changelog

The Pranor platform and background microservice ecosystem undergo continuous evolution across language tooling, gateways, brokers, storage engines, and observability collectors.


[v1.0.0] - Production Release

Language & Tooling (Pranor CLI, LSP & IDE Extension)

  • Unified Single-Binary Daemon: Embedded all 17 background microservices into a single pranord executable.
  • Language Server Protocol (LSP): Advanced handlers for workspace-wide fuzzy symbol search (workspace/symbol), call hierarchy inspection (textDocument/prepareCallHierarchy), multi-file symbol renames (textDocument/rename), and document highlighting (textDocument/documentHighlight).
  • VS Code Control Plane (pranor-vscode): Registered interactive webview control panels for Gate (API Client), Pulse (Event Stream Tailer), Vault (Vector Explorer), Trace (Flamegraph Viewer), Secret Manager, and Cluster Deployments.
  • Developer Experience: Interactive CLI setup wizard (pranor quickstart), diagnostic verification tool (pranor doctor), and devcontainer integration.

Core Ecosystem Modules

Pranor Gate (API Gateway & Ingress Router)

  • Edge HTTP/gRPC ingress routing with dynamic mTLS certificate rotation.
  • Token bucket rate limiting per IP / API key.
  • Sandboxed WebAssembly (Wazero) middleware execution.
  • Backpressure load balancing and dynamic IAM token refresh signaling.

Pranor Pulse (Async Event Broker & Message Queue)

  • Multi-protocol message broker supporting Kafka wire format, STOMP WebSockets, and MQTT 3.1/5.0.
  • Automatic Dead Letter Queue (DLQ) isolation with 1-click message replay.

Pranor Vault (S3 Storage & HNSW Vector Engine)

  • AWS S3 API compatibility (multipart uploads, presigned URLs, bucket policies).
  • Native HNSW vector similarity search (Cosine, Euclidean, Dot-product).
  • Offline S3 mock mode (--mock / PRANOR_VAULT_MOCK=true).

Pranor Flow (Workflow Engine & Durable Sagas)

  • Durable saga orchestrator with HTTP/STOMP compensation rollbacks.
  • Asynchronous STOMP compensation notifications over Pulse topics.

Pranor Auth, Cache, Mesh & Trace

  • Auth: Identity server with JWKS, TOTP MFA, Social OAuth, and KMS envelope key rotation.
  • Cache: Raft-based key-value caching with adaptive connection pool tuning.
  • Mesh: Zero-trust in-memory service discovery with gRPC JSON-codec transport.
  • Trace: OTLP/HTTP distributed tracing collector, flamegraph viewer, and Prometheus remote write ingestion.

External Connectors & Integrations

  • Terraform Provider (terraform-provider-pranor): Declarative management of buckets, topics, cron jobs, and gateway routes.
  • GitHub Action (pranor/deploy-action@v1): Automated CI/CD compilation and blue/green deployments.
  • Grafana Datasource Plugin: Direct visualization of Pranor Trace spans and Pulse queue metrics in Grafana.