@bulwark-ai/gateway 0.1.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.
@@ -0,0 +1,1490 @@
1
+ import { Request, Response as Response$1, NextFunction, Router } from 'express';
2
+
3
+ interface PIIConfig {
4
+ enabled: boolean;
5
+ /** Action when PII detected: "block" rejects request, "redact" masks PII, "warn" logs but allows */
6
+ action?: "block" | "redact" | "warn";
7
+ /** PII types to detect */
8
+ types?: PIIType[];
9
+ /** Custom regex patterns */
10
+ customPatterns?: {
11
+ name: string;
12
+ pattern: string;
13
+ action?: "block" | "redact" | "warn";
14
+ }[];
15
+ }
16
+ type PIIType = "email" | "phone" | "ssn" | "credit_card" | "iban" | "ip_address" | "passport" | "drivers_license" | "date_of_birth" | "address" | "name" | "vat_number" | "national_id" | "medical_id";
17
+ interface PIIMatch {
18
+ type: PIIType | string;
19
+ value: string;
20
+ redacted: string;
21
+ start: number;
22
+ end: number;
23
+ }
24
+ interface ContentPolicy {
25
+ /** Unique policy ID */
26
+ id: string;
27
+ /** Human-readable name */
28
+ name: string;
29
+ /** Policy type */
30
+ type: "topic_restriction" | "keyword_block" | "regex_block" | "max_tokens";
31
+ /** Keywords or patterns to match */
32
+ patterns?: string[];
33
+ /** Regex pattern */
34
+ regex?: string;
35
+ /** Max tokens (for max_tokens type) */
36
+ maxTokens?: number;
37
+ /** Action when violated */
38
+ action: "block" | "warn";
39
+ /** Apply to specific teams/users only (empty = all) */
40
+ applyTo?: {
41
+ teams?: string[];
42
+ users?: string[];
43
+ };
44
+ /** Tenant scope (multi-tenant mode) */
45
+ tenantId?: string;
46
+ }
47
+
48
+ interface BudgetConfig {
49
+ enabled: boolean;
50
+ /** Default monthly token budget per user (0 = unlimited) */
51
+ defaultUserLimit?: number;
52
+ /** Default monthly token budget per team (0 = unlimited) */
53
+ defaultTeamLimit?: number;
54
+ /** Action when budget exceeded: "block" or "warn" */
55
+ onExceeded?: "block" | "warn";
56
+ /** Alert thresholds (0-1) — triggers callback */
57
+ alertThresholds?: number[];
58
+ /** Callback when threshold hit */
59
+ onAlert?: (alert: BudgetAlert) => void | Promise<void>;
60
+ }
61
+ interface BudgetAlert {
62
+ type: "user" | "team" | "tenant";
63
+ id: string;
64
+ threshold: number;
65
+ used: number;
66
+ limit: number;
67
+ costUsd: number;
68
+ }
69
+ interface UsageRecord {
70
+ userId?: string;
71
+ teamId?: string;
72
+ tenantId?: string;
73
+ model: string;
74
+ inputTokens: number;
75
+ outputTokens: number;
76
+ costUsd: number;
77
+ timestamp: string;
78
+ }
79
+ interface CostRecord {
80
+ model: string;
81
+ provider: string;
82
+ inputTokens: number;
83
+ outputTokens: number;
84
+ inputCost: number;
85
+ outputCost: number;
86
+ totalCost: number;
87
+ }
88
+ /** Per million tokens pricing */
89
+ declare const MODEL_PRICING: Record<string, {
90
+ input: number;
91
+ output: number;
92
+ }>;
93
+
94
+ interface RAGConfig {
95
+ enabled: boolean;
96
+ /** Embedding model */
97
+ embeddingModel?: string;
98
+ /** Chunk size in characters */
99
+ chunkSize?: number;
100
+ /** Chunk overlap */
101
+ chunkOverlap?: number;
102
+ /** Max chunks to retrieve per query */
103
+ topK?: number;
104
+ /** Minimum similarity score (0-1) */
105
+ minScore?: number;
106
+ }
107
+ interface Chunk {
108
+ id: string;
109
+ sourceId: string;
110
+ sourceName: string;
111
+ content: string;
112
+ embedding?: number[];
113
+ metadata?: Record<string, unknown>;
114
+ tenantId?: string;
115
+ }
116
+ interface SearchResult {
117
+ chunk: Chunk;
118
+ score: number;
119
+ }
120
+ interface KnowledgeSource {
121
+ id: string;
122
+ name: string;
123
+ type: "pdf" | "docx" | "text" | "markdown" | "csv" | "html" | "url" | "confluence" | "sharepoint";
124
+ status: "pending" | "indexing" | "active" | "error";
125
+ chunkCount: number;
126
+ tenantId?: string;
127
+ createdAt: string;
128
+ updatedAt: string;
129
+ }
130
+
131
+ interface ProviderConfig {
132
+ apiKey: string;
133
+ baseUrl?: string;
134
+ defaultModel?: string;
135
+ }
136
+ type GatewayProvider = "openai" | "anthropic" | "mistral" | "google" | "ollama" | "azure" | "custom";
137
+ interface GatewayConfig {
138
+ /** LLM provider credentials */
139
+ providers: Partial<Record<GatewayProvider, ProviderConfig>>;
140
+ /** Database connection — SQLite path or Postgres URL */
141
+ database: string;
142
+ /** PII detection config */
143
+ pii?: PIIConfig | boolean;
144
+ /** Content policies */
145
+ policies?: ContentPolicy[];
146
+ /** Budget enforcement */
147
+ budgets?: BudgetConfig | boolean;
148
+ /** Audit logging — true = enabled with defaults */
149
+ audit?: boolean;
150
+ /** RAG knowledge base */
151
+ rag?: RAGConfig;
152
+ /** Multi-tenant mode */
153
+ multiTenant?: boolean;
154
+ /** Default model to use if not specified per request */
155
+ defaultModel?: string;
156
+ /** Model pricing overrides (per million tokens) */
157
+ modelPricing?: Record<string, {
158
+ input: number;
159
+ output: number;
160
+ }>;
161
+ /** Retry config for failed LLM calls */
162
+ retry?: {
163
+ /** Max retry attempts (default: 2) */
164
+ maxRetries?: number;
165
+ /** Base delay in ms before retry (default: 1000). Doubles each attempt (exponential backoff). */
166
+ baseDelayMs?: number;
167
+ /** Retry on these HTTP status codes (default: [429, 500, 502, 503, 504]) */
168
+ retryableStatuses?: number[];
169
+ };
170
+ /**
171
+ * Fallback models — tried in order when the primary model fails.
172
+ * Maps a model name to a list of fallback models.
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * fallbacks: {
177
+ * "gpt-4o": ["gpt-4o-mini", "claude-sonnet-4-20250514"],
178
+ * "claude-opus-4-20250514": ["gpt-4o", "gemini-1.5-pro"],
179
+ * }
180
+ * ```
181
+ */
182
+ fallbacks?: Record<string, string[]>;
183
+ }
184
+ interface ChatMessage {
185
+ role: "system" | "user" | "assistant" | "tool";
186
+ content: string;
187
+ name?: string;
188
+ }
189
+ interface ChatRequest {
190
+ /** Model name — auto-routes to correct provider */
191
+ model?: string;
192
+ messages: ChatMessage[];
193
+ /** User ID for budget/audit tracking */
194
+ userId?: string;
195
+ /** Team ID for team-level budgets */
196
+ teamId?: string;
197
+ /** Tenant ID for multi-tenant isolation */
198
+ tenantId?: string;
199
+ /** RAG knowledge base to search */
200
+ knowledgeBase?: string;
201
+ /** Override PII settings for this request */
202
+ pii?: boolean;
203
+ /** Override policies for this request */
204
+ skipPolicies?: boolean;
205
+ /** Streaming */
206
+ stream?: boolean;
207
+ /** Pass-through params (temperature, max_tokens, etc) */
208
+ temperature?: number;
209
+ maxTokens?: number;
210
+ topP?: number;
211
+ stop?: string[];
212
+ }
213
+ interface ChatResponse {
214
+ /** Generated text */
215
+ content: string;
216
+ /** Model used */
217
+ model: string;
218
+ /** Provider used */
219
+ provider: GatewayProvider;
220
+ /** Token usage */
221
+ usage: {
222
+ inputTokens: number;
223
+ outputTokens: number;
224
+ totalTokens: number;
225
+ };
226
+ /** Cost in USD */
227
+ cost: {
228
+ input: number;
229
+ output: number;
230
+ total: number;
231
+ };
232
+ /** PII detections (if any were found and redacted) */
233
+ piiDetections?: {
234
+ type: string;
235
+ redacted: boolean;
236
+ }[];
237
+ /** Policy violations (if any) */
238
+ policyViolations?: {
239
+ policy: string;
240
+ action: "blocked" | "warned";
241
+ }[];
242
+ /** RAG sources used */
243
+ sources?: {
244
+ content: string;
245
+ source: string;
246
+ score: number;
247
+ }[];
248
+ /** Audit log entry ID */
249
+ auditId?: string;
250
+ /** Request duration in ms */
251
+ durationMs: number;
252
+ }
253
+
254
+ interface PolicyViolation {
255
+ policyId: string;
256
+ policyName: string;
257
+ action: "block" | "warn";
258
+ matchedPattern?: string;
259
+ }
260
+ interface CheckContext {
261
+ userId?: string;
262
+ teamId?: string;
263
+ tenantId?: string;
264
+ }
265
+ declare class PolicyEngine {
266
+ private policies;
267
+ constructor(policies: ContentPolicy[]);
268
+ /** Get all policies */
269
+ getPolicies(): ContentPolicy[];
270
+ /** Add a policy at runtime */
271
+ addPolicy(policy: ContentPolicy): void;
272
+ /** Remove a policy by ID */
273
+ removePolicy(id: string): void;
274
+ /** Check messages against all active policies */
275
+ check(messages: ChatMessage[], context: CheckContext): PolicyViolation[];
276
+ }
277
+
278
+ /**
279
+ * Pluggable database abstraction.
280
+ * SQLite by default (zero-config), Postgres for production.
281
+ */
282
+ interface Database {
283
+ init(): void;
284
+ run(sql: string, params?: unknown[]): void;
285
+ queryOne<T>(sql: string, params?: unknown[]): T | undefined;
286
+ queryAll<T>(sql: string, params?: unknown[]): T[];
287
+ close(): void;
288
+ }
289
+ /** Create database instance based on connection string */
290
+ declare function createDatabase(connection: string): Database;
291
+
292
+ interface AuditEntry {
293
+ id: string;
294
+ tenantId?: string;
295
+ userId?: string;
296
+ teamId?: string;
297
+ action: "chat" | "embed" | "search" | "upload" | "policy_block" | "pii_detected" | "budget_exceeded" | "login";
298
+ model?: string;
299
+ provider?: string;
300
+ inputTokens?: number;
301
+ outputTokens?: number;
302
+ costUsd?: number;
303
+ durationMs?: number;
304
+ piiDetections?: number;
305
+ policyViolations?: string[];
306
+ metadata?: Record<string, unknown>;
307
+ timestamp: string;
308
+ }
309
+ interface AuditStore {
310
+ log(entry: Omit<AuditEntry, "id" | "timestamp">): Promise<string>;
311
+ query(filters: AuditQuery): Promise<{
312
+ entries: AuditEntry[];
313
+ total: number;
314
+ }>;
315
+ }
316
+ interface AuditQuery {
317
+ tenantId?: string;
318
+ userId?: string;
319
+ teamId?: string;
320
+ action?: string;
321
+ from?: string;
322
+ to?: string;
323
+ limit?: number;
324
+ offset?: number;
325
+ }
326
+
327
+ /**
328
+ * Document chunking — splits text into overlapping chunks for embedding.
329
+ * Supports: plain text, markdown, code.
330
+ */
331
+ interface ChunkOptions {
332
+ /** Max characters per chunk */
333
+ chunkSize?: number;
334
+ /** Overlap between chunks */
335
+ chunkOverlap?: number;
336
+ /** Split strategy */
337
+ strategy?: "paragraph" | "sentence" | "fixed" | "markdown";
338
+ }
339
+ interface TextChunk {
340
+ content: string;
341
+ index: number;
342
+ metadata?: Record<string, unknown>;
343
+ }
344
+ declare function chunkText(text: string, options?: ChunkOptions): TextChunk[];
345
+
346
+ /**
347
+ * Knowledge Base — document ingestion, chunking, embedding, and retrieval.
348
+ *
349
+ * Uses SQLite for chunk storage with in-process cosine similarity search.
350
+ * For production with large datasets, use Postgres + pgvector.
351
+ *
352
+ * @example
353
+ * ```ts
354
+ * const kb = gateway.knowledgeBase;
355
+ * await kb.ingest("My document content...", { name: "contract.pdf", type: "pdf" });
356
+ * const results = await kb.search("what are the payment terms?");
357
+ * ```
358
+ */
359
+ declare class KnowledgeBase {
360
+ private db;
361
+ private config;
362
+ private embedder;
363
+ constructor(db: Database, config: RAGConfig, openaiApiKey: string);
364
+ /**
365
+ * Ingest text content into the knowledge base.
366
+ * Chunks the text, generates embeddings, and stores them.
367
+ */
368
+ ingest(content: string, source: {
369
+ name: string;
370
+ type: KnowledgeSource["type"];
371
+ tenantId?: string;
372
+ }, chunkOptions?: ChunkOptions): Promise<{
373
+ sourceId: string;
374
+ chunks: number;
375
+ }>;
376
+ /**
377
+ * Search the knowledge base using semantic similarity.
378
+ */
379
+ search(query: string, options?: {
380
+ tenantId?: string;
381
+ sourceId?: string;
382
+ topK?: number;
383
+ minScore?: number;
384
+ }): Promise<SearchResult[]>;
385
+ /** List all knowledge sources */
386
+ listSources(tenantId?: string): KnowledgeSource[];
387
+ /** Delete a knowledge source and all its chunks. If tenantId provided, verifies ownership. */
388
+ deleteSource(sourceId: string, tenantId?: string): void;
389
+ }
390
+
391
+ interface TenantConfig {
392
+ id: string;
393
+ name: string;
394
+ providerKeys?: Record<string, string>;
395
+ allowedModels?: string[];
396
+ monthlyBudgetUsd?: number;
397
+ policies?: string[];
398
+ settings?: Record<string, unknown>;
399
+ createdAt?: string;
400
+ }
401
+ /**
402
+ * Multi-tenant management.
403
+ * Handles tenant CRUD and ensures all queries are scoped by tenant_id.
404
+ */
405
+ declare class TenantManager {
406
+ private db;
407
+ constructor(db: Database);
408
+ /** Create a new tenant */
409
+ create(name: string, settings?: Record<string, unknown>): TenantConfig;
410
+ /** Get a tenant by ID */
411
+ get(id: string): TenantConfig | null;
412
+ /** List all tenants */
413
+ list(): TenantConfig[];
414
+ /** Update tenant settings */
415
+ update(id: string, updates: {
416
+ name?: string;
417
+ settings?: Record<string, unknown>;
418
+ }): void;
419
+ /** Delete a tenant and ALL its data */
420
+ delete(id: string): void;
421
+ /** Get usage stats for a tenant */
422
+ getUsage(id: string): {
423
+ requests: number;
424
+ tokens: number;
425
+ costUsd: number;
426
+ activeUsers: number;
427
+ };
428
+ }
429
+
430
+ /**
431
+ * Bulwark AI Gateway
432
+ *
433
+ * Enterprise AI governance layer — drop into any Node.js app.
434
+ * PII detection, budget control, audit logging, multi-tenant, RAG.
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * const gateway = new AIGateway({
439
+ * providers: { openai: { apiKey: process.env.OPENAI_API_KEY! } },
440
+ * database: "bulwark.db",
441
+ * pii: { enabled: true, action: "redact" },
442
+ * budgets: true,
443
+ * audit: true,
444
+ * });
445
+ *
446
+ * const res = await gateway.chat({
447
+ * model: "gpt-4o",
448
+ * userId: "user-123",
449
+ * messages: [{ role: "user", content: "Hello" }],
450
+ * });
451
+ * ```
452
+ */
453
+ declare class AIGateway {
454
+ private readonly db;
455
+ private readonly providers;
456
+ private readonly piiDetector;
457
+ private readonly promptGuard;
458
+ private readonly _policyEngine;
459
+ private readonly costCalculator;
460
+ private readonly budgetManager;
461
+ private readonly auditStore;
462
+ private readonly kb;
463
+ private readonly cache;
464
+ private readonly rateLimiter;
465
+ private readonly _tenantManager;
466
+ private readonly timeoutMs;
467
+ private readonly retryConfig;
468
+ private readonly fallbacks;
469
+ private initialized;
470
+ private shutdownRequested;
471
+ private activeRequests;
472
+ constructor(config: GatewayConfig);
473
+ /** Initialize database tables. Called automatically on first request. */
474
+ init(): Promise<void>;
475
+ /**
476
+ * Send a chat completion request through the governance pipeline.
477
+ *
478
+ * Pipeline: Validate → PII scan → Policy check → Rate limit → Budget check → [RAG augment] → LLM call (with timeout) → Token count → Cost calc → Audit log
479
+ */
480
+ chat(request: ChatRequest): Promise<ChatResponse>;
481
+ /**
482
+ * Streaming chat — runs the full governance pipeline, then streams the LLM response.
483
+ * Pre-flight checks (PII, policies, budget, rate limit) run BEFORE streaming starts.
484
+ * Output PII scanning runs on the accumulated full response after streaming ends.
485
+ *
486
+ * @example
487
+ * ```ts
488
+ * const stream = gateway.chatStream({ model: "gpt-4o", userId: "user-1", messages: [...] });
489
+ * for await (const chunk of stream) {
490
+ * if (chunk.type === "delta") process.stdout.write(chunk.content);
491
+ * if (chunk.type === "done") console.log("Cost:", chunk.cost);
492
+ * }
493
+ * ```
494
+ */
495
+ chatStream(request: ChatRequest): AsyncGenerator<{
496
+ type: "delta" | "sources" | "pii_warning" | "usage" | "done" | "error";
497
+ content?: string;
498
+ sources?: ChatResponse["sources"];
499
+ piiTypes?: string[];
500
+ usage?: ChatResponse["usage"];
501
+ cost?: ChatResponse["cost"];
502
+ auditId?: string;
503
+ durationMs?: number;
504
+ }>;
505
+ /** Validate chat request inputs */
506
+ private validateRequest;
507
+ /**
508
+ * Call LLM with retry + fallback chain.
509
+ * Tries the primary model with retries, then falls back to configured alternatives.
510
+ */
511
+ private callWithRetryAndFallback;
512
+ /** Call LLM with timeout */
513
+ private callWithTimeout;
514
+ /** Resolve which provider handles a given model */
515
+ private resolveProvider;
516
+ private getProvider;
517
+ /** Graceful shutdown — wait for in-flight requests, close connections */
518
+ shutdown(): Promise<void>;
519
+ /** Get the audit store for direct queries */
520
+ get audit(): AuditStore;
521
+ /** Get the knowledge base for document ingestion and search */
522
+ get rag(): KnowledgeBase | null;
523
+ /** Get database instance for admin operations */
524
+ get database(): Database;
525
+ /** Get the policy engine for runtime policy management */
526
+ get policies(): PolicyEngine;
527
+ /** Get the tenant manager (multi-tenant mode only) */
528
+ get tenants(): TenantManager | null;
529
+ }
530
+ /** Bulwark-specific error with code and metadata */
531
+ declare class BulwarkError extends Error {
532
+ readonly code: string;
533
+ readonly details?: Record<string, unknown>;
534
+ readonly timestamp: string;
535
+ constructor(code: string, message: string, details?: Record<string, unknown>);
536
+ /** HTTP status code for this error */
537
+ get httpStatus(): number;
538
+ /** JSON-serializable representation */
539
+ toJSON(): {
540
+ error: string;
541
+ code: string;
542
+ details: Record<string, unknown> | undefined;
543
+ timestamp: string;
544
+ };
545
+ }
546
+
547
+ interface ScanResult {
548
+ text: string;
549
+ matches: PIIMatch[];
550
+ blocked: boolean;
551
+ redacted: boolean;
552
+ }
553
+ declare class PIIDetector {
554
+ private config;
555
+ private activeTypes;
556
+ constructor(config: PIIConfig);
557
+ /** Scan text for PII. Returns matches and optionally redacted text. */
558
+ scan(text: string): ScanResult;
559
+ }
560
+
561
+ /**
562
+ * Prompt injection detection and system prompt protection.
563
+ *
564
+ * Detects common prompt injection patterns:
565
+ * - "Ignore previous instructions"
566
+ * - "You are now..."
567
+ * - Role-play attacks ("Pretend you are DAN")
568
+ * - Delimiter injection (```, ----, ####)
569
+ * - Base64/encoded payloads
570
+ */
571
+ interface PromptGuardConfig {
572
+ enabled: boolean;
573
+ /** Action on injection detected */
574
+ action: "block" | "warn" | "sanitize";
575
+ /** Sensitivity: "low" catches obvious attacks, "high" catches subtle ones (more false positives) */
576
+ sensitivity?: "low" | "medium" | "high";
577
+ }
578
+ interface PromptGuardResult {
579
+ safe: boolean;
580
+ injections: {
581
+ pattern: string;
582
+ severity: "low" | "medium" | "high";
583
+ matched: string;
584
+ }[];
585
+ sanitizedText?: string;
586
+ }
587
+ declare class PromptGuard {
588
+ private config;
589
+ private patterns;
590
+ constructor(config: PromptGuardConfig);
591
+ /** Scan user message for prompt injection attempts */
592
+ scan(text: string): PromptGuardResult;
593
+ }
594
+ /**
595
+ * Create a hardened system prompt that resists injection.
596
+ * Wraps the original system prompt with protective instructions.
597
+ */
598
+ declare function hardenSystemPrompt(originalPrompt: string, options?: {
599
+ preventExtraction?: boolean;
600
+ enforceGDPR?: boolean;
601
+ }): string;
602
+
603
+ declare class CostCalculator {
604
+ private pricing;
605
+ constructor(overrides?: Record<string, {
606
+ input: number;
607
+ output: number;
608
+ }>);
609
+ /** Calculate cost for a request. Returns USD amounts. */
610
+ calculate(model: string, inputTokens: number, outputTokens: number): CostRecord;
611
+ /** Update pricing for a model */
612
+ setModelPrice(model: string, input: number, output: number): void;
613
+ }
614
+
615
+ interface BudgetCheck {
616
+ ok: boolean;
617
+ used: number;
618
+ limit: number;
619
+ costUsd: number;
620
+ }
621
+ declare class BudgetManager {
622
+ enabled: boolean;
623
+ private config;
624
+ private db;
625
+ constructor(db: Database, config: BudgetConfig);
626
+ /** Check if a user/team has budget remaining this month */
627
+ checkBudget(scope: {
628
+ userId?: string;
629
+ teamId?: string;
630
+ tenantId?: string;
631
+ }): Promise<BudgetCheck>;
632
+ /** Record token usage */
633
+ recordUsage(record: UsageRecord): Promise<void>;
634
+ }
635
+
636
+ declare function createAuditStore(db: Database): AuditStore;
637
+
638
+ /**
639
+ * Embedding generator — wraps OpenAI's embedding API.
640
+ * Produces 1536-dimensional vectors (text-embedding-3-small) or 3072 (text-embedding-3-large).
641
+ */
642
+ interface EmbeddingProvider {
643
+ embed(texts: string[]): Promise<number[][]>;
644
+ dimensions: number;
645
+ }
646
+ declare class OpenAIEmbeddings implements EmbeddingProvider {
647
+ private client;
648
+ private model;
649
+ dimensions: number;
650
+ constructor(apiKey: string, model?: string);
651
+ embed(texts: string[]): Promise<number[][]>;
652
+ }
653
+ /**
654
+ * Cosine similarity between two vectors.
655
+ * Returns value between -1 and 1 (higher = more similar).
656
+ */
657
+ declare function cosineSimilarity(a: number[], b: number[]): number;
658
+
659
+ /**
660
+ * Document parsers for RAG ingestion.
661
+ * Extracts text from PDF, DOCX, HTML, and plain text files.
662
+ */
663
+ /**
664
+ * Parse a PDF buffer into text.
665
+ * Requires `pdf-parse` as a peer dependency.
666
+ *
667
+ * @example
668
+ * ```ts
669
+ * const text = await parsePDF(fs.readFileSync("contract.pdf"));
670
+ * await kb.ingest(text, { name: "contract.pdf", type: "pdf" });
671
+ * ```
672
+ */
673
+ declare function parsePDF(buffer: Buffer): Promise<string>;
674
+ /**
675
+ * Parse an HTML string into plain text.
676
+ * Strips all tags, scripts, styles, and normalizes whitespace.
677
+ */
678
+ declare function parseHTML(html: string): string;
679
+ /**
680
+ * Parse a CSV string into text (row per line).
681
+ */
682
+ declare function parseCSV(csv: string): string;
683
+ /**
684
+ * Parse a Markdown file — strips formatting but preserves structure.
685
+ */
686
+ declare function parseMarkdown(md: string): string;
687
+ /**
688
+ * Auto-detect file type and parse to text.
689
+ */
690
+ declare function parseDocument(buffer: Buffer, filename: string): Promise<string>;
691
+
692
+ /**
693
+ * Cache and rate limiting abstraction.
694
+ * In-memory by default, Redis for production multi-instance deployments.
695
+ */
696
+ interface CacheStore {
697
+ /** Get a cached value */
698
+ get<T>(key: string): Promise<T | null>;
699
+ /** Set a value with optional TTL in seconds */
700
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void>;
701
+ /** Delete a key */
702
+ del(key: string): Promise<void>;
703
+ /** Increment a counter, returns new value */
704
+ incr(key: string, by?: number): Promise<number>;
705
+ /** Get counter value */
706
+ getCounter(key: string): Promise<number>;
707
+ /** Set expiry on a key */
708
+ expire(key: string, ttlSeconds: number): Promise<void>;
709
+ }
710
+ interface RateLimitConfig {
711
+ enabled: boolean;
712
+ /** Requests per window */
713
+ maxRequests: number;
714
+ /** Window size in seconds */
715
+ windowSeconds: number;
716
+ /** Scope: per-user, per-team, per-tenant, or per-ip */
717
+ scope: "user" | "team" | "tenant" | "ip";
718
+ }
719
+ interface RateLimitResult {
720
+ allowed: boolean;
721
+ remaining: number;
722
+ resetAt: number;
723
+ }
724
+ interface ResponseCacheConfig {
725
+ enabled: boolean;
726
+ /** TTL for cached responses in seconds */
727
+ ttlSeconds: number;
728
+ /** Only cache responses below this token count */
729
+ maxTokens?: number;
730
+ }
731
+
732
+ /** In-memory cache store — works for single-instance deployments */
733
+ declare class MemoryCacheStore implements CacheStore {
734
+ private store;
735
+ private counters;
736
+ private cleanupTimer;
737
+ constructor();
738
+ /** Stop background cleanup — call on shutdown */
739
+ close(): void;
740
+ private cleanup;
741
+ get<T>(key: string): Promise<T | null>;
742
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void>;
743
+ del(key: string): Promise<void>;
744
+ incr(key: string, by?: number): Promise<number>;
745
+ getCounter(key: string): Promise<number>;
746
+ expire(key: string, ttlSeconds: number): Promise<void>;
747
+ }
748
+
749
+ /**
750
+ * Redis cache store — for production multi-instance deployments.
751
+ * Requires `ioredis` as a peer dependency.
752
+ *
753
+ * @example
754
+ * ```ts
755
+ * import Redis from "ioredis";
756
+ * import { RedisCacheStore } from "@bulwark-ai/gateway/cache";
757
+ *
758
+ * const gateway = new AIGateway({
759
+ * cache: new RedisCacheStore(new Redis("redis://localhost:6379")),
760
+ * });
761
+ * ```
762
+ */
763
+ declare class RedisCacheStore implements CacheStore {
764
+ private client;
765
+ private prefix;
766
+ constructor(client: RedisLike, prefix?: string);
767
+ private key;
768
+ get<T>(key: string): Promise<T | null>;
769
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void>;
770
+ del(key: string): Promise<void>;
771
+ incr(key: string, by?: number): Promise<number>;
772
+ getCounter(key: string): Promise<number>;
773
+ expire(key: string, ttlSeconds: number): Promise<void>;
774
+ }
775
+ /** Minimal Redis client interface — compatible with ioredis and node-redis */
776
+ interface RedisLike {
777
+ get(key: string): Promise<string | null>;
778
+ set(key: string, value: string): Promise<unknown>;
779
+ setex(key: string, seconds: number, value: string): Promise<unknown>;
780
+ del(key: string): Promise<unknown>;
781
+ incr(key: string): Promise<number>;
782
+ incrby(key: string, increment: number): Promise<number>;
783
+ expire(key: string, seconds: number): Promise<unknown>;
784
+ }
785
+
786
+ declare class RateLimiter {
787
+ private store;
788
+ private config;
789
+ constructor(store: CacheStore, config: RateLimitConfig);
790
+ /** Check and consume a rate limit token. Returns whether the request is allowed. */
791
+ check(scope: {
792
+ userId?: string;
793
+ teamId?: string;
794
+ tenantId?: string;
795
+ ip?: string;
796
+ }): Promise<RateLimitResult>;
797
+ private getScopeId;
798
+ private currentWindow;
799
+ }
800
+
801
+ /**
802
+ * Response cache — caches identical LLM requests to save money.
803
+ * Uses SHA-256 hash of (model + messages) as cache key.
804
+ *
805
+ * @example
806
+ * ```ts
807
+ * const cache = new ResponseCache(store, { enabled: true, ttlSeconds: 3600 });
808
+ * const cached = await cache.get(request);
809
+ * if (cached) return cached; // saved $0.01
810
+ * const response = await llm.chat(request);
811
+ * await cache.set(request, response);
812
+ * ```
813
+ */
814
+ declare class ResponseCache {
815
+ private store;
816
+ private config;
817
+ constructor(store: CacheStore, config: ResponseCacheConfig);
818
+ /** Generate deterministic cache key from request */
819
+ private key;
820
+ /** Check if a cached response exists */
821
+ get(request: ChatRequest): Promise<ChatResponse | null>;
822
+ /** Cache a response */
823
+ set(request: ChatRequest, response: ChatResponse): Promise<void>;
824
+ }
825
+
826
+ /**
827
+ * SSE Streaming support for chat responses.
828
+ * Wraps provider streaming with governance checks (PII, policies, audit).
829
+ *
830
+ * @example
831
+ * ```ts
832
+ * // Express endpoint
833
+ * app.post("/api/ai/stream", async (req, res) => {
834
+ * res.setHeader("Content-Type", "text/event-stream");
835
+ * res.setHeader("Cache-Control", "no-cache");
836
+ * res.setHeader("Connection", "keep-alive");
837
+ *
838
+ * const stream = gateway.chatStream({ model: "gpt-4o", messages: req.body.messages, userId: "user-1" });
839
+ * for await (const event of stream) {
840
+ * res.write(`event: ${event.type}\ndata: ${JSON.stringify(event.data)}\n\n`);
841
+ * }
842
+ * res.write("event: done\ndata: {}\n\n");
843
+ * res.end();
844
+ * });
845
+ * ```
846
+ */
847
+ interface StreamEvent {
848
+ type: "delta" | "sources" | "pii_warning" | "error" | "usage" | "done";
849
+ data: {
850
+ content?: string;
851
+ sources?: {
852
+ content: string;
853
+ source: string;
854
+ score: number;
855
+ }[];
856
+ piiTypes?: string[];
857
+ error?: string;
858
+ usage?: {
859
+ inputTokens: number;
860
+ outputTokens: number;
861
+ totalTokens: number;
862
+ };
863
+ cost?: {
864
+ input: number;
865
+ output: number;
866
+ total: number;
867
+ };
868
+ auditId?: string;
869
+ durationMs?: number;
870
+ };
871
+ }
872
+ /**
873
+ * Creates an async iterable of stream events.
874
+ * Pre-flight checks (PII, policies, budget, rate limit) run before streaming starts.
875
+ * Token counting and audit logging happen after stream completes.
876
+ */
877
+ declare function createStreamAdapter(providerStream: AsyncIterable<string>, metadata: {
878
+ piiWarnings?: string[];
879
+ sources?: {
880
+ content: string;
881
+ source: string;
882
+ score: number;
883
+ }[];
884
+ }): AsyncGenerator<StreamEvent>;
885
+
886
+ /**
887
+ * GDPR Compliance Module
888
+ *
889
+ * Implements: Right to erasure (Art. 17), Data portability (Art. 20),
890
+ * Data retention, Consent tracking, Breach notification.
891
+ */
892
+
893
+ interface GDPRConfig {
894
+ /** Auto-delete audit/usage records older than this many days (0 = disabled) */
895
+ retentionDays?: number;
896
+ /** Hash user IDs in audit logs instead of storing plaintext */
897
+ hashUserIds?: boolean;
898
+ /** Don't store message content in audit logs — metadata only */
899
+ metadataOnlyAudit?: boolean;
900
+ /** Callback when PII breach detected (for notification obligations) */
901
+ onBreachDetected?: (breach: BreachEvent) => void | Promise<void>;
902
+ /** Allowed LLM provider regions (block if provider is outside) */
903
+ allowedRegions?: string[];
904
+ }
905
+ interface BreachEvent {
906
+ type: "pii_sent_to_llm" | "pii_in_response" | "unauthorized_access";
907
+ userId?: string;
908
+ tenantId?: string;
909
+ piiTypes: string[];
910
+ provider: string;
911
+ timestamp: string;
912
+ }
913
+ interface UserDataExport {
914
+ userId: string;
915
+ exportedAt: string;
916
+ auditEntries: unknown[];
917
+ usageRecords: unknown[];
918
+ knowledgeChunks: unknown[];
919
+ totalRecords: number;
920
+ }
921
+ declare class GDPRManager {
922
+ private db;
923
+ private config;
924
+ constructor(db: Database, config?: GDPRConfig);
925
+ /**
926
+ * Right to Erasure (Article 17) — delete ALL data for a user.
927
+ * Returns count of deleted records per table.
928
+ */
929
+ eraseUserData(userId: string): {
930
+ audit: number;
931
+ usage: number;
932
+ chunks: number;
933
+ };
934
+ /**
935
+ * Right to Erasure for a tenant — delete ALL tenant data.
936
+ */
937
+ eraseTenantData(tenantId: string): {
938
+ audit: number;
939
+ usage: number;
940
+ chunks: number;
941
+ sources: number;
942
+ policies: number;
943
+ };
944
+ /**
945
+ * Data Portability (Article 20) — export all data for a user as JSON.
946
+ */
947
+ exportUserData(userId: string): UserDataExport;
948
+ /**
949
+ * Data Retention — delete records older than retention period.
950
+ * Call this on a schedule (e.g., daily cron).
951
+ */
952
+ enforceRetention(): {
953
+ auditDeleted: number;
954
+ usageDeleted: number;
955
+ };
956
+ /**
957
+ * Generate a Data Processing Activity Report (for DPIA).
958
+ */
959
+ generateProcessingReport(tenantId?: string): ProcessingReport;
960
+ private deleteAndCount;
961
+ }
962
+ interface ProcessingReport {
963
+ generatedAt: string;
964
+ tenantId: string;
965
+ totalRequests: number;
966
+ uniqueUsers: number;
967
+ piiDetections: number;
968
+ policyBlocks: number;
969
+ dataProcessors: {
970
+ name: string;
971
+ requestCount: number;
972
+ }[];
973
+ retentionPolicy: string;
974
+ piiHandling: string;
975
+ auditLevel: string;
976
+ }
977
+
978
+ /**
979
+ * SOC 2 Compliance Module
980
+ *
981
+ * Implements: Immutable audit logs, Change tracking, Health monitoring,
982
+ * Anomaly detection, Vendor tracking, Data classification.
983
+ */
984
+
985
+ interface SOC2Config {
986
+ /** Enable immutable audit mode — prevents DELETE on audit table */
987
+ immutableAudit?: boolean;
988
+ /** Anomaly detection thresholds */
989
+ anomalyThresholds?: {
990
+ /** Max requests per user per hour before alerting */
991
+ maxRequestsPerUserPerHour?: number;
992
+ /** Max PII detections per hour before alerting */
993
+ maxPiiPerHour?: number;
994
+ /** Max cost per user per day (USD) */
995
+ maxCostPerUserPerDay?: number;
996
+ };
997
+ /** Callback for anomaly alerts */
998
+ onAnomaly?: (anomaly: AnomalyEvent) => void | Promise<void>;
999
+ }
1000
+ interface AnomalyEvent {
1001
+ type: "high_request_rate" | "pii_spike" | "cost_spike" | "policy_violation_spike" | "unauthorized_access";
1002
+ severity: "low" | "medium" | "high" | "critical";
1003
+ userId?: string;
1004
+ tenantId?: string;
1005
+ details: Record<string, unknown>;
1006
+ timestamp: string;
1007
+ }
1008
+ interface HealthStatus {
1009
+ status: "healthy" | "degraded" | "unhealthy";
1010
+ database: "connected" | "error";
1011
+ providers: Record<string, "available" | "error">;
1012
+ uptime: number;
1013
+ lastRequest?: string;
1014
+ activeRequests: number;
1015
+ version: string;
1016
+ }
1017
+ interface ChangeLogEntry {
1018
+ id: string;
1019
+ entityType: "policy" | "budget" | "tenant" | "config";
1020
+ entityId: string;
1021
+ action: "created" | "updated" | "deleted";
1022
+ changedBy: string;
1023
+ previousValue?: string;
1024
+ newValue?: string;
1025
+ timestamp: string;
1026
+ }
1027
+ interface VendorReport {
1028
+ providers: {
1029
+ name: string;
1030
+ region: string;
1031
+ requestCount: number;
1032
+ totalTokens: number;
1033
+ totalCost: number;
1034
+ dataTypes: string[];
1035
+ }[];
1036
+ generatedAt: string;
1037
+ }
1038
+ declare class SOC2Manager {
1039
+ private db;
1040
+ private config;
1041
+ private startTime;
1042
+ constructor(db: Database, config?: SOC2Config);
1043
+ /** Log a configuration change (for change management audit trail) */
1044
+ logChange(entry: Omit<ChangeLogEntry, "id" | "timestamp">): void;
1045
+ /** Get change history for an entity */
1046
+ getChangeHistory(entityType: string, entityId: string): ChangeLogEntry[];
1047
+ /** Run anomaly detection on recent activity */
1048
+ detectAnomalies(): Promise<AnomalyEvent[]>;
1049
+ /** Generate vendor/sub-processor report for SOC 2 auditors */
1050
+ generateVendorReport(): VendorReport;
1051
+ /** Health check endpoint data */
1052
+ getHealthStatus(activeRequests: number): HealthStatus;
1053
+ }
1054
+
1055
+ /**
1056
+ * HIPAA Compliance Module
1057
+ *
1058
+ * Implements technical safeguards required for handling PHI (Protected Health Information)
1059
+ * in AI/LLM applications:
1060
+ * - PHI detection (18 HIPAA identifiers)
1061
+ * - De-identification (Safe Harbor method)
1062
+ * - Audit controls (access logging)
1063
+ * - Encryption verification
1064
+ * - BAA tracking
1065
+ * - Minimum necessary standard
1066
+ */
1067
+
1068
+ /** The 18 HIPAA Safe Harbor identifiers that must be removed for de-identification */
1069
+ declare const HIPAA_IDENTIFIERS: readonly ["name", "address", "dates", "phone", "fax", "email", "ssn", "medical_record_number", "health_plan_id", "account_number", "certificate_license", "vehicle_id", "device_id", "url", "ip_address", "biometric_id", "photo", "other_unique_id"];
1070
+ interface HIPAAConfig {
1071
+ enabled: boolean;
1072
+ /** PHI handling: "block" rejects any request containing PHI, "deidentify" strips it */
1073
+ action: "block" | "deidentify";
1074
+ /** Log PHI access events */
1075
+ auditPhiAccess?: boolean;
1076
+ /** Require BAA verification before processing */
1077
+ requireBAA?: boolean;
1078
+ /** Verified BAA provider list */
1079
+ baaProviders?: string[];
1080
+ /** Data retention for PHI audit logs (days) */
1081
+ phiRetentionDays?: number;
1082
+ }
1083
+ interface PHIAccessLog {
1084
+ userId: string;
1085
+ action: "view" | "process" | "export" | "delete";
1086
+ phiTypes: string[];
1087
+ provider?: string;
1088
+ justification?: string;
1089
+ timestamp: string;
1090
+ }
1091
+ declare class HIPAAManager {
1092
+ private db;
1093
+ private config;
1094
+ constructor(db: Database, config: HIPAAConfig);
1095
+ /** Log PHI access event (required by HIPAA audit controls) */
1096
+ logAccess(entry: Omit<PHIAccessLog, "timestamp">): void;
1097
+ /** Query PHI access log */
1098
+ getAccessLog(userId?: string, limit?: number): PHIAccessLog[];
1099
+ /** Register a BAA (Business Associate Agreement) with a provider */
1100
+ registerBAA(provider: string, signedDate: string, expiryDate?: string, contactEmail?: string): void;
1101
+ /** Check if a provider has a valid BAA */
1102
+ hasValidBAA(provider: string): boolean;
1103
+ /** Verify provider has BAA before sending data (if requireBAA is enabled) */
1104
+ verifyProvider(provider: string): {
1105
+ allowed: boolean;
1106
+ reason?: string;
1107
+ };
1108
+ /** Get recommended PII types to enable for HIPAA compliance */
1109
+ getRecommendedPIITypes(): PIIType[];
1110
+ /** Generate HIPAA compliance report */
1111
+ generateComplianceReport(): {
1112
+ phiAccessEvents: number;
1113
+ uniqueUsers: number;
1114
+ activeBAAs: number;
1115
+ deidentificationEnabled: boolean;
1116
+ auditLogging: boolean;
1117
+ recommendations: string[];
1118
+ };
1119
+ /** Enforce PHI retention policy — delete old PHI access logs */
1120
+ enforceRetention(): {
1121
+ deleted: number;
1122
+ };
1123
+ }
1124
+
1125
+ /**
1126
+ * CCPA/CPRA Compliance Module (California Consumer Privacy Act)
1127
+ *
1128
+ * Implements:
1129
+ * - Right to know (data access)
1130
+ * - Right to delete
1131
+ * - Right to opt-out of sale/sharing
1132
+ * - Right to correct
1133
+ * - Automated decision-making opt-out (ADMT)
1134
+ * - Sensitive data consent tracking
1135
+ * - "Do Not Sell or Share" signal handling
1136
+ */
1137
+
1138
+ interface CCPAConfig {
1139
+ enabled: boolean;
1140
+ /** Honor Global Privacy Control (GPC) opt-out signals */
1141
+ honorGPC?: boolean;
1142
+ /** Track "Do Not Sell or Share" preferences */
1143
+ trackOptOut?: boolean;
1144
+ /** Log automated decision-making for ADMT compliance */
1145
+ logADMT?: boolean;
1146
+ }
1147
+ interface ConsumerRequest {
1148
+ type: "access" | "delete" | "correct" | "opt-out" | "opt-in";
1149
+ consumerId: string;
1150
+ requestedAt: string;
1151
+ completedAt?: string;
1152
+ status: "pending" | "verified" | "completed" | "denied";
1153
+ }
1154
+ declare class CCPAManager {
1155
+ private db;
1156
+ private config;
1157
+ constructor(db: Database, config: CCPAConfig);
1158
+ /** Right to Know — return all data for a consumer */
1159
+ accessRequest(consumerId: string): {
1160
+ data: unknown[];
1161
+ requestId: string;
1162
+ };
1163
+ /** Right to Delete — erase all consumer data */
1164
+ deleteRequest(consumerId: string): {
1165
+ requestId: string;
1166
+ deleted: boolean;
1167
+ };
1168
+ /** Right to Opt-Out of Sale/Sharing */
1169
+ optOut(consumerId: string, gpcSignal?: boolean): void;
1170
+ /** Check if consumer has opted out */
1171
+ isOptedOut(consumerId: string): boolean;
1172
+ /** Handle Global Privacy Control signal */
1173
+ handleGPC(consumerId: string): void;
1174
+ /** Get all consumer requests (for compliance reporting) */
1175
+ getRequests(consumerId?: string, limit?: number): ConsumerRequest[];
1176
+ /** Generate CCPA compliance report */
1177
+ generateReport(): {
1178
+ totalRequests: number;
1179
+ byType: Record<string, number>;
1180
+ optedOutConsumers: number;
1181
+ gpcSignals: number;
1182
+ avgResponseTime: string;
1183
+ };
1184
+ }
1185
+
1186
+ /**
1187
+ * Data Residency & Cross-Border Transfer Controls
1188
+ *
1189
+ * Implements:
1190
+ * - Provider region tracking (where does data go?)
1191
+ * - Region restriction (block requests to providers outside allowed regions)
1192
+ * - Transfer impact assessment logging
1193
+ * - Schrems II / EU-US Data Privacy Framework compliance
1194
+ */
1195
+ interface DataResidencyConfig {
1196
+ enabled: boolean;
1197
+ /** Allowed regions for data processing. If set, blocks providers outside these regions. */
1198
+ allowedRegions?: string[];
1199
+ /** Block cross-border transfers entirely */
1200
+ blockCrossBorder?: boolean;
1201
+ /** Log all cross-border transfers */
1202
+ logTransfers?: boolean;
1203
+ /** Your organization's primary region */
1204
+ primaryRegion?: string;
1205
+ }
1206
+ /** Known provider data processing regions */
1207
+ declare const PROVIDER_REGIONS: Record<string, {
1208
+ regions: string[];
1209
+ headquarters: string;
1210
+ dpf: boolean;
1211
+ description: string;
1212
+ }>;
1213
+ interface TransferAssessment {
1214
+ provider: string;
1215
+ sourceRegion: string;
1216
+ destinationRegions: string[];
1217
+ crossBorder: boolean;
1218
+ dpfCertified: boolean;
1219
+ allowed: boolean;
1220
+ reason?: string;
1221
+ }
1222
+ declare class DataResidencyManager {
1223
+ private config;
1224
+ constructor(config: DataResidencyConfig);
1225
+ /** Assess whether a transfer to a provider is allowed */
1226
+ assessTransfer(provider: string): TransferAssessment;
1227
+ /** Get all providers with their data residency status */
1228
+ getProviderMap(): Record<string, TransferAssessment>;
1229
+ /** Generate a Transfer Impact Assessment (TIA) report — required for GDPR cross-border */
1230
+ generateTIA(): {
1231
+ primaryRegion: string;
1232
+ allowedRegions: string[];
1233
+ providers: TransferAssessment[];
1234
+ crossBorderCount: number;
1235
+ blockedCount: number;
1236
+ recommendations: string[];
1237
+ };
1238
+ }
1239
+
1240
+ interface LLMRequest {
1241
+ model: string;
1242
+ messages: ChatMessage[];
1243
+ temperature?: number;
1244
+ maxTokens?: number;
1245
+ topP?: number;
1246
+ stop?: string[];
1247
+ stream?: boolean;
1248
+ }
1249
+ interface LLMResponse {
1250
+ content: string;
1251
+ usage: {
1252
+ inputTokens: number;
1253
+ outputTokens: number;
1254
+ totalTokens: number;
1255
+ };
1256
+ finishReason?: string;
1257
+ }
1258
+ interface LLMStreamChunk {
1259
+ content: string;
1260
+ done: boolean;
1261
+ usage?: LLMResponse["usage"];
1262
+ }
1263
+ interface LLMProvider {
1264
+ chat(request: LLMRequest): Promise<LLMResponse>;
1265
+ chatStream?(request: LLMRequest): AsyncIterable<LLMStreamChunk>;
1266
+ }
1267
+
1268
+ declare class OpenAIProvider implements LLMProvider {
1269
+ private client;
1270
+ constructor(config: ProviderConfig);
1271
+ chat(request: LLMRequest): Promise<LLMResponse>;
1272
+ chatStream(request: LLMRequest): AsyncIterable<LLMStreamChunk>;
1273
+ }
1274
+
1275
+ declare class AnthropicProvider implements LLMProvider {
1276
+ private client;
1277
+ constructor(config: ProviderConfig);
1278
+ chat(request: LLMRequest): Promise<LLMResponse>;
1279
+ chatStream(request: LLMRequest): AsyncIterable<LLMStreamChunk>;
1280
+ }
1281
+
1282
+ /**
1283
+ * Mistral AI provider — EU-based LLM (France).
1284
+ * Uses OpenAI-compatible API format.
1285
+ */
1286
+ declare class MistralProvider implements LLMProvider {
1287
+ private apiKey;
1288
+ private baseUrl;
1289
+ constructor(config: ProviderConfig);
1290
+ chat(request: LLMRequest): Promise<LLMResponse>;
1291
+ }
1292
+
1293
+ /**
1294
+ * Google Vertex AI / Gemini provider.
1295
+ * Uses the Gemini REST API format.
1296
+ *
1297
+ * @example
1298
+ * ```ts
1299
+ * providers: {
1300
+ * google: { apiKey: process.env.GOOGLE_AI_KEY! }
1301
+ * }
1302
+ * ```
1303
+ */
1304
+ declare class GoogleProvider implements LLMProvider {
1305
+ private apiKey;
1306
+ private baseUrl;
1307
+ constructor(config: ProviderConfig);
1308
+ chat(request: LLMRequest): Promise<LLMResponse>;
1309
+ }
1310
+
1311
+ /**
1312
+ * Ollama provider — run LLMs locally (Llama, Mistral, Phi, etc).
1313
+ * Zero data leaves your machine. Perfect for maximum privacy.
1314
+ *
1315
+ * @example
1316
+ * ```ts
1317
+ * providers: {
1318
+ * ollama: { apiKey: "", baseUrl: "http://localhost:11434" }
1319
+ * }
1320
+ * // Then: gateway.chat({ model: "llama3.2", ... })
1321
+ * ```
1322
+ */
1323
+ declare class OllamaProvider implements LLMProvider {
1324
+ private baseUrl;
1325
+ constructor(config: ProviderConfig);
1326
+ chat(request: LLMRequest): Promise<LLMResponse>;
1327
+ }
1328
+
1329
+ /**
1330
+ * Azure OpenAI provider — for enterprises using Azure's managed OpenAI service.
1331
+ * Requires: resourceName, deploymentName, apiVersion in config.
1332
+ *
1333
+ * @example
1334
+ * ```ts
1335
+ * providers: {
1336
+ * custom: {
1337
+ * apiKey: process.env.AZURE_OPENAI_KEY!,
1338
+ * baseUrl: "https://YOUR-RESOURCE.openai.azure.com/openai/deployments/YOUR-DEPLOYMENT",
1339
+ * }
1340
+ * }
1341
+ * ```
1342
+ */
1343
+ declare class AzureOpenAIProvider implements LLMProvider {
1344
+ private apiKey;
1345
+ private endpoint;
1346
+ private apiVersion;
1347
+ constructor(config: ProviderConfig & {
1348
+ apiVersion?: string;
1349
+ });
1350
+ chat(request: LLMRequest): Promise<LLMResponse>;
1351
+ }
1352
+
1353
+ /**
1354
+ * Express middleware that adds gateway to req.
1355
+ *
1356
+ * @example
1357
+ * ```ts
1358
+ * app.use(bulwarkMiddleware(gateway));
1359
+ * app.post("/api/chat", async (req, res) => {
1360
+ * const response = await req.bulwark.chat({ ... });
1361
+ * });
1362
+ * ```
1363
+ */
1364
+ declare function bulwarkMiddleware(gateway: AIGateway): (req: Request & {
1365
+ bulwark?: AIGateway;
1366
+ }, _res: Response$1, next: NextFunction) => void;
1367
+ /**
1368
+ * Mount a complete chat API endpoint with governance pipeline.
1369
+ *
1370
+ * @example
1371
+ * ```ts
1372
+ * app.use("/api/ai", bulwarkRouter(gateway, {
1373
+ * auth: (req) => ({ userId: req.user.id, teamId: req.user.team }),
1374
+ * maxBodySize: "1mb",
1375
+ * }));
1376
+ * // POST /api/ai/chat — governed chat completion
1377
+ * // GET /api/ai/audit — query audit log
1378
+ * ```
1379
+ */
1380
+ declare function bulwarkRouter(gateway: AIGateway, options?: {
1381
+ auth?: (req: Request) => {
1382
+ userId?: string;
1383
+ teamId?: string;
1384
+ tenantId?: string;
1385
+ } | null;
1386
+ maxBodySize?: string;
1387
+ }): Router;
1388
+
1389
+ /**
1390
+ * Next.js App Router handler factory.
1391
+ * No `next` dependency required — uses Web API Response.
1392
+ *
1393
+ * @example
1394
+ * ```ts
1395
+ * // app/api/ai/chat/route.ts
1396
+ * import { createNextHandler } from "@bulwark-ai/gateway";
1397
+ * import { gateway } from "@/lib/bulwark";
1398
+ * export const POST = createNextHandler(gateway, {
1399
+ * auth: (req) => ({ userId: req.headers.get("x-user-id") || undefined }),
1400
+ * });
1401
+ * ```
1402
+ */
1403
+ interface RequestLike {
1404
+ json(): Promise<unknown>;
1405
+ headers: {
1406
+ get(key: string): string | null;
1407
+ };
1408
+ nextUrl?: {
1409
+ searchParams: {
1410
+ get(key: string): string | null;
1411
+ };
1412
+ };
1413
+ url?: string;
1414
+ }
1415
+ declare function createNextHandler(gateway: AIGateway, options?: {
1416
+ auth?: (req: RequestLike) => {
1417
+ userId?: string;
1418
+ teamId?: string;
1419
+ tenantId?: string;
1420
+ } | null;
1421
+ }): (req: RequestLike) => Promise<Response>;
1422
+ declare function createNextAuditHandler(gateway: AIGateway): (req: RequestLike) => Promise<Response>;
1423
+
1424
+ /**
1425
+ * Fastify plugin for Bulwark AI.
1426
+ *
1427
+ * @example
1428
+ * ```ts
1429
+ * import Fastify from "fastify";
1430
+ * import { bulwarkPlugin } from "@bulwark-ai/gateway/middleware/fastify";
1431
+ *
1432
+ * const app = Fastify();
1433
+ * app.register(bulwarkPlugin, {
1434
+ * gateway,
1435
+ * prefix: "/api/ai",
1436
+ * auth: (req) => ({ userId: req.headers["x-user-id"] }),
1437
+ * });
1438
+ * ```
1439
+ */
1440
+ declare function bulwarkPlugin(fastify: FastifyLike, options: {
1441
+ gateway: AIGateway;
1442
+ prefix?: string;
1443
+ auth?: (req: unknown) => {
1444
+ userId?: string;
1445
+ teamId?: string;
1446
+ tenantId?: string;
1447
+ } | null;
1448
+ }, done: () => void): void;
1449
+ /** Minimal Fastify interfaces to avoid requiring fastify as dependency */
1450
+ interface FastifyLike {
1451
+ post(path: string, handler: (req: unknown, reply: FastifyReply) => Promise<unknown>): void;
1452
+ get(path: string, handler: (req: unknown, reply: FastifyReply) => Promise<unknown>): void;
1453
+ }
1454
+ interface FastifyReply {
1455
+ status(code: number): FastifyReply;
1456
+ send(data: unknown): FastifyReply;
1457
+ }
1458
+
1459
+ /**
1460
+ * Admin API — full CRUD endpoints for the admin panel.
1461
+ */
1462
+
1463
+ interface AdminDashboard {
1464
+ requestsToday: number;
1465
+ requestsThisMonth: number;
1466
+ costToday: number;
1467
+ costThisMonth: number;
1468
+ activeUsers: number;
1469
+ topModels: {
1470
+ model: string;
1471
+ count: number;
1472
+ cost: number;
1473
+ }[];
1474
+ topUsers: {
1475
+ userId: string;
1476
+ count: number;
1477
+ cost: number;
1478
+ }[];
1479
+ costByTeam: {
1480
+ teamId: string;
1481
+ cost: number;
1482
+ tokens: number;
1483
+ }[];
1484
+ }
1485
+ declare function getDashboard(db: Database, tenantId?: string): AdminDashboard;
1486
+ declare function createAdminRouter(gateway: AIGateway, options: {
1487
+ auth: (req: unknown) => boolean;
1488
+ }): any;
1489
+
1490
+ export { AIGateway, type AdminDashboard, type AnomalyEvent, AnthropicProvider, type AuditEntry, type AuditQuery, type AuditStore, AzureOpenAIProvider, type BreachEvent, type BudgetAlert, type BudgetConfig, BudgetManager, BulwarkError, type CCPAConfig, CCPAManager, type CacheStore, type ChangeLogEntry, type ChatMessage, type ChatRequest, type ChatResponse, type Chunk, type ConsumerRequest, type ContentPolicy, CostCalculator, type CostRecord, type DataResidencyConfig, DataResidencyManager, type Database, type GDPRConfig, GDPRManager, type GatewayConfig, type GatewayProvider, GoogleProvider, type HIPAAConfig, HIPAAManager, HIPAA_IDENTIFIERS, type HealthStatus, KnowledgeBase, type KnowledgeSource, type LLMProvider, type LLMRequest, type LLMResponse, MODEL_PRICING, MemoryCacheStore, MistralProvider, OllamaProvider, OpenAIEmbeddings, OpenAIProvider, type PHIAccessLog, type PIIConfig, PIIDetector, type PIIMatch, type PIIType, PROVIDER_REGIONS, PolicyEngine, type ProcessingReport, PromptGuard, type PromptGuardConfig, type PromptGuardResult, type ProviderConfig, type RAGConfig, type RateLimitConfig, type RateLimitResult, RateLimiter, RedisCacheStore, ResponseCache, type ResponseCacheConfig, type SOC2Config, SOC2Manager, type SearchResult, type StreamEvent, type TenantConfig, TenantManager, type TransferAssessment, type UsageRecord, type UserDataExport, type VendorReport, bulwarkMiddleware, bulwarkPlugin, bulwarkRouter, chunkText, cosineSimilarity, createAdminRouter, createAuditStore, createDatabase, createNextAuditHandler, createNextHandler, createStreamAdapter, getDashboard, hardenSystemPrompt, parseCSV, parseDocument, parseHTML, parseMarkdown, parsePDF };