npm package: @fulcrum-governance/sdk
Description: TypeScript SDK for Fulcrum - Intelligent AI Governance Platform
Author: Fulcrum Team
Latest version: 0.1.4

# Fulcrum TypeScript SDK

> Intelligent AI Governance for Enterprise Agents

[![npm version](https://badge.fury.io/js/%40fulcrum-governance%2Fsdk.svg)](https://badge.fury.io/js/%40fulcrum-governance%2Fsdk)
[![Node.js 18+](https://img.shields.io/badge/node-18+-green.svg)](https://nodejs.org/)
[![License](https://img.shields.io/badge/License-Proprietary-blue.svg)](https://fulcrum.dev/license)

## Installation

```bash
npm install @fulcrum-governance/sdk
```

## Quick Start

```typescript
import { FulcrumClient } from '@fulcrum-governance/sdk';

// Initialize client
const client = new FulcrumClient({
  host: 'your-fulcrum-server:50051',
  apiKey: 'your-api-key',
  onFailure: 'FAIL_OPEN' // or 'FAIL_CLOSED'
});

// Wrap agent executions in governance envelopes
const envelope = client.envelope({
  workflowId: 'customer-support-bot',
  tenantId: 'your-tenant-id'
});

// Check if action is allowed before executing
const allowed = await envelope.guard('send_email', userMessage);

if (allowed) {
  // Action approved - proceed
  const result = await sendEmail(userMessage);
  envelope.log('email_sent', { recipient: email, status: 'success' });
} else {
  // Action blocked by policy
  envelope.log('action_blocked', { reason: 'policy_violation' });
}
```

## Features

- **Policy Enforcement**: Real-time governance checks before agent actions
- **Cost Tracking**: Monitor and control LLM spending per workflow
- **Audit Trail**: Complete execution history for compliance
- **Fail-Safe Modes**: Configurable FAIL_OPEN or FAIL_CLOSED behavior
- **TypeScript Support**: Full type definitions included

## Configuration

### Client Options

```typescript
import { FulcrumClient, FailureMode } from '@fulcrum-governance/sdk';

const client = new FulcrumClient({
  host: 'localhost:50051',           // Fulcrum server address
  apiKey: 'your-api-key',            // API key for authentication
  tenantId: 'your-tenant-id',        // Default tenant ID
  onFailure: FailureMode.FAIL_OPEN,  // FAIL_OPEN or FAIL_CLOSED
  timeoutMs: 500,                    // Request timeout in milliseconds
  enableTls: true,                   // Enable TLS encryption
  caCertPath: '/path/to/ca.crt',     // Custom CA certificate (optional)
});
```

### Environment Variables

```bash
export FULCRUM_HOST="localhost:50051"
export FULCRUM_API_KEY="your-api-key"
export FULCRUM_TENANT_ID="your-tenant-id"
export FULCRUM_TIMEOUT_MS="500"
```

```typescript
// Client auto-discovers from environment
const client = FulcrumClient.fromEnv();
```

## API Reference

### FulcrumClient

```typescript
interface FulcrumClientOptions {
  host: string;                      // gRPC server address (e.g., 'localhost:50051')
  apiKey?: string;                   // Authentication key
  tenantId?: string;                 // Default tenant ID
  onFailure?: 'FAIL_OPEN' | 'FAIL_CLOSED';  // Behavior on errors
  timeoutMs?: number;                // Request timeout (default: 500ms)
  enableTls?: boolean;               // Enable TLS (default: false for localhost)
  caCertPath?: string;               // Custom CA certificate path
}
```

#### Methods

| Method | Description |
|--------|-------------|
| `envelope(options)` | Create a governance envelope |
| `evaluate(action, inputText, context)` | Evaluate a policy decision |
| `getCost(envelopeId)` | Get cost for an envelope |
| `listPolicies(tenantId)` | List active policies |
| `healthCheck()` | Check server connectivity |

### Envelope

```typescript
interface EnvelopeOptions {
  workflowId: string;                // Identifier for the workflow
  executionId?: string;              // Auto-generated if not provided
  tenantId?: string;                 // Defaults to client tenant
  metadata?: Record<string, string>; // Additional context
}
```

#### Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `guard` | `(actionName: string, inputText: string, metadata?: Record<string, string>) => Promise<boolean>` | Check if action is allowed |
| `log` | `(eventType: string, payload: Record<string, any>) => void` | Log event for audit |
| `checkpoint` | `() => Promise<Checkpoint>` | Create execution checkpoint |
| `getCost` | `() => Promise<CostSnapshot>` | Get current execution cost |
| `complete` | `(result?: any) => Promise<void>` | Mark envelope complete |

## Error Handling

```typescript
import { FulcrumClient } from '@fulcrum-governance/sdk';
import {
  FulcrumError,           // Base error class
  PolicyViolationError,   // Action blocked by policy
  BudgetExceededError,    // Budget limit reached
  ConnectionError,        // Server unreachable
  AuthenticationError,    // Invalid API key
  TimeoutError,           // Request timed out
} from '@fulcrum-governance/sdk/errors';

const client = new FulcrumClient({
  host: 'localhost:50051',
  apiKey: 'your-key'
});

try {
  const envelope = client.envelope({ workflowId: 'my-agent' });
  const allowed = await envelope.guard('send_email', 'Hello');

  if (allowed) {
    await sendEmail('Hello');
  }

  await envelope.complete();
} catch (error) {
  if (error instanceof PolicyViolationError) {
    console.log(`Policy violation: ${error.policyId}`);
    console.log(`Reason: ${error.message}`);
    console.log(`Matched rules: ${error.matchedRules.join(', ')}`);
  } else if (error instanceof BudgetExceededError) {
    console.log(`Budget exceeded: $${error.currentSpend} / $${error.budgetLimit}`);
  } else if (error instanceof ConnectionError) {
    console.log(`Cannot reach Fulcrum server: ${error.message}`);
    // Handle based on failure mode
  } else if (error instanceof TimeoutError) {
    console.log('Request timed out');
  } else {
    throw error;
  }
}
```

## Integration Examples

### Vercel AI SDK

```typescript
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
import { FulcrumClient } from '@fulcrum-governance/sdk';

const fulcrum = FulcrumClient.fromEnv();

export async function POST(req: Request) {
  const { messages } = await req.json();
  const lastMessage = messages[messages.length - 1].content;

  const envelope = fulcrum.envelope({
    workflowId: 'vercel-ai-chat',
    metadata: { source: 'api' }
  });

  // Pre-check message
  if (!await envelope.guard('process_message', lastMessage)) {
    return new Response('Message blocked by policy', { status: 403 });
  }

  const result = await streamText({
    model: openai('gpt-4'),
    messages,
    onFinish: async ({ usage }) => {
      envelope.log('completion', {
        inputTokens: usage.promptTokens,
        outputTokens: usage.completionTokens,
      });
      await envelope.complete();
    }
  });

  return result.toAIStreamResponse();
}
```

### LangChain.js Integration

```typescript
import { ChatOpenAI } from '@langchain/openai';
import { AgentExecutor } from 'langchain/agents';
import { FulcrumClient } from '@fulcrum-governance/sdk';

const fulcrum = FulcrumClient.fromEnv();

async function runGovernedAgent(
  agent: AgentExecutor,
  query: string
): Promise<string> {
  const envelope = fulcrum.envelope({
    workflowId: 'langchain-agent'
  });

  // Check if query is allowed
  if (!await envelope.guard('process_query', query)) {
    throw new Error('Query blocked by policy');
  }

  // Run agent
  const result = await agent.invoke({
    input: query,
    callbacks: [{
      handleToolStart: async (tool, input) => {
        const allowed = await envelope.guard(tool.name, JSON.stringify(input));
        if (!allowed) {
          envelope.log('tool_blocked', { tool: tool.name });
          throw new Error(`Tool ${tool.name} blocked by policy`);
        }
      },
      handleToolEnd: (output) => {
        envelope.log('tool_executed', { output: output.substring(0, 100) });
      }
    }]
  });

  await envelope.complete({ result: result.output });
  return result.output;
}
```

### Express Middleware

```typescript
import express from 'express';
import { FulcrumClient } from '@fulcrum-governance/sdk';

const app = express();
const fulcrum = FulcrumClient.fromEnv();

// Governance middleware
const governanceMiddleware = (workflowId: string) => {
  return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
    const envelope = fulcrum.envelope({
      workflowId,
      metadata: {
        path: req.path,
        method: req.method,
        userId: req.headers['x-user-id'] as string,
      }
    });

    // Attach to request for use in handlers
    (req as any).fulcrumEnvelope = envelope;

    // Check request
    const inputText = JSON.stringify(req.body);
    if (!await envelope.guard('api_request', inputText)) {
      return res.status(403).json({ error: 'Request blocked by policy' });
    }

    // Complete envelope on response finish
    res.on('finish', () => {
      envelope.log('response', { status: res.statusCode });
      envelope.complete();
    });

    next();
  };
};

app.use('/api/agents', governanceMiddleware('agent-api'));
```

## Cost Tracking

```typescript
const envelope = client.envelope({ workflowId: 'my-agent' });

// ... agent execution ...

const cost = await envelope.getCost();
console.log(`Total cost: $${cost.totalUsd.toFixed(4)}`);
console.log(`Input tokens: ${cost.inputTokens}`);
console.log(`Output tokens: ${cost.outputTokens}`);
console.log(`LLM calls: ${cost.llmCalls}`);

// Model breakdown
for (const [model, stats] of Object.entries(cost.modelBreakdown)) {
  console.log(`  ${model}: $${stats.cost.toFixed(4)} (${stats.calls} calls)`);
}
```

## Type Definitions

```typescript
interface PolicyDecision {
  allowed: boolean;
  policyId?: string;
  decision: 'ALLOW' | 'DENY' | 'WARN' | 'REQUIRE_APPROVAL';
  matchedRules: RuleMatch[];
  actions: PolicyAction[];
  message?: string;
}

interface RuleMatch {
  ruleId: string;
  ruleName: string;
  matchedConditions: string[];
}

interface CostSnapshot {
  totalUsd: number;
  inputTokens: number;
  outputTokens: number;
  llmCalls: number;
  toolCalls: number;
  modelBreakdown: Record<string, { calls: number; cost: number }>;
}

interface Checkpoint {
  checkpointId: string;
  version: number;
  stateHash: string;
  createdAt: Date;
}
```

## REST Clients

The SDK includes REST-based clients for managing Fulcrum resources through the Dashboard API. These clients are ideal for administrative tasks, dashboards, and browser environments.

### PolicyClient

Manage governance policies programmatically:

```typescript
import { PolicyClient } from '@fulcrum-governance/sdk';

const policyClient = new PolicyClient({
  baseUrl: 'https://your-fulcrum-dashboard.com',
  apiKey: 'your-api-key',
  timeoutMs: 5000  // optional, default: 5000
});

// List all policies
const policies = await policyClient.list();

// List with filters
const activePolicies = await policyClient.list({
  status: 'active',
  priority: 'high'
});

// Get a specific policy
const policy = await policyClient.get('policy-id');

// Create a new policy
const newPolicy = await policyClient.create({
  name: 'No PII in Responses',
  description: 'Prevents sensitive data exposure',
  rules: [{ type: 'semantic', pattern: 'pii_detection' }],
  priority: 1,
  enabled: true
});

// Update a policy
const updated = await policyClient.update('policy-id', {
  name: 'Updated Policy Name',
  priority: 2
});

// Enable/disable policies
await policyClient.setEnabled('policy-id', false);

// Delete a policy
await policyClient.delete('policy-id');
```

### ApprovalClient

Manage human-in-the-loop approval workflows:

```typescript
import { ApprovalClient } from '@fulcrum-governance/sdk';

const approvalClient = new ApprovalClient({
  baseUrl: 'https://your-fulcrum-dashboard.com',
  apiKey: 'your-api-key'
});

// List all pending approvals
const pending = await approvalClient.listPending();

// List with filters
const approvals = await approvalClient.list({
  status: 'pending',
  workflow_id: 'customer-support-bot'
});

// Get approval details
const approval = await approvalClient.get('approval-id');

// Approve a request
await approvalClient.approve('approval-id', 'Looks safe to proceed');

// Deny a request
await approvalClient.deny('approval-id', 'Contains sensitive information');

// Generic decision method
await approvalClient.decide('approval-id', {
  decision: 'approved',  // or 'denied'
  comment: 'Reviewed and approved'
});
```

### BudgetClient

Manage AI spending budgets and limits:

```typescript
import { BudgetClient } from '@fulcrum-governance/sdk';

const budgetClient = new BudgetClient({
  baseUrl: 'https://your-fulcrum-dashboard.com',
  apiKey: 'your-api-key'
});

// List all budgets with summary
const { budgets, summary } = await budgetClient.list();
console.log(`Total budgets: ${summary.total}`);
console.log(`Active: ${summary.active}, Exceeded: ${summary.exceeded}`);

// Filter by scope or status
const tenantBudgets = await budgetClient.listBudgets({ scope: 'TENANT' });
const exceededBudgets = await budgetClient.getExceeded();
const warningBudgets = await budgetClient.getWarnings();

// Get a specific budget
const budget = await budgetClient.get('budget-id');

// Create a new budget
const newBudget = await budgetClient.create({
  name: 'Marketing Team Monthly',
  scope: 'TENANT',           // GLOBAL, TENANT, WORKFLOW, MODEL
  scope_id: 'tenant-123',
  limit_amount: 1000,        // in dollars
  period: 'MONTHLY',         // DAILY, WEEKLY, MONTHLY, QUARTERLY
  action: 'SOFT_LIMIT',      // WARN, SOFT_LIMIT, HARD_LIMIT
  alert_thresholds: [50, 75, 90]
});

// Update budget
await budgetClient.update('budget-id', {
  limit_amount: 1500,
  alert_thresholds: [60, 80, 95]
});

// Helper methods
const percentage = budgetClient.calculatePercentage(budget);
const isNearLimit = budgetClient.isAtThreshold(budget, 80);

// Delete a budget
await budgetClient.delete('budget-id');
```

### MetricsClient

Access platform metrics and audit logs:

```typescript
import { MetricsClient } from '@fulcrum-governance/sdk';

const metricsClient = new MetricsClient({
  baseUrl: 'https://your-fulcrum-dashboard.com',
  apiKey: 'your-api-key'  // optional for public metrics
});

// Public metrics (no auth required)
const metrics = await metricsClient.getPublicMetrics();
console.log(`Policies evaluated (24h): ${metrics.policiesEvaluated24h}`);
console.log(`Avg latency: ${metrics.avgLatencyMs}ms`);
console.log(`Blocked requests: ${metrics.blockedRequests24h}`);

// Cognitive layer metrics
const cognitive = await metricsClient.getCognitiveMetrics();
console.log(`Semantic Judge violations: ${cognitive.semanticJudgeViolations}`);
console.log(`Oracle savings: $${cognitive.oracleSavings}`);

// Audit logs (auth required)
const { logs, pagination, actors } = await metricsClient.getAuditLogs({
  resource_type: 'Policy',
  start_date: '2026-01-01',
  end_date: '2026-01-31',
  page: 1,
  page_size: 50
});

// Convenience methods for audit logs
const policyLogs = await metricsClient.getLogsByResourceType('Policy');
const userLogs = await metricsClient.getLogsByUser('user-id');
const recentLogs = await metricsClient.getLogsByDateRange(
  new Date('2026-01-01'),
  new Date('2026-01-31')
);
const searchResults = await metricsClient.searchAuditLogs('budget exceeded');
```

### REST Client Types

```typescript
// Policy types
interface Policy {
  id: string;
  org_id: string;
  name: string;
  description: string;
  rules: PolicyRule[];
  priority: number;
  enabled: boolean;
  status: 'active' | 'inactive' | 'draft';
  created_at: string;
  updated_at: string;
}

// Approval types
interface Approval {
  id: string;
  envelope_id: string;
  workflow_id: string;
  action_name: string;
  input_text: string;
  status: 'pending' | 'approved' | 'denied' | 'expired';
  requested_at: string;
  decided_at?: string;
  decided_by?: string;
  comment?: string;
}

// Budget types
type BudgetScope = 'GLOBAL' | 'TENANT' | 'WORKFLOW' | 'MODEL';
type BudgetPeriod = 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'QUARTERLY';
type BudgetAction = 'WARN' | 'SOFT_LIMIT' | 'HARD_LIMIT';
type BudgetStatus = 'active' | 'warning' | 'exceeded' | 'disabled';

interface Budget {
  id: string;
  name: string;
  scope: BudgetScope;
  scope_id: string | null;
  limit_amount: number;
  current_spend: number;
  period: BudgetPeriod;
  action: BudgetAction;
  status: BudgetStatus;
  percentage: number;
  alert_thresholds: number[];
}

// Metrics types
interface PublicMetrics {
  lastUpdated: string;
  policiesEvaluated24h: number;
  avgLatencyMs: number;
  budgetAlerts24h: number;
  activeTenants: number;
  blockedRequests24h: number;
  cognitiveLayer: CognitiveLayerMetrics;
}

interface CognitiveLayerMetrics {
  semanticJudgeRequests: number;
  semanticJudgeViolations: number;
  oraclePredictions: number;
  oracleSavings: number;
  immunePoliciesGenerated: number;
}

type ResourceType = 'User' | 'Policy' | 'Budget' | 'APIKey' | 'Workflow' | 'Envelope' | 'Approval';

interface AuditLogEntry {
  id: string;
  timestamp: string;
  actor_id: string;
  actor_email: string;
  action: string;
  resource_type: ResourceType;
  resource_id?: string;
  resource_name?: string;
  status: 'success' | 'failure';
  changes?: Record<string, { old: unknown; new: unknown }>;
}
```

### Error Handling for REST Clients

Each REST client has its own error class:

```typescript
import {
  PolicyClient,
  PolicyClientError,
  ApprovalClient,
  ApprovalClientError,
  BudgetClient,
  BudgetClientError,
  MetricsClient,
  MetricsClientError
} from '@fulcrum-governance/sdk';

try {
  const policy = await policyClient.get('invalid-id');
} catch (error) {
  if (error instanceof PolicyClientError) {
    console.log(`Error: ${error.message}`);
    console.log(`Status: ${error.statusCode}`);  // e.g., 404, 401, 500
  }
}
```

## Browser Support

For browser environments, use the REST clients which work with the standard `fetch` API:

```typescript
import { PolicyClient, BudgetClient, MetricsClient } from '@fulcrum-governance/sdk';

// REST clients work in browsers
const policyClient = new PolicyClient({
  baseUrl: 'https://your-fulcrum-dashboard.com',
  apiKey: 'your-api-key'
});

// For real-time governance (gRPC), use the REST envelope wrapper
// (Coming soon)
```

## Documentation

Full documentation: [https://docs.fulcrum.dev](https://docs.fulcrum.dev)

## Support

- Email: support@fulcrum.dev
- Documentation: https://docs.fulcrum.dev
- Issues: Contact your account representative