Skip to content

Fulcrum: System Context Document

Version: 1.1.0
Date: 2026-01-03 (Updated from December 10, 2025 original)
Purpose: Implementation guide bridging architecture decisions to service implementation
Audience: Implementation teams (Claude Code, Cursor, engineers)


Document Structure

  1. System Overview
  2. Service Catalog
  3. Data Flows
  4. API Contracts
  5. Error Handling
  6. Security Model
  7. Phase 1 Scope

System Overview

Architecture Philosophy

Fulcrum is a governance layer, not an orchestration framework. It wraps existing agent orchestrators (LangGraph, Microsoft Agent Framework, CrewAI) with:

  • Cost governance - Budget limits, token tracking, circuit breakers
  • Policy enforcement - Pre/mid/post-execution authorization
  • Unified observability - Cross-framework telemetry and audit trails

Core Abstraction

The Execution Envelope is Fulcrum's unit of governance. Every agent execution—regardless of framework—is wrapped in an Envelope that captures:

Execution Envelope
├── Identification (tenant_id, envelope_id, execution_id)
├── Governance Context (budget_id, policy_set, token_limit, cost_limit)
├── Framework Context (adapter_type, native_ref, checkpoint_id)
├── Lifecycle State (PENDING → AUTHORIZED → RUNNING → COMPLETED)
└── Cost Summary (tokens_used, cost_usd, llm_calls, tool_calls)

High-Level Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                           CONTROL PLANE                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐               │
│  │   Gateway    │  │   Admin UI   │  │     CLI      │               │
│  │  (HTTP/gRPC) │  │   (React)    │  │    (Go)      │               │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘               │
│         │                 │                 │                        │
│         └─────────────────┼─────────────────┘                        │
│                           ▼                                          │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │                     SERVICE MESH                                │ │
│  ├────────────┬────────────┬────────────┬────────────────────────┤ │
│  │  Envelope  │   Policy   │   Budget   │   Event Processor      │ │
│  │  Service   │   Service  │   Service  │                        │ │
│  └─────┬──────┴─────┬──────┴─────┬──────┴──────────┬─────────────┘ │
│        │            │            │                  │               │
│        ▼            ▼            ▼                  ▼               │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                    DATA LAYER                                  │  │
│  │  PostgreSQL (Envelopes, Policies, Budgets, Tenants)           │  │
│  │  TimescaleDB (Cost time-series, Token metrics)                │  │
│  │  Redis (Policy cache, Budget cache, Rate limits)              │  │
│  │  NATS JetStream (Event bus, Durable queues)                   │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘
                    ┌───────────────┼───────────────┐
                    ▼               ▼               ▼
             ┌──────────┐   ┌──────────┐   ┌──────────┐
             │ LangGraph│   │ Microsoft│   │  A2A     │
             │ Adapter  │   │ Adapter  │   │  Proxy   │
             └────┬─────┘   └────┬─────┘   └────┬─────┘
                  ▼              ▼              ▼
             ┌──────────┐   ┌──────────┐   ┌──────────┐
             │ LangGraph│   │ MS Agent │   │ External │
             │ Runtime  │   │ Framework│   │ Agents   │
             └──────────┘   └──────────┘   └──────────┘

Service Catalog

Phase 1 Services

Service Responsibility Port Protocol
Gateway API routing, auth, rate limiting 8080 HTTP/gRPC
Envelope Service Envelope lifecycle management 8081 gRPC
Policy Service Policy evaluation, authorization 8082 gRPC
Budget Service Budget CRUD, enforcement 8083 gRPC
Event Processor Event ingestion, cost aggregation - NATS consumer

Service Dependencies

Gateway
├── depends: Envelope Service (sync)
├── depends: Policy Service (sync)
├── depends: Budget Service (sync)
└── depends: Redis (auth cache)

Envelope Service
├── depends: PostgreSQL (envelope storage)
├── depends: Policy Service (authorization check)
├── depends: Budget Service (budget validation)
└── publishes: NATS (envelope events)

Policy Service
├── depends: PostgreSQL (policy definitions)
├── depends: Redis (policy cache)
└── publishes: NATS (policy violation events)

Budget Service
├── depends: PostgreSQL (budget definitions)
├── depends: TimescaleDB (cost aggregates)
├── depends: Redis (budget cache)
└── publishes: NATS (budget alerts)

Event Processor
├── subscribes: NATS (all events)
├── depends: PostgreSQL (event storage)
├── depends: TimescaleDB (cost writes)
└── depends: Budget Service (real-time enforcement)

Data Flows

Flow 1: Execution Start (Happy Path)

SDK/Adapter                Gateway              Envelope           Policy            Budget
    │                         │                   │                  │                 │
    │──POST /envelopes────────▶                   │                  │                 │
    │                         │──CreateEnvelope───▶                  │                 │
    │                         │                   │──CheckPolicy─────▶                 │
    │                         │                   │◀─────ALLOW───────│                 │
    │                         │                   │──ValidateBudget──────────────────▶│
    │                         │                   │◀─────VALID────────────────────────│
    │                         │                   │                  │                 │
    │                         │                   │──[Store Envelope]│                 │
    │                         │                   │──[Publish Event]─┼────────────────▶ NATS
    │                         │◀─Envelope(AUTHORIZED)                │                 │
    │◀──201 Created───────────│                   │                  │                 │

Flow 2: Mid-Execution Budget Check

Adapter                Event Processor          Budget            Envelope
   │                         │                    │                  │
   │──[LLM Call Complete]────▶                    │                  │
   │──Event(tokens=500)──────▶                    │                  │
   │                         │──UpdateUsage───────▶                  │
   │                         │                    │                  │
   │                         │  [Budget at 80%]   │                  │
   │                         │◀─WARNING───────────│                  │
   │                         │──PublishAlert──────┼─────────────────▶ NATS
   │                         │                    │                  │
   │                    [Budget at 100%]          │                  │
   │                         │──EXCEEDED──────────▶                  │
   │                         │                    │──TerminateEnvelope─▶
   │◀─────TerminateSignal────│                    │                  │

Flow 3: Policy Violation

Adapter               Gateway              Policy            Envelope
   │                     │                   │                  │
   │──ToolInvocation─────▶                   │                  │
   │  (tool=browser)     │──CheckPolicy──────▶                  │
   │                     │                   │                  │
   │                     │  [Policy: DENY browser]              │
   │                     │◀─DENY(reason)─────│                  │
   │                     │                   │──LogViolation────▶
   │                     │                   │──[Publish Event]─▶ NATS
   │◀─403 PolicyViolation─│                   │                  │

Flow 4: Checkpoint and Resume

Adapter               Envelope            Checkpoint Store
   │                     │                      │
   │──CaptureCheckpoint──▶                      │
   │                     │──StoreState──────────▶
   │                     │◀─checkpoint_id───────│
   │◀─CheckpointRef──────│                      │
   │                     │                      │
   │    [Later...]       │                      │
   │                     │                      │
   │──RestoreCheckpoint──▶                      │
   │  (checkpoint_id)    │──LoadState───────────▶
   │                     │◀─state───────────────│
   │◀─ResumedExecution───│                      │

API Contracts

Envelope API (OpenAPI 3.1)

openapi: 3.1.0
info:
  title: Fulcrum Envelope API
  version: 1.0.0
  description: Execution Envelope lifecycle management

paths:
  /v1/envelopes:
    post:
      operationId: createEnvelope
      summary: Create a new Execution Envelope
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEnvelopeRequest'
      responses:
        '201':
          description: Envelope created and authorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope'
        '403':
          description: Policy denied execution
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyViolation'
        '422':
          description: Budget exhausted or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BudgetError'

  /v1/envelopes/{envelope_id}:
    get:
      operationId: getEnvelope
      summary: Get envelope by ID
      parameters:
        - name: envelope_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Envelope found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope'
        '404':
          description: Envelope not found

  /v1/envelopes/{envelope_id}/events:
    post:
      operationId: recordEvent
      summary: Record an event against an envelope
      parameters:
        - name: envelope_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EventRecord'
      responses:
        '202':
          description: Event accepted
        '409':
          description: Envelope terminated or completed

  /v1/envelopes/{envelope_id}/terminate:
    post:
      operationId: terminateEnvelope
      summary: Force terminate an execution
      parameters:
        - name: envelope_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TerminateRequest'
      responses:
        '200':
          description: Envelope terminated
        '409':
          description: Already completed or terminated

components:
  schemas:
    CreateEnvelopeRequest:
      type: object
      required:
        - tenant_id
        - budget_id
        - adapter_type
      properties:
        tenant_id:
          type: string
          format: uuid
        budget_id:
          type: string
          format: uuid
        adapter_type:
          type: string
          enum: [langgraph, microsoft, crewai, a2a_proxy, custom]
        policy_set:
          type: array
          items:
            type: string
        metadata:
          type: object
          additionalProperties: true

    Envelope:
      type: object
      properties:
        envelope_id:
          type: string
          format: uuid
        tenant_id:
          type: string
          format: uuid
        budget_id:
          type: string
          format: uuid
        execution_id:
          type: string
        adapter_type:
          type: string
        state:
          type: string
          enum: [PENDING, AUTHORIZED, RUNNING, PAUSED, COMPLETED, FAILED, TERMINATED]
        governance_context:
          $ref: '#/components/schemas/GovernanceContext'
        cost_summary:
          $ref: '#/components/schemas/CostSummary'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    GovernanceContext:
      type: object
      properties:
        token_limit:
          type: integer
        cost_limit_usd:
          type: number
          format: double
        timeout_seconds:
          type: integer
        policy_set:
          type: array
          items:
            type: string

    CostSummary:
      type: object
      properties:
        tokens_input:
          type: integer
        tokens_output:
          type: integer
        tokens_total:
          type: integer
        cost_usd:
          type: number
          format: double
        llm_calls:
          type: integer
        tool_calls:
          type: integer

    EventRecord:
      type: object
      required:
        - event_type
        - timestamp
      properties:
        event_type:
          type: string
        timestamp:
          type: string
          format: date-time
        tokens:
          type: object
          properties:
            input:
              type: integer
            output:
              type: integer
            model:
              type: string
            cost_usd:
              type: number
        payload:
          type: object

    TerminateRequest:
      type: object
      properties:
        reason:
          type: string
        force:
          type: boolean
          default: false

    PolicyViolation:
      type: object
      properties:
        code:
          type: string
        policy_id:
          type: string
        message:
          type: string
        denied_action:
          type: string

    BudgetError:
      type: object
      properties:
        code:
          type: string
        budget_id:
          type: string
        current_usage:
          type: number
        limit:
          type: number
        message:
          type: string

Budget API (OpenAPI 3.1)

openapi: 3.1.0
info:
  title: Fulcrum Budget API
  version: 1.0.0
  description: Budget management and enforcement

paths:
  /v1/budgets:
    post:
      operationId: createBudget
      summary: Create a new budget
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBudgetRequest'
      responses:
        '201':
          description: Budget created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'
    get:
      operationId: listBudgets
      summary: List budgets for tenant
      parameters:
        - name: tenant_id
          in: query
          required: true
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          schema:
            type: string
            enum: [active, exhausted, expired, all]
      responses:
        '200':
          description: Budget list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Budget'

  /v1/budgets/{budget_id}:
    get:
      operationId: getBudget
      summary: Get budget by ID
      parameters:
        - name: budget_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Budget found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Budget'

  /v1/budgets/{budget_id}/usage:
    get:
      operationId: getBudgetUsage
      summary: Get real-time budget usage
      parameters:
        - name: budget_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Current usage
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BudgetUsage'

  /v1/budgets/{budget_id}/check:
    post:
      operationId: checkBudget
      summary: Check if budget allows execution
      description: Returns whether the proposed execution fits within budget constraints
      parameters:
        - name: budget_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BudgetCheckRequest'
      responses:
        '200':
          description: Budget check result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BudgetCheckResult'

components:
  schemas:
    CreateBudgetRequest:
      type: object
      required:
        - tenant_id
        - name
        - type
      properties:
        tenant_id:
          type: string
          format: uuid
        name:
          type: string
        type:
          type: string
          enum: [token, cost, hybrid]
        limits:
          $ref: '#/components/schemas/BudgetLimits'
        alerts:
          type: array
          items:
            $ref: '#/components/schemas/AlertThreshold'
        period:
          type: string
          enum: [hourly, daily, weekly, monthly, total]
        expires_at:
          type: string
          format: date-time

    Budget:
      type: object
      properties:
        budget_id:
          type: string
          format: uuid
        tenant_id:
          type: string
          format: uuid
        name:
          type: string
        type:
          type: string
        status:
          type: string
          enum: [active, exhausted, expired]
        limits:
          $ref: '#/components/schemas/BudgetLimits'
        usage:
          $ref: '#/components/schemas/BudgetUsage'
        alerts:
          type: array
          items:
            $ref: '#/components/schemas/AlertThreshold'
        created_at:
          type: string
          format: date-time

    BudgetLimits:
      type: object
      properties:
        max_tokens:
          type: integer
          description: Maximum tokens per period (null = unlimited)
        max_cost_usd:
          type: number
          format: double
          description: Maximum cost in USD per period (null = unlimited)
        max_executions:
          type: integer
          description: Maximum envelope count per period

    BudgetUsage:
      type: object
      properties:
        tokens_used:
          type: integer
        cost_usd:
          type: number
          format: double
        executions:
          type: integer
        percent_tokens:
          type: number
        percent_cost:
          type: number
        period_start:
          type: string
          format: date-time
        period_end:
          type: string
          format: date-time

    AlertThreshold:
      type: object
      properties:
        percent:
          type: integer
          minimum: 1
          maximum: 100
        action:
          type: string
          enum: [notify, warn, terminate]
        webhook_url:
          type: string
          format: uri

    BudgetCheckRequest:
      type: object
      properties:
        estimated_tokens:
          type: integer
        estimated_cost_usd:
          type: number

    BudgetCheckResult:
      type: object
      properties:
        allowed:
          type: boolean
        reason:
          type: string
        remaining_tokens:
          type: integer
        remaining_cost_usd:
          type: number
        warnings:
          type: array
          items:
            type: string

Policy API (OpenAPI 3.1)

openapi: 3.1.0
info:
  title: Fulcrum Policy API
  version: 1.0.0
  description: Policy definition and evaluation

paths:
  /v1/policies:
    post:
      operationId: createPolicy
      summary: Create a new policy
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePolicyRequest'
      responses:
        '201':
          description: Policy created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Policy'
    get:
      operationId: listPolicies
      summary: List policies for tenant
      parameters:
        - name: tenant_id
          in: query
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Policy list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Policy'

  /v1/policies/{policy_id}:
    get:
      operationId: getPolicy
      summary: Get policy by ID
      parameters:
        - name: policy_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Policy found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Policy'

  /v1/policies/evaluate:
    post:
      operationId: evaluatePolicy
      summary: Evaluate policies against an action
      description: Check if an action is allowed by the applicable policy set
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PolicyEvaluationRequest'
      responses:
        '200':
          description: Evaluation result
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PolicyEvaluationResult'

components:
  schemas:
    CreatePolicyRequest:
      type: object
      required:
        - tenant_id
        - name
        - rules
      properties:
        tenant_id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
        rules:
          type: array
          items:
            $ref: '#/components/schemas/PolicyRule'
        priority:
          type: integer
          description: Higher priority policies evaluate first

    Policy:
      type: object
      properties:
        policy_id:
          type: string
          format: uuid
        tenant_id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
        rules:
          type: array
          items:
            $ref: '#/components/schemas/PolicyRule'
        priority:
          type: integer
        enabled:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    PolicyRule:
      type: object
      required:
        - action
        - effect
      properties:
        action:
          type: string
          description: 'Action pattern (e.g., "tool:*", "llm:gpt-4*", "execution:start")'
        effect:
          type: string
          enum: [allow, deny]
        conditions:
          type: array
          items:
            $ref: '#/components/schemas/PolicyCondition'

    PolicyCondition:
      type: object
      properties:
        field:
          type: string
          description: 'Context field to check (e.g., "request.model", "budget.percent_used")'
        operator:
          type: string
          enum: [eq, neq, gt, gte, lt, lte, in, not_in, matches]
        value:
          description: Value to compare against

    PolicyEvaluationRequest:
      type: object
      required:
        - tenant_id
        - action
      properties:
        tenant_id:
          type: string
          format: uuid
        envelope_id:
          type: string
          format: uuid
        policy_set:
          type: array
          items:
            type: string
          description: Specific policies to evaluate (empty = all tenant policies)
        action:
          type: string
          description: Action being requested
        context:
          type: object
          additionalProperties: true
          description: Additional context for condition evaluation

    PolicyEvaluationResult:
      type: object
      properties:
        allowed:
          type: boolean
        effect:
          type: string
          enum: [allow, deny, no_match]
        matched_policy:
          type: string
        matched_rule:
          type: string
        reason:
          type: string
        evaluation_time_ms:
          type: number

Error Handling

Error Code Taxonomy

All Fulcrum errors follow a structured code format: FULCRUM-{DOMAIN}-{CODE}

Domain Code Range Description
ENV 1000-1999 Envelope errors
POL 2000-2999 Policy errors
BUD 3000-3999 Budget errors
EVT 4000-4999 Event errors
ADP 5000-5999 Adapter errors
SYS 9000-9999 System errors

Standard Error Response

{
  "error": {
    "code": "FULCRUM-BUD-3001",
    "message": "Budget exhausted",
    "details": {
      "budget_id": "uuid",
      "limit": 10000,
      "current": 10234
    },
    "request_id": "req-uuid",
    "timestamp": "2025-12-10T14:30:00Z",
    "documentation_url": "https://docs.fulcrum.io/errors/BUD-3001"
  }
}

Recoverable vs Terminal Errors

Error Type Behavior Client Action
Recoverable Execution can continue Retry with backoff
Terminal Execution must stop Complete envelope as FAILED

Recoverable Errors: - FULCRUM-SYS-9001: Service temporarily unavailable (retry) - FULCRUM-ADP-5002: Checkpoint store timeout (retry) - FULCRUM-EVT-4001: Event delivery failed (buffered retry)

Terminal Errors: - FULCRUM-POL-2001: Policy denied (no retry, requires policy change) - FULCRUM-BUD-3001: Budget exhausted (no retry, requires budget top-up) - FULCRUM-ENV-1003: Envelope already terminated (no retry)

Circuit Breaker Pattern

Services implement circuit breakers for downstream dependencies:

States: CLOSED → OPEN → HALF_OPEN → CLOSED

CLOSED: Normal operation, track failure rate
OPEN: All requests fail-fast (no downstream calls)
HALF_OPEN: Allow probe requests, success → CLOSED, failure → OPEN

Thresholds:
- Open after: 5 failures in 10 seconds
- Half-open after: 30 seconds in OPEN
- Close after: 3 consecutive successes in HALF_OPEN

Graceful Degradation

Dependency Failure Degradation Strategy
Policy Service down Fail-closed (deny all) or cached policy
Budget Service down Fail-open with soft limits from cache
Event Processor down Buffer events locally, replay on recovery
Checkpoint Store down Disable checkpointing, continue execution

Security Model

Authentication

Service-to-Service: mTLS with certificate rotation (Cert-Manager)

Client-to-Gateway: API keys or JWT tokens

Authorization: Bearer <jwt>
X-API-Key: <api_key>
X-Tenant-ID: <tenant_uuid>

Authorization Layers

┌───────────────────────────────────────────────┐
│ Layer 1: API Gateway                          │
│ - Rate limiting (per API key)                 │
│ - JWT validation                              │
│ - Tenant isolation                            │
├───────────────────────────────────────────────┤
│ Layer 2: Service Authorization                │
│ - RBAC for admin operations                   │
│ - Resource ownership validation               │
├───────────────────────────────────────────────┤
│ Layer 3: Policy Engine                        │
│ - Execution-time policy evaluation            │
│ - Tool/LLM access controls                    │
└───────────────────────────────────────────────┘

Tenant Isolation

Database: Row-level security with tenant_id on all tables

CREATE POLICY tenant_isolation ON envelopes
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

NATS: Subject namespacing fulcrum.{tenant_id}.events.*

Redis: Key prefixing {tenant_id}:policy:{policy_id}

Secrets Management

Secret Type Storage Rotation
Database credentials Kubernetes Secrets / Vault 30 days
API keys PostgreSQL (hashed) On demand
JWT signing keys Kubernetes Secrets 90 days
LLM API keys Vault On demand

Audit Trail

All governance actions logged to immutable audit log:

{
  "audit_id": "uuid",
  "timestamp": "2025-12-10T14:30:00Z",
  "tenant_id": "uuid",
  "actor": {
    "type": "api_key",
    "id": "key-uuid"
  },
  "action": "policy.evaluate",
  "resource": {
    "type": "envelope",
    "id": "env-uuid"
  },
  "result": "allow",
  "metadata": {}
}

Phase 1 Scope

In Scope

Component Deliverable Acceptance Criteria
Envelope Service Full CRUD + lifecycle Create, read, update state, terminate
Budget Service CRUD + real-time enforcement Budget checks complete <10ms p99
Policy Service CRUD + evaluation Policy eval complete <5ms p99
Event Processor Event ingestion + cost aggregation Process 10k events/sec
Gateway HTTP API + auth <50ms p99 latency
LangGraph Adapter Embedded middleware All 14 interface methods
SDK (TypeScript) Client library Typed API for all endpoints

Out of Scope (Phase 2+)

  • Admin UI (Phase 2)
  • Microsoft Agent Framework adapter (Phase 2)
  • A2A Protocol Proxy (Phase 3)
  • Multi-region deployment (Phase 4)
  • CLI tool (Phase 5)
  • Additional framework adapters (Phase 4+)

Phase 1 Architecture Constraints

  1. Single region - No cross-region replication
  2. Single PostgreSQL - No read replicas
  3. Synchronous policy checks - Async optimization in Phase 2
  4. LangGraph only - One adapter proves the pattern

Success Metrics

Metric Target Measurement
Envelope creation latency <100ms p99 Gateway logs
Policy evaluation latency <10ms p99 Service metrics
Budget check latency <10ms p99 Service metrics
Event processing throughput 10k/sec NATS consumer lag
System availability 99.9% Uptime monitoring

Implementation Notes

Database Schema (PostgreSQL)

-- Core tables
CREATE TABLE tenants (
  tenant_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name VARCHAR(255) NOT NULL,
  settings JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE budgets (
  budget_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID REFERENCES tenants(tenant_id),
  name VARCHAR(255) NOT NULL,
  type VARCHAR(50) NOT NULL,
  limits JSONB NOT NULL,
  alerts JSONB DEFAULT '[]',
  period VARCHAR(50),
  status VARCHAR(50) DEFAULT 'active',
  expires_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE policies (
  policy_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID REFERENCES tenants(tenant_id),
  name VARCHAR(255) NOT NULL,
  rules JSONB NOT NULL,
  priority INTEGER DEFAULT 0,
  enabled BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE envelopes (
  envelope_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID REFERENCES tenants(tenant_id),
  budget_id UUID REFERENCES budgets(budget_id),
  execution_id VARCHAR(255),
  adapter_type VARCHAR(50) NOT NULL,
  state VARCHAR(50) DEFAULT 'PENDING',
  governance_context JSONB NOT NULL,
  framework_context JSONB DEFAULT '{}',
  cost_summary JSONB DEFAULT '{"tokens_input":0,"tokens_output":0,"cost_usd":0}',
  checkpoint_id UUID,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  completed_at TIMESTAMPTZ
);

CREATE TABLE events (
  event_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  envelope_id UUID REFERENCES envelopes(envelope_id),
  tenant_id UUID REFERENCES tenants(tenant_id),
  event_type VARCHAR(100) NOT NULL,
  tokens JSONB,
  payload JSONB,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE checkpoints (
  checkpoint_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  envelope_id UUID REFERENCES envelopes(envelope_id),
  state_hash VARCHAR(64) NOT NULL,
  state_data BYTEA NOT NULL,
  size_bytes INTEGER NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_envelopes_tenant ON envelopes(tenant_id);
CREATE INDEX idx_envelopes_state ON envelopes(state) WHERE state IN ('RUNNING', 'PENDING');
CREATE INDEX idx_events_envelope ON events(envelope_id);
CREATE INDEX idx_budgets_tenant ON budgets(tenant_id);
CREATE INDEX idx_policies_tenant ON policies(tenant_id);

NATS Subject Hierarchy

fulcrum.
├── {tenant_id}.
│   ├── envelopes.
│   │   ├── created
│   │   ├── started
│   │   ├── completed
│   │   ├── failed
│   │   └── terminated
│   ├── events.
│   │   ├── llm.*
│   │   ├── tool.*
│   │   └── checkpoint.*
│   ├── budgets.
│   │   ├── warning
│   │   └── exceeded
│   └── policies.
│       └── violation
└── system.
    ├── health
    └── metrics

Service Configuration

# config.yaml (all services)
server:
  port: 8081
  grpc_port: 9081
  shutdown_timeout: 30s

database:
  host: ${DB_HOST}
  port: 5432
  name: fulcrum
  pool_size: 20
  ssl_mode: require

redis:
  host: ${REDIS_HOST}
  port: 6379
  pool_size: 10

nats:
  url: ${NATS_URL}
  cluster_id: fulcrum
  client_id: ${SERVICE_NAME}

observability:
  otel_endpoint: ${OTEL_ENDPOINT}
  metrics_port: 9090
  log_level: info
  log_format: json

This document provides the implementation bridge between architectural decisions and service code. Refer to ADRs for decision rationale, protobufs for data contracts, and this document for operational guidance.