devfortress-sdk 4.2.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/LICENSE ADDED
@@ -0,0 +1,63 @@
1
+ Business Source License 1.1
2
+
3
+ Licensor: Duncan Ndegwa / DevFortress
4
+ devfortress.net
5
+ Nairobi, Kenya
6
+
7
+ Licensed Work: DevFortress SDK
8
+ The Licensed Work is (c) 2026 Duncan Ndegwa
9
+
10
+ Change Date: Four years from the date each version of the
11
+ Licensed Work is first publicly distributed.
12
+ For devfortress-sdk@4.0.0, the Change Date
13
+ is 2030-01-01.
14
+
15
+ Change License: Apache License, Version 2.0
16
+
17
+ Additional Use Grant: You may use the Licensed Work to monitor,
18
+ observe, and protect your own applications,
19
+ APIs, and AI agents for security threats,
20
+ provided that you do not use the Licensed Work
21
+ to provide a competing commercial security
22
+ monitoring service or platform to third parties.
23
+
24
+ For commercial licensing, enterprise use, or questions:
25
+ support@devfortress.net
26
+
27
+ -----------------------------------------------------------------------------
28
+
29
+ Business Source License 1.1
30
+
31
+ Terms
32
+
33
+ The Licensor hereby grants you the right to copy, modify, create
34
+ derivative works, redistribute, and make non-production use of the
35
+ Licensed Work. The Licensor may make an Additional Use Grant, above,
36
+ permitting limited production use.
37
+
38
+ Effective on the Change Date, or the fourth anniversary of the first
39
+ publicly available distribution of a specific version of the Licensed
40
+ Work under this License, whichever comes first, the Licensor hereby
41
+ grants you rights under the terms of the Change License, and the
42
+ rights granted in the paragraph above terminate.
43
+
44
+ If your use of the Licensed Work does not comply with the requirements
45
+ currently in effect as described in this License, you must purchase a
46
+ commercial license from the Licensor, refrain from using the Licensed
47
+ Work, or make arrangements with the Licensor for a separate license.
48
+
49
+ For avoidance of doubt, a "Competing Service" means any commercial
50
+ product or service that provides API security monitoring, application
51
+ security monitoring, AI agent security monitoring, session threat
52
+ detection, automated threat response, or credential isolation
53
+ functionality to third parties.
54
+
55
+ Notice
56
+
57
+ The Business Source License (this document, or the "License") is not
58
+ an Open Source license. However, the Licensed Work will eventually be
59
+ made available under an Open Source License, as stated in this License.
60
+
61
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights
62
+ Reserved. "Business Source License" is a trademark of MariaDB
63
+ Corporation Ab.
package/README.md ADDED
@@ -0,0 +1,474 @@
1
+ # devfortress-sdk
2
+
3
+ The developer-first **Application and API security** SDK that stops attacks automatically — not just monitors them.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/devfortress-sdk)](https://www.npmjs.com/package/devfortress-sdk)
6
+ [![License: BUSL-1.1](https://img.shields.io/badge/License-BUSL--1.1-blue.svg)](https://github.com/duncan982/devfortress/blob/main/packages/devfortress-sdk/LICENSE)
7
+
8
+ ## 🔒 Privacy First — What We Collect vs. What We Never Collect
9
+
10
+ | ✅ We Collect | ❌ We Never Collect |
11
+ | ------------------------------------ | --------------------------------------- |
12
+ | IP address (hashable in strict mode) | Request/response body content |
13
+ | HTTP method & path | Cookies or session data |
14
+ | Status code & response time | Authorization headers or tokens |
15
+ | User agent (first 200 chars) | Query string values or form data |
16
+ | Timestamp | User PII (names, emails, phone numbers) |
17
+ | Session identifiers (anonymised) | Real session tokens |
18
+ | | Database queries or source code |
19
+
20
+ > **Your real session tokens never leave your server.** DevFortress uses a proprietary aliasing mechanism — the platform never sees or stores your actual tokens. [Full transparency →](https://devfortress.net/privacy/data-collected)
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install devfortress-sdk
26
+ ```
27
+
28
+ ## ⚡ Zero-Config Quick Start (under 3 minutes)
29
+
30
+ ```bash
31
+ npx devfortress-init
32
+ ```
33
+
34
+ Or one line in your code:
35
+
36
+ ```typescript
37
+ import df from 'devfortress-sdk/quick';
38
+ df.init({ apiKey: 'df_your_key' });
39
+ ```
40
+
41
+ ### Privacy-Strict Mode
42
+
43
+ ```typescript
44
+ df.init({ apiKey: 'df_...', privacy: 'strict' });
45
+ // IPs are SHA-256 hashed before sending, user agents omitted
46
+ ```
47
+
48
+ ### Debug Mode — See Exactly What's Sent
49
+
50
+ ```typescript
51
+ df.init({ apiKey: 'df_...', debug: true });
52
+ // Console: [DF →] DevFortress initialized (framework: express, privacy: standard)
53
+ ```
54
+
55
+ ### Data Snapshot — Inspect Before Sending
56
+
57
+ ```typescript
58
+ import { getDataSnapshot } from 'devfortress-sdk/quick';
59
+ console.log(getDataSnapshot(req));
60
+ // { collected: { ip, method, path, ... }, neverCollected: ['Request body', ...] }
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ### Express.js Middleware (Automatic)
66
+
67
+ ```typescript
68
+ import express from 'express';
69
+ import { devfortressMiddleware } from 'devfortress-sdk';
70
+
71
+ const app = express();
72
+
73
+ // Add DevFortress monitoring — automatically detects threats
74
+ app.use(
75
+ devfortressMiddleware({
76
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
77
+ })
78
+ );
79
+
80
+ app.get('/api/users', (req, res) => {
81
+ res.json({ users: [] });
82
+ });
83
+
84
+ app.listen(3000);
85
+ ```
86
+
87
+ ### Manual Event Tracking (Node.js)
88
+
89
+ ```typescript
90
+ import { DevFortressClient } from 'devfortress-sdk';
91
+
92
+ const client = new DevFortressClient({
93
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
94
+ });
95
+
96
+ // Track a security event
97
+ await client.trackEvent({
98
+ eventType: 'auth_failure',
99
+ ip: req.ip || '0.0.0.0',
100
+ userAgent: req.get('user-agent'),
101
+ metadata: {
102
+ username: req.body.username,
103
+ reason: 'invalid_password',
104
+ },
105
+ });
106
+ ```
107
+
108
+ ### Browser Client
109
+
110
+ ```typescript
111
+ import { DevFortressBrowserClient } from 'devfortress-sdk/browser';
112
+
113
+ const client = new DevFortressBrowserClient({
114
+ apiKey: 'your-publishable-key', // Use a PUBLIC/scoped key — visible in DevTools
115
+ });
116
+
117
+ // Install global error handler
118
+ const cleanup = client.installGlobalErrorHandler();
119
+
120
+ // Track API failures
121
+ client.trackApiFailure('/api/data', 500, 'GET');
122
+
123
+ // Cleanup when done
124
+ cleanup();
125
+ ```
126
+
127
+ > ⚠️ **Browser Security Notice:** The API key is visible to end users via browser DevTools. Use a scoped/publishable key with limited permissions — never use your secret admin key in browser builds.
128
+
129
+ ## Features
130
+
131
+ - 🚀 **Zero-config Express.js middleware** — automatic threat detection
132
+ - 🔒 **Pattern detection** — SQL injection, XSS, path traversal, brute force
133
+ - 📊 **Real-time security insights** — events stream to your DevFortress dashboard
134
+ - ⚡ **Non-blocking** — async event capture, never slows your API
135
+ - 🎯 **Custom event tracking** — send any security-relevant event
136
+ - 🌐 **Multi-platform** — Node.js, Browser, Express, FastAPI, Flask
137
+ - 🔧 **Type-safe** — full TypeScript support with exported types
138
+ - 🤖 **Agent Security (v3.2)** — observe AI agent tool calls, per-agent credential isolation, behavioral baselines, anomaly detection, scope enforcement
139
+ - 🔑 **Session Privacy** — Encrypted session identifiers, secure reverse-lookup, fallback cache
140
+ - 🛡️ **Closed-Loop Response** — automatic threat detection → block → webhook notification → action report
141
+ - 🏭 **Internal Mode (v3.3)** — Sub-millisecond inline protection with air-gap mode and zero external dependencies
142
+ - 🔄 **Hybrid Mode (v4.0)** — Local evaluation first, external enrichment with automatic failover
143
+ - ⚡ **Resilient Failover (v4.0)** — Automatic failover for hybrid mode resilience
144
+ - 🎫 **Tier Gating (v4.0)** — Starter/Pro/Enterprise subscription enforcement: modes, blocking, event limits at SDK level
145
+ - 📋 **Unified Audit Trail (v4.0)** — single timeline merging internal/external/hybrid decisions with stats, histograms, export
146
+
147
+ ## 🤖 AI Agent Security (v3.2)
148
+
149
+ Protect AI agents (LangChain, OpenAI, Anthropic, custom) from prompt injection, credential theft, and scope escalation.
150
+
151
+ ### Agent Tool Observability
152
+
153
+ ```typescript
154
+ import { DevFortress, AgentAdapter } from 'devfortress-sdk';
155
+
156
+ const df = new DevFortress({ apiKey: process.env.DEVFORTRESS_API_KEY! });
157
+ const agent = new AgentAdapter(df, {
158
+ agentId: 'research-agent',
159
+ agentName: 'Research Assistant',
160
+ sanitizeInputs: true, // Auto-redact keys/tokens/secrets
161
+ onFlagged: (toolCall, result) => {
162
+ console.error(`Tool ${toolCall.tool} flagged: risk=${result.riskScore}`);
163
+ },
164
+ });
165
+
166
+ // LangChain integration
167
+ await agent.observeLangChainTool(
168
+ 'web_search',
169
+ { query: 'test' },
170
+ { model: 'gpt-4o' }
171
+ );
172
+
173
+ // OpenAI function calling
174
+ await agent.observeOpenAIToolCall({
175
+ function: { name: 'get_weather', arguments: '{"location":"London"}' },
176
+ });
177
+
178
+ // Raw HTTP tool call
179
+ await agent.observeHttpToolCall('https://api.example.com/data', 'POST', {
180
+ statusCode: 200,
181
+ durationMs: 150,
182
+ });
183
+ ```
184
+
185
+ ### Agent Credential Isolation
186
+
187
+ ```typescript
188
+ import { DevFortress } from 'devfortress-sdk';
189
+
190
+ const df = new DevFortress({
191
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
192
+ appId: 'my-app',
193
+ mode: 'internal',
194
+ tier: 'enterprise',
195
+ });
196
+
197
+ // Isolate agent credentials — real keys never leave your server
198
+ const alias = await df.isolateCredential('sk-real-api-key-here', 'agent-1');
199
+
200
+ // Quarantine an agent (preserves session for forensics)
201
+ await df.quarantineAgent('agent-1', 'Suspicious tool usage');
202
+
203
+ // Full revocation — compromised agent
204
+ await df.revokeAgentAccess('agent-1', 'active_threat');
205
+ ```
206
+
207
+ ### Behavioral Baseline & Anomaly Detection
208
+
209
+ ```typescript
210
+ import { DevFortress } from 'devfortress-sdk';
211
+
212
+ const df = new DevFortress({
213
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
214
+ appId: 'my-app',
215
+ tier: 'enterprise',
216
+ });
217
+
218
+ // Register handler for anomalies
219
+ df.onAnomaly((signal) => {
220
+ if (signal.severity === 'critical') {
221
+ // Auto-quarantine agent on critical anomaly
222
+ df.quarantineAgent(signal.agentId, signal.description);
223
+ }
224
+ });
225
+
226
+ // Record sessions to build baseline (auto after 5 sessions)
227
+ df.recordSession({ agentId: 'agent-1', sessionId: 's1', toolCalls: [...] });
228
+
229
+ // Detect anomalies per tool call
230
+ const signals = df.analyzeToolCall('agent-1', 'delete_database', 1_000_000);
231
+ // → [{ type: 'scope_deviation', severity: 'medium' },
232
+ // { type: 'data_volume_anomaly', severity: 'high' }]
233
+ ```
234
+
235
+ ### Scope Enforcement (Prompt Injection Defence)
236
+
237
+ ```typescript
238
+ import { DevFortress } from 'devfortress-sdk';
239
+
240
+ const df = new DevFortress({
241
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
242
+ appId: 'my-app',
243
+ tier: 'enterprise',
244
+ });
245
+
246
+ // Define what tools an agent is allowed to use
247
+ df.defineAgentScope('agent-1', ['web_search', 'calculator', 'format'], true);
248
+
249
+ // Check before execution
250
+ if (!df.isToolAllowed('agent-1', 'shell_exec')) {
251
+ // CRITICAL: unsanctioned tool — likely prompt injection
252
+ // The anomaly detector also fires this automatically
253
+ }
254
+ ```
255
+
256
+ ## Configuration
257
+
258
+ ### Middleware Options
259
+
260
+ ```typescript
261
+ interface DevFortressMiddlewareOptions {
262
+ apiKey: string; // Required: Your DevFortress API key
263
+ endpoint?: string; // Default: https://www.devfortress.net/api/events/ingest
264
+ captureBody?: boolean; // Default: false — capture request body
265
+ captureHeaders?: boolean; // Default: false — capture request headers
266
+ excludePaths?: string[]; // Paths to exclude from monitoring (e.g. ['/health'])
267
+ sanitize?: (data) => data; // Sanitize metadata before sending
268
+ onRequest?: (req) => event; // Custom event detection callback
269
+ onError?: (error) => void; // Error handler for failed event sends
270
+ timeout?: number; // Request timeout in ms (default: 5000)
271
+ retries?: number; // Retry failed requests (default: 3)
272
+ }
273
+ ```
274
+
275
+ > ⚠️ **Privacy Warning:** When `captureHeaders` is `true`, headers including `Authorization`, `Cookie`, and session tokens are sent to DevFortress. When `captureBody` is `true`, raw request bodies (which may contain passwords, credit cards, etc.) are captured. Always use the `sanitize` callback to strip sensitive data.
276
+
277
+ ### Client Options
278
+
279
+ ```typescript
280
+ interface DevFortressClientOptions {
281
+ apiKey: string; // Required: Your DevFortress API key
282
+ endpoint?: string; // Default: https://www.devfortress.net/api/events/ingest
283
+ timeout?: number; // Request timeout in ms (default: 5000)
284
+ retries?: number; // Retry count (default: 3, exponential backoff)
285
+ debug?: boolean; // Enable debug logging (default: false)
286
+ }
287
+ ```
288
+
289
+ ## Event Types
290
+
291
+ The SDK automatically detects and reports:
292
+
293
+ | Event Type | Description | Auto-Detected |
294
+ | ----------------------- | ---------------------------------- | ------------- |
295
+ | `auth_failure` | Failed authentication (401/403) | ✅ |
296
+ | `validation_error` | Input validation errors (400/422) | ✅ |
297
+ | `rate_limit_exceeded` | Rate limit violations (429) | ✅ |
298
+ | `5xx_error` | Server errors | ✅ |
299
+ | `4xx_error` | Client errors | ✅ |
300
+ | `suspicious_pattern` | SQL injection, XSS, path traversal | ✅ |
301
+ | `sql_injection_attempt` | SQL injection detected | Manual |
302
+ | `xss_attempt` | XSS attack detected | Manual |
303
+ | `custom` | Any custom security event | Manual |
304
+
305
+ ## Python Middleware
306
+
307
+ ### FastAPI / Starlette
308
+
309
+ Copy `src/middleware/fastapi.py` into your project:
310
+
311
+ ```python
312
+ from devfortress_middleware import DevFortressMiddleware
313
+
314
+ app = FastAPI()
315
+ app.add_middleware(
316
+ DevFortressMiddleware,
317
+ api_key="your-api-key",
318
+ endpoint="https://www.devfortress.net/api/events/ingest"
319
+ )
320
+ ```
321
+
322
+ ### Flask
323
+
324
+ Copy `src/middleware/flask.py` into your project:
325
+
326
+ ```python
327
+ from devfortress_middleware import DevFortressFlask
328
+
329
+ app = Flask(__name__)
330
+ devfortress = DevFortressFlask(
331
+ app,
332
+ api_key="your-api-key",
333
+ endpoint="https://www.devfortress.net/api/events/ingest"
334
+ )
335
+ ```
336
+
337
+ ## Security Best Practices
338
+
339
+ 1. **API Key Management** — Store keys in environment variables, never commit them
340
+ 2. **Header/Body Capture** — Both default to `false`. Enable only with a `sanitize` callback
341
+ 3. **Browser Keys** — Use scoped/publishable keys for browser builds (visible in DevTools)
342
+ 4. **HTTPS Only** — The SDK warns if a non-HTTPS endpoint is configured
343
+ 5. **Error Handling** — Implement `onError` to prevent monitoring failures from affecting your API
344
+ 6. **Rate Limiting** — SDK respects rate limits (1000 events/minute per project)
345
+
346
+ ## Advanced Usage
347
+
348
+ ### Custom Threat Detection
349
+
350
+ ```typescript
351
+ app.use(
352
+ devfortressMiddleware({
353
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
354
+ onRequest: req => {
355
+ // Custom threat detection logic
356
+ if (isCustomThreat(req)) {
357
+ return {
358
+ eventType: 'custom',
359
+ severity: 'HIGH',
360
+ reason: 'Custom rule triggered',
361
+ };
362
+ }
363
+ return null;
364
+ },
365
+ })
366
+ );
367
+ ```
368
+
369
+ ### Sanitizing Sensitive Data
370
+
371
+ ```typescript
372
+ app.use(
373
+ devfortressMiddleware({
374
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
375
+ captureBody: true,
376
+ captureHeaders: true,
377
+ sanitize: data => {
378
+ // Strip sensitive fields before sending to DevFortress
379
+ const sanitized = { ...data };
380
+ if (sanitized.body) {
381
+ delete (sanitized.body as Record<string, unknown>).password;
382
+ delete (sanitized.body as Record<string, unknown>).creditCard;
383
+ }
384
+ if (sanitized.headers) {
385
+ delete (sanitized.headers as Record<string, unknown>).authorization;
386
+ delete (sanitized.headers as Record<string, unknown>).cookie;
387
+ }
388
+ return sanitized;
389
+ },
390
+ })
391
+ );
392
+ ```
393
+
394
+ ## Required Endpoints
395
+
396
+ The SDK communicates with these DevFortress platform endpoints (all must be accessible):
397
+
398
+ | Endpoint | Method | Purpose |
399
+ | -------------------------- | -------- | ------------------------ |
400
+ | `/api/events/ingest` | POST | Send security events |
401
+ | `/api/events/blocked` | GET | Check if IP is blocked |
402
+ | `/api/events/action-taken` | POST | Report actions taken |
403
+ | `/api/events/test-ips` | GET/POST | Manage test IP whitelist |
404
+
405
+ Base URL: `https://www.devfortress.net`
406
+
407
+ > **Note:** In Internal mode (`mode: 'internal'`), no external endpoints are called. In Hybrid mode, endpoints are called only for allowed traffic with automatic failover to local-only processing.
408
+
409
+ ## 🔄 Three-Mode Closed-Loop (v4.0)
410
+
411
+ SDK v4.0.0 introduces three closed-loop protection modes:
412
+
413
+ ```typescript
414
+ import { DevFortress } from 'devfortress-sdk';
415
+
416
+ // External mode — cloud-based analysis (default for Starter/Pro)
417
+ const dfExternal = new DevFortress({
418
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
419
+ appId: 'my-app',
420
+ mode: 'external',
421
+ tier: 'pro',
422
+ });
423
+
424
+ // Internal mode — air-gapped, zero network calls (Enterprise only)
425
+ const dfInternal = new DevFortress({
426
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
427
+ appId: 'my-app',
428
+ mode: 'internal',
429
+ tier: 'enterprise',
430
+ });
431
+
432
+ // Hybrid mode — local first, cloud enrichment with automatic failover
433
+ const dfHybrid = new DevFortress({
434
+ apiKey: process.env.DEVFORTRESS_API_KEY!,
435
+ appId: 'my-app',
436
+ mode: 'hybrid',
437
+ tier: 'enterprise',
438
+ });
439
+
440
+ // All modes use the same observe() API
441
+ const result = await dfHybrid.observe({
442
+ ip: '1.2.3.4',
443
+ endpoint: '/api/users',
444
+ });
445
+
446
+ // Unified audit trail — one view across all modes
447
+ const stats = dfHybrid.getAudit().getStats();
448
+ // { internalDecisions, externalDecisions, hybridDecisions, fallbackEvents, ... }
449
+ ```
450
+
451
+ ## Testing Your Integration
452
+
453
+ See the full [SDK Integration Guide](https://github.com/duncan982/devfortress/blob/main/docs/sdk-integration-guide.md) for step-by-step testing and troubleshooting.
454
+
455
+ ## Pricing
456
+
457
+ | Tier | Events/Month | Automated Actions | Retention |
458
+ | ---------------- | :----------: | :---------------: | :-------: |
459
+ | Starter ($99/mo) | 50K | ❌ alerts only | 7 days |
460
+ | Pro ($199/mo) | 500K | 500/mo | 30 days |
461
+ | Team ($499/mo) | 5M | 5K/mo | 90 days |
462
+
463
+ ## Support
464
+
465
+ - 📖 [SDK Integration Guide](https://github.com/duncan982/devfortress/blob/main/docs/sdk-integration-guide.md)
466
+ - 📋 [Full SDK Specification](https://github.com/duncan982/devfortress/blob/main/devfortress-updated/devfortress-sdk-spec.md)
467
+ - 💬 [GitHub Discussions](https://github.com/duncan982/devfortress/discussions)
468
+ - 🐛 [Report Issues](https://github.com/duncan982/devfortress/issues)
469
+
470
+ ## License
471
+
472
+ BUSL-1.1 © DevFortress (devfortress.net)
473
+
474
+ See [LICENSE](./LICENSE) for details. The Change License is Apache-2.0, effective 2030-01-01.