@yobekasbah/sdk 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,180 @@
1
+ # @kasbah/sdk
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@kasbah/sdk.svg?color=cc3300)](https://www.npmjs.com/package/@kasbah/sdk)
4
+ [![KasbahOS Governed](https://api.bekasbah.com/v1/badge/global.svg)](https://bekasbah.com)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Full%20Types-blue.svg)](https://bekasbah.com)
7
+
8
+ Official Node.js SDK for [KasbahOS](https://bekasbah.com) — govern any AI agent in 5 lines. Cryptographic receipts, 37 detection systems, drop-in proxy for OpenAI and Anthropic.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @kasbah/sdk
14
+ ```
15
+
16
+ ## 5-line quick start
17
+
18
+ ```js
19
+ const Kasbah = require('@kasbah/sdk');
20
+
21
+ const k = new Kasbah({ apiKey: process.env.KASBAH_API_KEY });
22
+
23
+ const result = await k.govern({ prompt: userInput, agent: 'my-agent' });
24
+ if (result.verdict === 'DENY') throw new Error('Blocked: ' + result.threats.join(', '));
25
+
26
+ console.log(`Safe — proof: ${result.proof}`);
27
+ ```
28
+
29
+ ## Drop-in OpenAI proxy
30
+
31
+ ```js
32
+ const Kasbah = require('@kasbah/sdk');
33
+ const OpenAI = require('openai');
34
+
35
+ const kasbah = new Kasbah({ apiKey: process.env.KASBAH_API_KEY });
36
+ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
37
+
38
+ // Create a governed agent session
39
+ const session = await kasbah.createAgent({
40
+ agentId: 'research-bot',
41
+ passportId: process.env.KASBAH_PASSPORT_ID,
42
+ goal: 'Summarize recent papers on LLM safety',
43
+ manifest: { allowedTools: ['search', 'read_url'], maxTokens: 50000 },
44
+ });
45
+
46
+ // Wrap OpenAI — every call is auto-governed
47
+ const governed = kasbah.wrapOpenAI(openai, session.sessionId);
48
+
49
+ // This call transparently goes through KasbahOS governance
50
+ const completion = await governed.chat.completions.create({
51
+ model: 'gpt-4o',
52
+ messages: [{ role: 'user', content: 'Summarize this paper...' }],
53
+ });
54
+ ```
55
+
56
+ ## Drop-in Anthropic proxy
57
+
58
+ ```js
59
+ const Kasbah = require('@kasbah/sdk');
60
+ const Anthropic = require('@anthropic-ai/sdk');
61
+
62
+ const kasbah = new Kasbah({ apiKey: process.env.KASBAH_API_KEY });
63
+ const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
64
+
65
+ const session = await kasbah.createAgent({
66
+ agentId: 'claude-agent',
67
+ passportId: process.env.KASBAH_PASSPORT_ID,
68
+ goal: 'Answer customer questions safely',
69
+ });
70
+
71
+ const governed = kasbah.wrapAnthropic(anthropic, session.sessionId);
72
+ const message = await governed.messages.create({ model: 'claude-opus-4-5', ... });
73
+ ```
74
+
75
+ ## Per-agent passports
76
+
77
+ ```js
78
+ // Issue a passport for an agent — limits what it can do
79
+ const passport = await k.passport.issue({
80
+ agentId: 'data-pipeline',
81
+ capabilities: ['read_database', 'write_report'],
82
+ trustLevel: 'medium',
83
+ spendPolicy: { maxTokensPerDay: 100000, hardBlockOnExceed: true },
84
+ });
85
+
86
+ // Every govern() call tracks passport trust score
87
+ const result = await k.govern({
88
+ prompt: userInput,
89
+ passportId: passport.passportId,
90
+ });
91
+ ```
92
+
93
+ ## Scan for secrets and threats
94
+
95
+ ```js
96
+ const scan = await k.scan(codeSnippet);
97
+ if (!scan.safe) {
98
+ console.log('Threats:', scan.threats);
99
+ // e.g. ['AWS Access Key', 'Hardcoded Password']
100
+ }
101
+ ```
102
+
103
+ ## Verify a governance proof (auditors)
104
+
105
+ ```js
106
+ // Zero-trust: verify any governance decision mathematically, no KasbahOS trust needed
107
+ const verified = await fetch('https://api.bekasbah.com/v1/zk/verify', {
108
+ method: 'POST',
109
+ body: JSON.stringify({ proof: result.proof, publicInput: { verdict: 'ALLOW' } }),
110
+ });
111
+ // { valid: true, rulesVerified: ['no_injection', 'no_pii', 'no_secrets'] }
112
+ ```
113
+
114
+ ## All methods
115
+
116
+ | Method | Description |
117
+ |--------|-------------|
118
+ | `govern(opts)` | Govern a prompt/response through all 37 systems |
119
+ | `scan(text)` | Lightweight threat scan |
120
+ | `explain(prompt)` | Explain why a prompt would be blocked |
121
+ | `bells(text)` | Bell's Inequality AI detection (CHSH S-value) |
122
+ | `maqasid(text)` | 5-pillar ethics scoring |
123
+ | `rtp(text)` | RTP governance pipeline |
124
+ | `passport.issue(opts)` | Create agent passport |
125
+ | `passport.revoke(id)` | Revoke a passport |
126
+ | `delegation.issue(opts)` | Issue delegation token (agent A acts as B) |
127
+ | `honeytoken.deploy(service)` | Plant a canary credential |
128
+ | `honeytoken.check(text)` | Check text for leaked canaries |
129
+ | `createAgent(opts)` | Create governed agent session |
130
+ | `governTool(sessionId, tool, args)` | Govern a tool call before executing |
131
+ | `scanToolResult(sessionId, tool, output)` | Scan tool output for injections |
132
+ | `wrapOpenAI(client, sessionId)` | Auto-govern all OpenAI calls |
133
+ | `wrapAnthropic(client, sessionId)` | Auto-govern all Anthropic calls |
134
+ | `proxyOpenAI(body, key)` | Proxy an OpenAI completion |
135
+ | `proxyAnthropic(body, key)` | Proxy an Anthropic message |
136
+ | `getUsage(passportId)` | Token/cost usage for a passport |
137
+ | `setBudget(passportId, policy)` | Set hard token/cost limits |
138
+ | `health()` | API health check |
139
+ | `stats()` | Governance statistics |
140
+ | `auditChain()` | Tamper-evident audit ledger |
141
+
142
+ ## TypeScript
143
+
144
+ Full TypeScript types are included:
145
+
146
+ ```typescript
147
+ import Kasbah, { GovernResult, Verdict, Passport, AgentSession } from '@kasbah/sdk';
148
+
149
+ const k = new Kasbah({ apiKey: process.env.KASBAH_API_KEY! });
150
+
151
+ const result: GovernResult = await k.govern({ prompt: 'Hello world' });
152
+ const verdict: Verdict = result.verdict; // 'ALLOW' | 'WARN' | 'DENY'
153
+ ```
154
+
155
+ ## Configuration
156
+
157
+ ```js
158
+ const k = new Kasbah({
159
+ apiKey: process.env.KASBAH_API_KEY, // your API key
160
+ baseUrl: 'http://your-server:8788', // self-hosted instance
161
+ timeout: 10000, // ms (default: 10000)
162
+ autoRetry: true, // retry on 5xx (default: true)
163
+ passportId: 'pp_default_agent', // default passport for all govern() calls
164
+ });
165
+ ```
166
+
167
+ ## Self-hosted
168
+
169
+ ```bash
170
+ docker run -p 8788:8788 kasbahguard/kasbah-os:latest
171
+ ```
172
+
173
+ Then:
174
+ ```js
175
+ const k = new Kasbah({ baseUrl: 'http://localhost:8788' });
176
+ ```
177
+
178
+ ---
179
+
180
+ [bekasbah.com](https://bekasbah.com)  |  [GitHub](https://github.com/kasbah-guard)  |  [Docs](https://bekasbah.com/public/glassbox.html)
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@yobekasbah/sdk",
3
+ "version": "6.0.0",
4
+ "description": "KasbahOS — govern any AI agent in one line. Cryptographic receipts, multi-layer threat detection, drop-in middleware for OpenAI, Anthropic, LangChain.",
5
+ "main": "src/index.js",
6
+ "types": "src/index.d.ts",
7
+ "files": [
8
+ "src/index.js",
9
+ "src/index.d.ts",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "test": "node src/test.js"
14
+ },
15
+ "keywords": [
16
+ "ai", "security", "governance", "llm", "openai", "anthropic",
17
+ "langchain", "prompt-injection", "kasbah", "kasbah-os", "receipt",
18
+ "audit", "compliance", "hipaa", "soc2", "middleware"
19
+ ],
20
+ "author": "Kasbah Guard <hello@bekasbah.com>",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/kasbah-guard/kasbah"
25
+ },
26
+ "homepage": "https://bekasbah.com",
27
+ "bugs": { "url": "https://github.com/kasbah-guard/kasbah/issues" },
28
+ "engines": { "node": ">=18.0.0" }
29
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,147 @@
1
+ /**
2
+ * KasbahOS SDK — TypeScript definitions
3
+ * @version 6.0.0
4
+ */
5
+
6
+ export interface GovernOptions {
7
+ agent?: string;
8
+ passportId?: string;
9
+ context?: Record<string, unknown>;
10
+ }
11
+
12
+ export interface GovernResult {
13
+ verdict: 'ALLOW' | 'WARN' | 'DENY';
14
+ score: number;
15
+ threats: string[];
16
+ receipt: string;
17
+ receiptPayload?: string;
18
+ ticket?: { id: string; expiresAt: number; ttlMs: number };
19
+ latency_ms: number;
20
+ timestamp: string;
21
+ requestId: string;
22
+ passport?: Record<string, unknown>;
23
+ pii?: { detected: boolean; count: number; riskScore: number };
24
+ steg?: { detected: boolean; method: string; confidence: number };
25
+ sentinel?: { score: number; threats: string[]; deontic?: string };
26
+ secrets?: { found: boolean; count: number; types: string[] };
27
+ intent?: { intent: string; confidence: number; riskLevel: string };
28
+ manipulation?: { patterns: number; risk: string };
29
+ bells?: { sValue: number; isAI: boolean };
30
+ maqasid?: { compliance: number; concerns: string[] };
31
+ rtp?: { intent: string; modulatorScore: number; obfuscationScore: number };
32
+ }
33
+
34
+ export interface ScanResult {
35
+ verdict: 'ALLOW' | 'WARN' | 'DENY';
36
+ threats: string[];
37
+ risk_score: number;
38
+ safe: boolean;
39
+ latency_ms: number;
40
+ timestamp: string;
41
+ }
42
+
43
+ export interface HealthResult {
44
+ status: string;
45
+ version: string;
46
+ engine: string;
47
+ uptime_s: string;
48
+ persistence: 'redis' | 'memory';
49
+ systems: { active: number; total: number; wasm: boolean };
50
+ timestamp: string;
51
+ }
52
+
53
+ export interface ReceiptVerification {
54
+ valid: boolean;
55
+ verdict?: string;
56
+ requestId?: string;
57
+ timestamp?: number;
58
+ error?: string;
59
+ }
60
+
61
+ export interface PassportResult {
62
+ passportId: string;
63
+ agentId: string;
64
+ publicKey: string;
65
+ privateKey: string;
66
+ issuedAt: string;
67
+ warning: string;
68
+ }
69
+
70
+ export interface StreamHandle {
71
+ close(): void;
72
+ on(event: 'error', handler: (err: Error) => void): StreamHandle;
73
+ on(event: 'open', handler: () => void): StreamHandle;
74
+ }
75
+
76
+ export interface ProxyResult {
77
+ id: string;
78
+ object: string;
79
+ choices: unknown[];
80
+ usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };
81
+ _kasbahReceipt?: string;
82
+ _kasbahVerdict?: string;
83
+ }
84
+
85
+ export interface UsageResult {
86
+ passportId: string;
87
+ spendLedger: { tokens1m: number; tokens24h: number; costCents24h: number };
88
+ watcherState: { band: string; brittleness: number; tokensPerHour: number; costPerHour: number };
89
+ timestamp: string;
90
+ }
91
+
92
+ export interface BudgetPolicy {
93
+ maxTokensPerMin?: number;
94
+ maxTokensPerDay?: number;
95
+ maxCostCentsPerDay?: number;
96
+ }
97
+
98
+ export declare class KasbahError extends Error {
99
+ statusCode?: number;
100
+ verdict?: string;
101
+ }
102
+
103
+ export declare class Kasbah {
104
+ constructor(options: { apiKey: string; baseUrl?: string; timeout?: number });
105
+
106
+ /** Govern any prompt — returns verdict, receipt, threats */
107
+ govern(prompt: string | { prompt: string; [key: string]: unknown }, options?: GovernOptions): Promise<GovernResult>;
108
+
109
+ /** Lightweight text scan without full policy gate */
110
+ scan(text: string): Promise<ScanResult>;
111
+
112
+ /** Check API health */
113
+ health(): Promise<HealthResult>;
114
+
115
+ /** Verify a governance receipt offline — no API call needed */
116
+ verifyReceipt(receipt: string, payload?: string): ReceiptVerification;
117
+
118
+ /** Issue a Governance Passport for an agent */
119
+ issuePassport(agentId: string, capabilities?: string[]): Promise<PassportResult>;
120
+
121
+ /** Stream real-time governance events via SSE */
122
+ stream(onEvent: (event: GovernResult) => void): StreamHandle;
123
+
124
+ /** Proxy an OpenAI chat completion through Kasbah governance */
125
+ proxyOpenAI(body: Record<string, unknown>, upstreamKey: string, options?: GovernOptions): Promise<ProxyResult>;
126
+
127
+ /** Proxy an Anthropic messages call through Kasbah governance */
128
+ proxyAnthropic(body: Record<string, unknown>, upstreamKey: string, options?: GovernOptions): Promise<ProxyResult>;
129
+
130
+ /** Get token/cost usage for a passport */
131
+ getUsage(passportId: string): Promise<UsageResult>;
132
+
133
+ /** Set token/cost budget policy for a passport */
134
+ setBudget(passportId: string, policy: BudgetPolicy): Promise<{ ok: boolean; passportId: string; policy: BudgetPolicy }>;
135
+
136
+ /** Get current budget policy for a passport */
137
+ getBudget(passportId: string): Promise<{ passportId: string; policy: BudgetPolicy; usage: UsageResult }>;
138
+
139
+ readonly passport: {
140
+ issue(options: { agentId?: string; capabilities?: string[] }): Promise<PassportResult>;
141
+ get(passportId: string): Promise<Record<string, unknown>>;
142
+ revoke(passportId: string): Promise<{ ok: boolean }>;
143
+ list(): Promise<{ passports: PassportResult[]; total: number }>;
144
+ };
145
+ }
146
+
147
+ export default Kasbah;
package/src/index.js ADDED
@@ -0,0 +1,701 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Kasbah Guard SDK — Official Node.js Client
5
+ *
6
+ * Govern AI agents from any Node.js app. Wraps the Kasbah API
7
+ * with automatic passport management, retry logic, and streaming.
8
+ *
9
+ * Usage:
10
+ * const Kasbah = require('@yobekasbah/sdk');
11
+ * const k = new Kasbah({ apiKey: 'kg_...', baseUrl: 'https://api.bekasbah.com' });
12
+ *
13
+ * // Govern a prompt
14
+ * const result = await k.govern({ prompt: 'User message here' });
15
+ * if (result.verdict === 'DENY') throw new Error('Blocked: ' + result.threats.join(', '));
16
+ *
17
+ * // Issue a passport for an agent
18
+ * const passport = await k.passport.issue({ agentId: 'my-agent', capabilities: ['search'] });
19
+ *
20
+ * // Check system health
21
+ * const health = await k.health();
22
+ */
23
+
24
+ const http = require('http');
25
+ const https = require('https');
26
+ const url = require('url');
27
+
28
+ const SDK_VERSION = '6.0.0';
29
+
30
+ class KasbahError extends Error {
31
+ constructor(message, status, body) {
32
+ super(message);
33
+ this.name = 'KasbahError';
34
+ this.status = status;
35
+ this.body = body;
36
+ }
37
+ }
38
+
39
+ class Kasbah {
40
+ /**
41
+ * @param {object} opts
42
+ * @param {string} opts.apiKey — API key (default: 'kg_desktop_builtin')
43
+ * @param {string} opts.baseUrl — API base URL (default: 'https://api.bekasbah.com')
44
+ * @param {number} opts.timeout — Request timeout ms (default: 10000)
45
+ * @param {boolean} opts.autoRetry — Retry on 5xx with backoff (default: true)
46
+ */
47
+ constructor(opts = {}) {
48
+ this.apiKey = opts.apiKey || 'kg_desktop_builtin';
49
+ this.baseUrl = (opts.baseUrl || 'https://api.bekasbah.com').replace(/\/$/, '');
50
+ this.timeout = opts.timeout || 10_000;
51
+ this.autoRetry = opts.autoRetry !== false;
52
+ this._passportId = opts.passportId || null;
53
+
54
+ // Sub-clients
55
+ this.passport = new PassportClient(this);
56
+ this.delegation = new DelegationClient(this);
57
+ this.honeytoken = new HoneytokenClient(this);
58
+ this.spend = new SpendClient(this);
59
+ }
60
+
61
+ // ── Core govern ─────────────────────────────────────────────────────────
62
+
63
+ /**
64
+ * Govern a prompt/response through all 17 frontier systems.
65
+ * @param {object} body — { prompt?, response?, passportId?, delegationTokenId?, agent? }
66
+ * @returns {Promise<GovernResult>}
67
+ */
68
+ async govern(body = {}) {
69
+ if (this._passportId && !body.passportId) body.passportId = this._passportId;
70
+ return this._post('/v1/govern', body);
71
+ }
72
+
73
+ /**
74
+ * Scan text for threats (lightweight — no passport/delegation processing).
75
+ * @param {string} text
76
+ * @returns {Promise<ScanResult>}
77
+ */
78
+ async scan(text) {
79
+ const raw = await this._post('/v1/scan', { text });
80
+ // /v1/scan returns {threats, risk, risk_score, safe, latency_ms} — normalize
81
+ // to {decision, verdict, blocked, risk, threats, ...raw} so callers can rely on it.
82
+ const threats = raw.threats || raw.violations || [];
83
+ const risk = raw.risk_score ?? raw.riskScore ?? raw.risk ?? 0;
84
+ const safe = raw.safe !== false;
85
+ const verdict = raw.verdict || raw.decision || (safe ? 'ALLOW' : (risk < 0.7 ? 'WARN' : 'DENY'));
86
+ return Object.assign({}, raw, {
87
+ verdict,
88
+ decision: verdict,
89
+ blocked: verdict === 'DENY',
90
+ risk,
91
+ threats
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Explain why a prompt would be blocked/warned.
97
+ * @param {string} prompt
98
+ * @returns {Promise<ExplainResult>}
99
+ */
100
+ async explain(prompt) {
101
+ return this._post('/v1/explain', { prompt });
102
+ }
103
+
104
+ /**
105
+ * Evaluate an action against compliance + biometric-surveillance rule packs
106
+ * BEFORE it runs. Packs default to HIPAA, GDPR, SOC2 and BIOMETRIC_GUARD —
107
+ * the latter blocks facial-micro-expression / silent-speech / subvocal / BCI /
108
+ * QAI intent-surveillance vectors.
109
+ * @param {object} opts - { verb, target?, content?, packs? }
110
+ * @returns {Promise<{decision, reason, violations}>}
111
+ */
112
+ async checkCompliance({ verb, target = '', content = '', packs = 'HIPAA,GDPR,SOC2,BIOMETRIC_GUARD' } = {}) {
113
+ if (!verb) throw new KasbahError('checkCompliance requires a verb');
114
+ return this._post('/v1/algorithms/policy-engine/run', { verb, target, content, packs });
115
+ }
116
+
117
+ /**
118
+ * Defensive check: is this action a silent-speech / biometric surveillance
119
+ * attempt? Returns DENY (with cited BIOMETRIC_GUARD rule) if so. Kasbah never
120
+ * captures or analyzes facial/biometric data — it blocks those attempts.
121
+ * @param {object} opts - { verb?, target?, content? }
122
+ */
123
+ async guardBiometric({ verb = 'CAPTURE_VIDEO', target = 'facial_expression', content = '' } = {}) {
124
+ return this._post('/v1/algorithms/policy-engine/run', { verb, target, content, packs: 'BIOMETRIC_GUARD' });
125
+ }
126
+
127
+ // ── Governance Proxy (wrap an LLM turn) ─────────────────────────────────────
128
+
129
+ /**
130
+ * Govern a full LLM turn: pass message history + proposed tool calls, get a
131
+ * bounded advisory verdict (CLEAR / WARN / REQUIRE_APPROVAL) plus authoritative
132
+ * DENY for forbidden verbs / non-whitelisted domains. Includes multi-step
133
+ * attack-trajectory detection and a forward-secure audit receipt.
134
+ */
135
+ async governTurn({ messages = [], tools = [], clearance = 2 } = {}) {
136
+ return this._post('/v1/proxy/turn', { messages, tools, clearance });
137
+ }
138
+
139
+ /** List actions queued for human approval (REQUIRE_APPROVAL). */
140
+ async pendingApprovals() { return this._request('GET', '/v1/proxy/pending'); }
141
+
142
+ /** Approve a queued action (requires OPERATOR clearance ≥ 3). */
143
+ async approveAction(actionId, clearance = 3, approver = 'sdk') {
144
+ return this._post(`/v1/proxy/approve/${encodeURIComponent(actionId)}`, { clearance, approver });
145
+ }
146
+
147
+ /** Run a single advisory analyzer directly (detectgpt, intent, conformal, …). */
148
+ async advisory(module, payload = {}) {
149
+ return this._post(`/v1/advisory/${module}`, payload);
150
+ }
151
+
152
+ /** Access the kasbah-os Python engine (defensive live; offensive introspect-only). */
153
+ async kasbahOS(action, params = {}) {
154
+ if (action === 'govern') return this._post('/v1/kasbah-os/governance/turn', params);
155
+ const path = action === 'audit-verify' ? 'audit/verify' : action === 'offensive-info' ? 'offensive/info' : 'health';
156
+ return this._request('GET', `/v1/kasbah-os/${path}`);
157
+ }
158
+
159
+ // ── New v4.0 endpoints ──────────────────────────────────────────────────
160
+
161
+ /**
162
+ * Run Bell's Inequality AI text detection (CHSH S-value).
163
+ * S > 2.0 = AI-generated text with non-local semantic correlations.
164
+ */
165
+ async bells(text) {
166
+ return this._post('/v1/bells', { text });
167
+ }
168
+
169
+ /**
170
+ * Run Maqasid Ethics Framework (5-pillar Islamic ethics scoring).
171
+ */
172
+ async maqasid(text) {
173
+ return this._post('/v1/maqasid', { text });
174
+ }
175
+
176
+ /**
177
+ * Run RTP pipeline (f0–f5 governance stages, no side-effects).
178
+ */
179
+ async rtp(text, passportId = null) {
180
+ return this._post('/v1/rtp', { text, passportId });
181
+ }
182
+
183
+ /**
184
+ * Run Witt-Crystalline Cohomology Analysis.
185
+ * Novel mathematical framework: de Rham + crystalline + Witt vectors.
186
+ * Computes [ω] ∈ H^k → W(ω) = η → lim σ_n (perfect governance state).
187
+ */
188
+ async witt(data) {
189
+ return this._post('/v1/witt/analyze', { data });
190
+ }
191
+
192
+ /**
193
+ * Run Nexus unified engine (RTP + Kernel + Bell's + Detector in one call).
194
+ */
195
+ async nexus(text) {
196
+ return this._post('/v1/nexus', { text });
197
+ }
198
+
199
+ /**
200
+ * Verify and consume an execution ticket.
201
+ */
202
+ async verifyTicket(ticketId, hmac) {
203
+ return this._post('/v1/ticket/verify', { ticketId, hmac });
204
+ }
205
+
206
+ // ── System ──────────────────────────────────────────────────────────────
207
+
208
+ async health() { return this._get('/v1/health'); }
209
+ async stats() { return this._get('/v1/stats'); }
210
+ async audit(n=50) { return this._get(`/v1/audit?limit=${n}`); }
211
+ async integrity() { return this._get('/v1/integrity'); }
212
+ async forecast() { return this._get('/v1/forecast'); }
213
+ async swarm() { return this._get('/v1/swarm/status'); }
214
+ async auditChain() { return this._get('/v1/audit/chain'); }
215
+ async policy() { return this._get('/v1/policy/active'); }
216
+
217
+ async setPolicy(policy) { return this._request('PUT', '/v1/policy/active', policy); }
218
+
219
+ // ── Products (all 16 engines) ─────────────────────────────────────────────
220
+
221
+ async productsStatus() { return this._get('/v1/products/status'); }
222
+ async productScan(product, t) { return this._post(`/v1/products/${product}`, { text: t }); }
223
+
224
+ // ── Trinity ───────────────────────────────────────────────────────────────
225
+
226
+ async forgeKSI(text) { return this._post('/v1/forge/ksi', { text }); }
227
+ async forgeConfig() { return this._get('/v1/forge/config'); }
228
+ async nexusCommand(cmd) { return this._post('/v1/nexus/command', { command: cmd }); }
229
+ async nexusStatus() { return this._get('/v1/nexus/status'); }
230
+ async cortexExec(cmd) { return this._post('/v1/cortex/exec', { command: cmd }); }
231
+
232
+ // ── Crypto ────────────────────────────────────────────────────────────────
233
+
234
+ async shamirSplit(s, n, k) { return this._post('/v1/crypto/shamir/split', { secret: s, n, k }); }
235
+ async shamirCombine(shares) { return this._post('/v1/crypto/shamir/combine', { shares }); }
236
+ async mmrAppend(data) { return this._post('/v1/crypto/mmr/append', { data }); }
237
+ async vdfEval(input, it) { return this._post('/v1/crypto/vdf/eval', { input, iterations: it }); }
238
+
239
+ // ── Silent speech + Zero-trust audit ──────────────────────────────────────
240
+
241
+ async silentSpeech(opts) { return this._post('/v1/silent-speech', opts); }
242
+ async auditReceipt(opts) { return this._post('/v1/audit/receipt', opts); }
243
+
244
+ // ── Receipts (v3) ─────────────────────────────────────────────────────────
245
+
246
+ async signReceipt(opts) { return this._post('/v1/sign', opts); }
247
+ async signReceiptV3(opts) { return this._post('/v1/sign?v=3', opts); }
248
+ async verifyReceipt(opts) { return this._post('/v1/receipt/verify', opts); }
249
+ async verifyReceiptBatch(opts) { return this._post('/v1/receipt/verify-batch', opts); }
250
+
251
+ // ── KasbahOS Python core ──────────────────────────────────────────────────
252
+
253
+ async kasbahOSIngest(opts) { return this._post('/v1/kasbah-os/ingest', opts); }
254
+ async kasbahOSHealth() { return this._get('/v1/kasbah-os/health'); }
255
+ async kasbahOSRetrieve(id) { return this._post('/v1/kasbah-os/retrieve', { receipt_id: id }); }
256
+
257
+ // ── v4.0 Mythos-Class Engines ────────────────────────────────────────────
258
+
259
+ // Crypto
260
+ async kasbahOSKeygen() { return this._post('/v1/kasbah-os/crypto/keygen'); }
261
+ async kasbahOSSign(opts) { return this._post('/v1/kasbah-os/crypto/sign', opts); }
262
+ async kasbahOSVerify(opts) { return this._post('/v1/kasbah-os/crypto/verify', opts); }
263
+ async kasbahOSPubkey(seedHex) { return this._post('/v1/kasbah-os/crypto/pubkey', { seed_hex: seedHex }); }
264
+
265
+ // Audit / Zero-Trust
266
+ async kasbahOSAuditEvent(opts) { return this._post('/v1/kasbah-os/audit/event', opts); }
267
+ async kasbahOSAuditReport() { return this._get('/v1/kasbah-os/audit/report'); }
268
+ async kasbahOSAuditChain() { return this._get('/v1/kasbah-os/audit/chain'); }
269
+ async kasbahOSAuditChainImport(chain) { return this._post('/v1/kasbah-os/audit/chain/import', { chain }); }
270
+ async kasbahOSAuditTrust(engine) { return this._post('/v1/kasbah-os/audit/trust', { engine: engine || 'bridge' }); }
271
+
272
+ // Merkle
273
+ async kasbahOSMerkleBuild(entries) { return this._post('/v1/kasbah-os/merkle/build', { entries }); }
274
+ async kasbahOSMerkleVerify(opts) { return this._post('/v1/kasbah-os/merkle/verify', opts); }
275
+
276
+ // Binary Analysis
277
+ async kasbahOSBinaryAnalyze(hex, sampleId) {
278
+ return this._post('/v1/kasbah-os/binary/analyze', { binary_hex: hex, sample_id: sampleId || 'sdk' });
279
+ }
280
+
281
+ // Pipeline / Orchestration
282
+ async kasbahOSPipelineRun(hex, targetInfo) {
283
+ return this._post('/v1/kasbah-os/pipeline/run', { binary_hex: hex, target_info: targetInfo || {} });
284
+ }
285
+
286
+ // System
287
+ async kasbahOSModules() { return this._get('/v1/kasbah-os/modules'); }
288
+ async kasbahOSPing() { return this._get('/v1/kasbah-os/ping'); }
289
+
290
+ // ── Governance Proxy ─────────────────────────────────────────────────────
291
+
292
+ async kasbahOSGovernanceProcess(messages, tools, clearance) {
293
+ return this._post('/v1/kasbah-os/governance/process', {
294
+ messages: messages || [], tools: tools || [], clearance: clearance ?? 2
295
+ });
296
+ }
297
+ async kasbahOSGovernanceApprove(actionId) {
298
+ return this._post('/v1/kasbah-os/governance/approve/' + actionId);
299
+ }
300
+ async kasbahOSGovernanceHealth() { return this._get('/v1/kasbah-os/governance/health'); }
301
+
302
+ // ── Unified pipeline ──────────────────────────────────────────────────────
303
+
304
+ async pipelineUnified(text) { return this._post('/v1/pipeline/unified', { text }); }
305
+
306
+ // ── Keys ──────────────────────────────────────────────────────────────────
307
+
308
+ async keys() { return this._get('/v1/keys'); }
309
+ async wellKnownKeys() { return this._get('/.well-known/kasbah-keys.json'); }
310
+ async models() { return this._get('/v1/models'); }
311
+
312
+ // ── Multi-MCP Governance ──────────────────────────────────────────────────
313
+
314
+ async mcpServers() { return this._get('/v1/mcp/servers'); }
315
+ async mcpCreateTeam(name, admin) { return this._post('/v1/mcp/teams', { name, adminPassportId: admin }); }
316
+ async mcpAddMember(teamId, pid) { return this._post(`/v1/mcp/teams/${teamId}/members`, { passportId: pid }); }
317
+ async mcpAddServer(teamId, mcp) { return this._post(`/v1/mcp/teams/${teamId}/mcp`, { mcpServer: mcp }); }
318
+ async mcpPolicies() { return this._get('/v1/mcp/policies'); }
319
+ async mcpApplyPolicy(teamId, pol){ return this._post(`/v1/mcp/teams/${teamId}/policies`, { policyId: pol }); }
320
+
321
+ // ── Proxy helpers ───────────────────────────────────────────────────────
322
+
323
+ /**
324
+ * Proxy an OpenAI chat completion through Kasbah governance.
325
+ * Drop-in replacement for OpenAI's /v1/chat/completions
326
+ * @param {object} body - OpenAI chat completion request body
327
+ * @param {string} upstreamKey - Your OpenAI API key
328
+ * @param {object} [options]
329
+ * @returns OpenAI-compatible response with _kasbahReceipt captured
330
+ */
331
+ async proxyOpenAI(body, upstreamKey, options = {}) {
332
+ const extraHeaders = { 'Authorization': `Bearer ${upstreamKey}` };
333
+ const { body: json, headers } = await this._requestRaw(
334
+ 'POST', '/v1/proxy/openai/v1/chat/completions', body, extraHeaders
335
+ );
336
+ return { ...json, _kasbahReceipt: headers['x-kasbah-receipt'] || null };
337
+ }
338
+
339
+ /**
340
+ * Proxy an Anthropic messages call through Kasbah governance.
341
+ * Drop-in replacement for Anthropic's /v1/messages
342
+ * @param {object} body - Anthropic messages request body
343
+ * @param {string} upstreamKey - Your Anthropic API key
344
+ * @param {object} [options]
345
+ * @returns Anthropic-compatible response with _kasbahReceipt captured
346
+ */
347
+ async proxyAnthropic(body, upstreamKey, options = {}) {
348
+ const extraHeaders = { 'x-api-key': upstreamKey };
349
+ const { body: json, headers } = await this._requestRaw(
350
+ 'POST', '/v1/proxy/anthropic/v1/messages', body, extraHeaders
351
+ );
352
+ return { ...json, _kasbahReceipt: headers['x-kasbah-receipt'] || null };
353
+ }
354
+
355
+ // ── Budget management ───────────────────────────────────────────────────
356
+
357
+ /**
358
+ * Get token/cost usage for a passport.
359
+ * @param {string} passportId
360
+ */
361
+ async getUsage(passportId) {
362
+ return this._request('GET', `/v1/usage/${passportId}`);
363
+ }
364
+
365
+ /**
366
+ * Set token/cost budget policy for a passport.
367
+ * @param {string} passportId
368
+ * @param {object} policy - { maxTokensPerMin?, maxTokensPerDay?, maxCostCentsPerDay? }
369
+ */
370
+ async setBudget(passportId, policy) {
371
+ return this._request('POST', `/v1/budgets/${passportId}`, policy);
372
+ }
373
+
374
+ /**
375
+ * Get current budget policy for a passport.
376
+ * @param {string} passportId
377
+ */
378
+ async getBudget(passportId) {
379
+ return this._request('GET', `/v1/budgets/${passportId}`);
380
+ }
381
+
382
+ // ── Agentic Layer ───────────────────────────────────────────────────────
383
+
384
+ /**
385
+ * Create a governed agent session.
386
+ * Returns { sessionId, agentId, status, manifest, ... }
387
+ * @param {object} opts
388
+ * @param {string} opts.agentId - human-readable agent name
389
+ * @param {string} opts.passportId - Kasbah passport for this agent
390
+ * @param {string} opts.goal - agent objective (logged)
391
+ * @param {object} opts.manifest - { allowedTools, maxTokens, maxCostCents, ... }
392
+ */
393
+ async createAgent(opts = {}) {
394
+ return this._request('POST', '/v1/agents', opts);
395
+ }
396
+
397
+ /**
398
+ * Govern a tool call for an active session.
399
+ * Call this BEFORE executing any tool.
400
+ * Returns { ok, verdict, reason?, receipt?, riskScore }
401
+ * @param {string} sessionId
402
+ * @param {string} tool - tool name, e.g. 'bash', 'write_file'
403
+ * @param {object} args - raw args object
404
+ * @param {string} argsText - flattened text for content scanning
405
+ */
406
+ async governTool(sessionId, tool, args = {}, argsText = '') {
407
+ return this._request('POST', `/v1/agents/${sessionId}/tool`, { tool, args, argsText });
408
+ }
409
+
410
+ /**
411
+ * Scan a tool result for injected instructions.
412
+ * Call this AFTER receiving a tool result, before feeding it back to the agent.
413
+ * Returns { ok, verdict?, reason?, riskScore }
414
+ * @param {string} sessionId
415
+ * @param {string} tool
416
+ * @param {string} result - raw tool output text
417
+ */
418
+ async scanToolResult(sessionId, tool, result) {
419
+ return this._request('POST', `/v1/agents/${sessionId}/tool-result`, { tool, result });
420
+ }
421
+
422
+ /**
423
+ * Record a conversation turn for budget and chain tracking.
424
+ * @param {string} sessionId
425
+ * @param {string} role - 'user' | 'assistant' | 'system' | 'tool'
426
+ * @param {string} content
427
+ * @param {number} tokens - token count for this turn
428
+ * @param {number} costCents - cost in cents for this turn
429
+ */
430
+ async recordTurn(sessionId, role, content, tokens = 0, costCents = 0) {
431
+ return this._request('POST', `/v1/agents/${sessionId}/turn`, { role, content, tokens, costCents });
432
+ }
433
+
434
+ /**
435
+ * Get the current state of a governed session.
436
+ * @param {string} sessionId
437
+ */
438
+ async getAgent(sessionId) {
439
+ return this._request('GET', `/v1/agents/${sessionId}`);
440
+ }
441
+
442
+ /**
443
+ * List all active governed sessions.
444
+ */
445
+ async listAgents() {
446
+ return this._request('GET', '/v1/agents');
447
+ }
448
+
449
+ /**
450
+ * Emergency kill: immediately stop a governed agent session.
451
+ * @param {string} sessionId
452
+ * @param {string} reason
453
+ */
454
+ async killAgent(sessionId, reason = 'manual') {
455
+ return this._request('DELETE', `/v1/agents/${sessionId}`, { reason });
456
+ }
457
+
458
+ /**
459
+ * Mark a session as completed normally.
460
+ * @param {string} sessionId
461
+ */
462
+ async completeAgent(sessionId) {
463
+ return this._request('POST', `/v1/agents/${sessionId}/complete`);
464
+ }
465
+
466
+ /**
467
+ * Wrap an OpenAI client so every API call is auto-governed.
468
+ *
469
+ * The wrapped client is a Proxy — it has the exact same interface as the
470
+ * original. All method calls transparently go through governTool() first.
471
+ *
472
+ * Usage:
473
+ * const session = await kasbah.createAgent({ agentId: 'my-bot', ... });
474
+ * const governed = kasbah.wrapOpenAI(openai, session.sessionId);
475
+ * // now governed.chat.completions.create(...) is auto-governed
476
+ *
477
+ * @param {object} openaiClient - OpenAI SDK client instance
478
+ * @param {string} sessionId
479
+ */
480
+ wrapOpenAI(openaiClient, sessionId) {
481
+ return this._wrapClient(openaiClient, sessionId, 'openai');
482
+ }
483
+
484
+ /**
485
+ * Wrap an Anthropic client so every API call is auto-governed.
486
+ * @param {object} anthropicClient - Anthropic SDK client instance
487
+ * @param {string} sessionId
488
+ */
489
+ wrapAnthropic(anthropicClient, sessionId) {
490
+ return this._wrapClient(anthropicClient, sessionId, 'anthropic');
491
+ }
492
+
493
+ _wrapClient(client, sessionId, type) {
494
+ const self = this;
495
+ const intercept = async (methodPath, originalFn, args) => {
496
+ // Extract text for governance
497
+ const firstArg = args[0] || {};
498
+ const messages = firstArg.messages || firstArg.prompt || '';
499
+ const argsText = typeof messages === 'string'
500
+ ? messages
501
+ : Array.isArray(messages)
502
+ ? messages.map(m => (typeof m.content === 'string' ? m.content : JSON.stringify(m.content))).join('\n')
503
+ : JSON.stringify(firstArg).slice(0, 800);
504
+
505
+ const decision = await self.governTool(sessionId, methodPath, firstArg, argsText);
506
+ if (!decision.ok) {
507
+ const err = new Error(`KasbahOS blocked: ${decision.reason}`);
508
+ err.kasbah = decision;
509
+ err.verdict = decision.verdict;
510
+ throw err;
511
+ }
512
+
513
+ // Execute the real call
514
+ const result = await originalFn.apply(client, args);
515
+
516
+ // Scan response for injection
517
+ const responseText = type === 'openai'
518
+ ? result?.choices?.[0]?.message?.content || ''
519
+ : result?.content?.[0]?.text || '';
520
+ if (responseText) {
521
+ await self.scanToolResult(sessionId, methodPath, responseText);
522
+ }
523
+
524
+ // Record token usage
525
+ const usage = result?.usage;
526
+ const tokens = usage
527
+ ? (usage.total_tokens || (usage.input_tokens || 0) + (usage.output_tokens || 0))
528
+ : 0;
529
+ if (tokens > 0) {
530
+ await self.recordTurn(sessionId, 'assistant', responseText.slice(0, 400), tokens, 0);
531
+ }
532
+
533
+ return result;
534
+ };
535
+
536
+ // Build a recursive proxy
537
+ const makeProxy = (target, pathPrefix) => new Proxy(target, {
538
+ get(inner, prop) {
539
+ const val = inner[prop];
540
+ if (typeof val === 'function') {
541
+ return (...args) => intercept(`${pathPrefix}.${String(prop)}`, val, args);
542
+ }
543
+ if (val && typeof val === 'object') {
544
+ return makeProxy(val, `${pathPrefix}.${String(prop)}`);
545
+ }
546
+ return val;
547
+ },
548
+ });
549
+
550
+ return makeProxy(client, type);
551
+ }
552
+
553
+ // ── HTTP internals ──────────────────────────────────────────────────────
554
+
555
+ async _get(path) { return this._request('GET', path); }
556
+ async _post(path, body) { return this._request('POST', path, body); }
557
+
558
+ async _request(method, path, body = null, attempt = 1) {
559
+ const parsed = new url.URL(this.baseUrl + path);
560
+ const isHttps = parsed.protocol === 'https:';
561
+ const lib = isHttps ? https : http;
562
+
563
+ const bodyStr = body ? JSON.stringify(body) : null;
564
+ const headers = {
565
+ 'Content-Type': 'application/json',
566
+ 'x-api-key': this.apiKey,
567
+ 'x-kasbah-sdk': `node/${SDK_VERSION}`,
568
+ };
569
+ if (bodyStr) headers['Content-Length'] = Buffer.byteLength(bodyStr);
570
+
571
+ return new Promise((resolve, reject) => {
572
+ const req = lib.request({
573
+ hostname: parsed.hostname,
574
+ port: parsed.port || (isHttps ? 443 : 80),
575
+ path: parsed.pathname + parsed.search,
576
+ method,
577
+ headers,
578
+ timeout: this.timeout,
579
+ }, (res) => {
580
+ let data = '';
581
+ res.on('data', chunk => { data += chunk; });
582
+ res.on('end', () => {
583
+ try {
584
+ const json = JSON.parse(data);
585
+ if (res.statusCode >= 200 && res.statusCode < 300) {
586
+ resolve(json);
587
+ } else if (res.statusCode >= 500 && this.autoRetry && attempt < 3) {
588
+ setTimeout(() => this._request(method, path, body, attempt + 1).then(resolve).catch(reject),
589
+ Math.pow(2, attempt) * 200);
590
+ } else {
591
+ reject(new KasbahError(json.error || `HTTP ${res.statusCode}`, res.statusCode, json));
592
+ }
593
+ } catch (e) {
594
+ reject(new KasbahError('Invalid JSON response', res.statusCode, data));
595
+ }
596
+ });
597
+ });
598
+
599
+ req.on('error', reject);
600
+ req.on('timeout', () => { req.destroy(); reject(new KasbahError('Request timeout', 408)); });
601
+ if (bodyStr) req.write(bodyStr);
602
+ req.end();
603
+ });
604
+ }
605
+
606
+ /**
607
+ * Like _request but returns { body, headers } so callers can inspect
608
+ * response headers (e.g. x-kasbah-receipt for proxy endpoints).
609
+ * @param {string} method
610
+ * @param {string} path
611
+ * @param {object|null} body
612
+ * @param {object} [extraHeaders] - Additional headers to merge in (e.g. Authorization)
613
+ * @param {number} [attempt]
614
+ * @returns {Promise<{ body: object, headers: object }>}
615
+ */
616
+ async _requestRaw(method, path, body = null, extraHeaders = {}, attempt = 1) {
617
+ const parsed = new url.URL(this.baseUrl + path);
618
+ const isHttps = parsed.protocol === 'https:';
619
+ const lib = isHttps ? https : http;
620
+
621
+ const bodyStr = body ? JSON.stringify(body) : null;
622
+ const headers = {
623
+ 'Content-Type': 'application/json',
624
+ 'x-api-key': this.apiKey,
625
+ 'x-kasbah-sdk': `node/${SDK_VERSION}`,
626
+ ...extraHeaders,
627
+ };
628
+ if (bodyStr) headers['Content-Length'] = Buffer.byteLength(bodyStr);
629
+
630
+ return new Promise((resolve, reject) => {
631
+ const req = lib.request({
632
+ hostname: parsed.hostname,
633
+ port: parsed.port || (isHttps ? 443 : 80),
634
+ path: parsed.pathname + parsed.search,
635
+ method,
636
+ headers,
637
+ timeout: this.timeout,
638
+ }, (res) => {
639
+ let data = '';
640
+ res.on('data', chunk => { data += chunk; });
641
+ res.on('end', () => {
642
+ try {
643
+ const json = JSON.parse(data);
644
+ if (res.statusCode >= 200 && res.statusCode < 300) {
645
+ resolve({ body: json, headers: res.headers });
646
+ } else if (res.statusCode >= 500 && this.autoRetry && attempt < 3) {
647
+ setTimeout(() => this._requestRaw(method, path, body, extraHeaders, attempt + 1).then(resolve).catch(reject),
648
+ Math.pow(2, attempt) * 200);
649
+ } else {
650
+ reject(new KasbahError(json.error || `HTTP ${res.statusCode}`, res.statusCode, json));
651
+ }
652
+ } catch (e) {
653
+ reject(new KasbahError('Invalid JSON response', res.statusCode, data));
654
+ }
655
+ });
656
+ });
657
+
658
+ req.on('error', reject);
659
+ req.on('timeout', () => { req.destroy(); reject(new KasbahError('Request timeout', 408)); });
660
+ if (bodyStr) req.write(bodyStr);
661
+ req.end();
662
+ });
663
+ }
664
+ }
665
+
666
+ // ── Sub-clients ──────────────────────────────────────────────────────────────
667
+
668
+ class PassportClient {
669
+ constructor(k) { this._k = k; }
670
+ async issue(opts = {}) { return this._k._post('/v1/passport/issue', opts); }
671
+ async list() { return this._k._get('/v1/passport/list'); }
672
+ async get(id) { return this._k._get(`/v1/passport/${id}`); }
673
+ async revoke(id) { return this._k._request('DELETE', `/v1/passport/${id}`); }
674
+ async spend(id) { return this._k._get(`/v1/passport/${id}/spend`); }
675
+ async setSpendPolicy(id, policy) { return this._k._post(`/v1/passport/${id}/spend/policy`, policy); }
676
+ }
677
+
678
+ class DelegationClient {
679
+ constructor(k) { this._k = k; }
680
+ async issue(opts = {}) { return this._k._post('/v1/delegation/issue', opts); }
681
+ async verify(tokenId) { return this._k._post('/v1/delegation/verify', { tokenId }); }
682
+ }
683
+
684
+ class HoneytokenClient {
685
+ constructor(k) { this._k = k; }
686
+ async list() { return this._k._get('/v1/honeytokens'); }
687
+ async deploy(service) { return this._k._post('/v1/honeytokens/deploy', { service }); }
688
+ async check(text) { return this._k._post('/v1/honeytokens/check', { text }); }
689
+ }
690
+
691
+ class SpendClient {
692
+ constructor(k) { this._k = k; }
693
+ async get(passportId) { return this._k._get(`/v1/passport/${passportId}/spend`); }
694
+ async setPolicy(passportId, policy) { return this._k._post(`/v1/passport/${passportId}/spend/policy`, policy); }
695
+ }
696
+
697
+ module.exports = Kasbah;
698
+ module.exports.Kasbah = Kasbah;
699
+ module.exports.KasbahError = KasbahError;
700
+ // Public-key receipt v2 — world-proof Ed25519 verification.
701
+ module.exports.receipt = require('./receipt');