@timmeck/brain-core 2.1.0 → 2.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/dist/api/middleware.d.ts +62 -0
- package/dist/api/middleware.js +107 -0
- package/dist/api/middleware.js.map +1 -0
- package/dist/api/server.d.ts +7 -0
- package/dist/api/server.js +52 -14
- package/dist/api/server.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/ipc/errors.d.ts +32 -0
- package/dist/ipc/errors.js +50 -0
- package/dist/ipc/errors.js.map +1 -0
- package/dist/ipc/validation.d.ts +15 -0
- package/dist/ipc/validation.js +62 -0
- package/dist/ipc/validation.js.map +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface RateLimitConfig {
|
|
2
|
+
windowMs?: number;
|
|
3
|
+
maxRequests?: number;
|
|
4
|
+
keyExtractor?: (req: {
|
|
5
|
+
socket: {
|
|
6
|
+
remoteAddress?: string;
|
|
7
|
+
};
|
|
8
|
+
}) => string;
|
|
9
|
+
}
|
|
10
|
+
export declare class RateLimiter {
|
|
11
|
+
private store;
|
|
12
|
+
private windowMs;
|
|
13
|
+
private maxRequests;
|
|
14
|
+
private keyExtractor;
|
|
15
|
+
private cleanupTimer;
|
|
16
|
+
constructor(config?: RateLimitConfig);
|
|
17
|
+
/**
|
|
18
|
+
* Check if a request is allowed. Returns { allowed, remaining, resetAt }.
|
|
19
|
+
*/
|
|
20
|
+
check(req: {
|
|
21
|
+
socket: {
|
|
22
|
+
remoteAddress?: string;
|
|
23
|
+
};
|
|
24
|
+
}): {
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
remaining: number;
|
|
27
|
+
resetAt: number;
|
|
28
|
+
};
|
|
29
|
+
/** Reset a specific key (for testing) */
|
|
30
|
+
reset(key: string): void;
|
|
31
|
+
/** Clear all entries */
|
|
32
|
+
clear(): void;
|
|
33
|
+
/** Stop cleanup timer */
|
|
34
|
+
stop(): void;
|
|
35
|
+
private cleanup;
|
|
36
|
+
}
|
|
37
|
+
export interface SizeLimitConfig {
|
|
38
|
+
maxBodyBytes?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read request body with size limit enforcement.
|
|
42
|
+
* Returns the body string or null if the limit is exceeded.
|
|
43
|
+
*/
|
|
44
|
+
export declare function readBodyWithLimit(req: import('node:http').IncomingMessage, config?: SizeLimitConfig): Promise<{
|
|
45
|
+
body: string;
|
|
46
|
+
error?: undefined;
|
|
47
|
+
} | {
|
|
48
|
+
body?: undefined;
|
|
49
|
+
error: string;
|
|
50
|
+
}>;
|
|
51
|
+
export interface SecurityHeadersConfig {
|
|
52
|
+
cors?: {
|
|
53
|
+
origins?: string[];
|
|
54
|
+
methods?: string[];
|
|
55
|
+
headers?: string[];
|
|
56
|
+
};
|
|
57
|
+
hsts?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Apply security headers to an HTTP response.
|
|
61
|
+
*/
|
|
62
|
+
export declare function applySecurityHeaders(res: import('node:http').ServerResponse, config?: SecurityHeadersConfig): void;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export class RateLimiter {
|
|
2
|
+
store = new Map();
|
|
3
|
+
windowMs;
|
|
4
|
+
maxRequests;
|
|
5
|
+
keyExtractor;
|
|
6
|
+
cleanupTimer;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.windowMs = config?.windowMs ?? 60_000;
|
|
9
|
+
this.maxRequests = config?.maxRequests ?? 100;
|
|
10
|
+
this.keyExtractor = config?.keyExtractor ?? ((req) => req.socket.remoteAddress ?? 'unknown');
|
|
11
|
+
// Cleanup expired entries every minute
|
|
12
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), 60_000);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Check if a request is allowed. Returns { allowed, remaining, resetAt }.
|
|
16
|
+
*/
|
|
17
|
+
check(req) {
|
|
18
|
+
const key = this.keyExtractor(req);
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const entry = this.store.get(key);
|
|
21
|
+
if (!entry || now >= entry.resetAt) {
|
|
22
|
+
this.store.set(key, { count: 1, resetAt: now + this.windowMs });
|
|
23
|
+
return { allowed: true, remaining: this.maxRequests - 1, resetAt: now + this.windowMs };
|
|
24
|
+
}
|
|
25
|
+
entry.count++;
|
|
26
|
+
if (entry.count > this.maxRequests) {
|
|
27
|
+
return { allowed: false, remaining: 0, resetAt: entry.resetAt };
|
|
28
|
+
}
|
|
29
|
+
return { allowed: true, remaining: this.maxRequests - entry.count, resetAt: entry.resetAt };
|
|
30
|
+
}
|
|
31
|
+
/** Reset a specific key (for testing) */
|
|
32
|
+
reset(key) {
|
|
33
|
+
this.store.delete(key);
|
|
34
|
+
}
|
|
35
|
+
/** Clear all entries */
|
|
36
|
+
clear() {
|
|
37
|
+
this.store.clear();
|
|
38
|
+
}
|
|
39
|
+
/** Stop cleanup timer */
|
|
40
|
+
stop() {
|
|
41
|
+
clearInterval(this.cleanupTimer);
|
|
42
|
+
}
|
|
43
|
+
cleanup() {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
for (const [key, entry] of this.store) {
|
|
46
|
+
if (now >= entry.resetAt) {
|
|
47
|
+
this.store.delete(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Read request body with size limit enforcement.
|
|
54
|
+
* Returns the body string or null if the limit is exceeded.
|
|
55
|
+
*/
|
|
56
|
+
export function readBodyWithLimit(req, config) {
|
|
57
|
+
const maxBytes = config?.maxBodyBytes ?? 102_400;
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
const chunks = [];
|
|
60
|
+
let totalBytes = 0;
|
|
61
|
+
let aborted = false;
|
|
62
|
+
req.on('data', (chunk) => {
|
|
63
|
+
if (aborted)
|
|
64
|
+
return;
|
|
65
|
+
totalBytes += chunk.length;
|
|
66
|
+
if (totalBytes > maxBytes) {
|
|
67
|
+
aborted = true;
|
|
68
|
+
req.destroy();
|
|
69
|
+
resolve({ error: `Request body exceeds limit of ${maxBytes} bytes` });
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
chunks.push(chunk);
|
|
73
|
+
});
|
|
74
|
+
req.on('end', () => {
|
|
75
|
+
if (aborted)
|
|
76
|
+
return;
|
|
77
|
+
resolve({ body: Buffer.concat(chunks).toString('utf8') });
|
|
78
|
+
});
|
|
79
|
+
req.on('error', () => {
|
|
80
|
+
if (aborted)
|
|
81
|
+
return;
|
|
82
|
+
resolve({ error: 'Request read error' });
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Apply security headers to an HTTP response.
|
|
88
|
+
*/
|
|
89
|
+
export function applySecurityHeaders(res, config) {
|
|
90
|
+
// CORS
|
|
91
|
+
const origins = config?.cors?.origins ?? ['*'];
|
|
92
|
+
const methods = config?.cors?.methods ?? ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'];
|
|
93
|
+
const headers = config?.cors?.headers ?? ['Content-Type', 'Authorization', 'X-API-Key'];
|
|
94
|
+
res.setHeader('Access-Control-Allow-Origin', origins.join(', '));
|
|
95
|
+
res.setHeader('Access-Control-Allow-Methods', methods.join(', '));
|
|
96
|
+
res.setHeader('Access-Control-Allow-Headers', headers.join(', '));
|
|
97
|
+
// Security headers
|
|
98
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
99
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
100
|
+
res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
101
|
+
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
102
|
+
// HSTS (only when explicitly enabled — requires HTTPS)
|
|
103
|
+
if (config?.hsts) {
|
|
104
|
+
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/api/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/api/server.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import type { IpcRouter } from '../ipc/server.js';
|
|
3
|
+
import type { RateLimitConfig, SizeLimitConfig, SecurityHeadersConfig } from './middleware.js';
|
|
3
4
|
export interface ApiServerOptions {
|
|
4
5
|
port: number;
|
|
5
6
|
router: IpcRouter;
|
|
6
7
|
apiKey?: string;
|
|
8
|
+
rateLimit?: RateLimitConfig;
|
|
9
|
+
sizeLimit?: SizeLimitConfig;
|
|
10
|
+
security?: SecurityHeadersConfig;
|
|
11
|
+
/** Callback for deep health checks (DB, engines, etc.) */
|
|
12
|
+
healthCheck?: () => Record<string, unknown>;
|
|
7
13
|
}
|
|
8
14
|
export interface RouteDefinition {
|
|
9
15
|
method: string;
|
|
@@ -17,6 +23,7 @@ export declare class BaseApiServer {
|
|
|
17
23
|
protected logger: import("winston").Logger;
|
|
18
24
|
private routes;
|
|
19
25
|
protected sseClients: Set<http.ServerResponse>;
|
|
26
|
+
private rateLimiter;
|
|
20
27
|
constructor(options: ApiServerOptions);
|
|
21
28
|
start(): void;
|
|
22
29
|
stop(): void;
|
package/dist/api/server.js
CHANGED
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import { getLogger } from '../utils/logger.js';
|
|
3
|
+
import { RateLimiter, readBodyWithLimit, applySecurityHeaders } from './middleware.js';
|
|
4
|
+
import { validateParams } from '../ipc/validation.js';
|
|
5
|
+
import { ValidationError } from '../ipc/errors.js';
|
|
3
6
|
export class BaseApiServer {
|
|
4
7
|
options;
|
|
5
8
|
server = null;
|
|
6
9
|
logger = getLogger();
|
|
7
10
|
routes;
|
|
8
11
|
sseClients = new Set();
|
|
12
|
+
rateLimiter;
|
|
9
13
|
constructor(options) {
|
|
10
14
|
this.options = options;
|
|
11
15
|
this.routes = this.buildRoutes();
|
|
16
|
+
this.rateLimiter = new RateLimiter(options.rateLimit);
|
|
12
17
|
}
|
|
13
18
|
start() {
|
|
14
19
|
const { port, apiKey } = this.options;
|
|
15
20
|
this.server = http.createServer((req, res) => {
|
|
16
|
-
|
|
17
|
-
res
|
|
18
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key');
|
|
21
|
+
// Security headers
|
|
22
|
+
applySecurityHeaders(res, this.options.security);
|
|
19
23
|
if (req.method === 'OPTIONS') {
|
|
20
24
|
res.writeHead(204);
|
|
21
25
|
res.end();
|
|
22
26
|
return;
|
|
23
27
|
}
|
|
28
|
+
// Rate limiting (skip health check)
|
|
29
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
30
|
+
if (url.pathname !== '/api/v1/health' && url.pathname !== '/api/v1/ready') {
|
|
31
|
+
const limit = this.rateLimiter.check(req);
|
|
32
|
+
res.setHeader('X-RateLimit-Remaining', String(limit.remaining));
|
|
33
|
+
res.setHeader('X-RateLimit-Reset', String(Math.ceil(limit.resetAt / 1000)));
|
|
34
|
+
if (!limit.allowed) {
|
|
35
|
+
this.json(res, 429, { error: 'Too Many Requests', message: 'Rate limit exceeded' });
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// API key auth
|
|
24
40
|
if (apiKey) {
|
|
25
41
|
const provided = req.headers['x-api-key'] ??
|
|
26
42
|
req.headers.authorization?.replace('Bearer ', '');
|
|
@@ -42,6 +58,7 @@ export class BaseApiServer {
|
|
|
42
58
|
});
|
|
43
59
|
}
|
|
44
60
|
stop() {
|
|
61
|
+
this.rateLimiter.stop();
|
|
45
62
|
for (const client of this.sseClients) {
|
|
46
63
|
try {
|
|
47
64
|
client.end();
|
|
@@ -62,9 +79,18 @@ export class BaseApiServer {
|
|
|
62
79
|
const pathname = url.pathname;
|
|
63
80
|
const method = req.method ?? 'GET';
|
|
64
81
|
const query = url.searchParams;
|
|
65
|
-
// Health check
|
|
82
|
+
// Health check (deep)
|
|
66
83
|
if (pathname === '/api/v1/health') {
|
|
67
|
-
|
|
84
|
+
const base = { status: 'ok', timestamp: new Date().toISOString(), uptime: Math.floor(process.uptime()), memory: Math.floor(process.memoryUsage().rss / 1024 / 1024) };
|
|
85
|
+
const extra = this.options.healthCheck?.() ?? {};
|
|
86
|
+
this.json(res, 200, { ...base, ...extra });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Readiness probe (for Kubernetes)
|
|
90
|
+
if (pathname === '/api/v1/ready') {
|
|
91
|
+
const extra = this.options.healthCheck?.() ?? {};
|
|
92
|
+
const ready = extra.db !== false && extra.ipc !== false;
|
|
93
|
+
this.json(res, ready ? 200 : 503, { ready, timestamp: new Date().toISOString(), ...extra });
|
|
68
94
|
return;
|
|
69
95
|
}
|
|
70
96
|
// SSE event stream
|
|
@@ -91,21 +117,27 @@ export class BaseApiServer {
|
|
|
91
117
|
}
|
|
92
118
|
// Generic RPC endpoint
|
|
93
119
|
if (pathname === '/api/v1/rpc' && method === 'POST') {
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
120
|
+
const bodyResult = await readBodyWithLimit(req, this.options.sizeLimit);
|
|
121
|
+
if (bodyResult.error) {
|
|
122
|
+
this.json(res, 413, { error: 'Payload Too Large', message: bodyResult.error });
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (!bodyResult.body) {
|
|
96
126
|
this.json(res, 400, { error: 'Bad Request', message: 'Empty request body' });
|
|
97
127
|
return;
|
|
98
128
|
}
|
|
99
|
-
const parsed = JSON.parse(body);
|
|
129
|
+
const parsed = JSON.parse(bodyResult.body);
|
|
100
130
|
// Batch RPC support
|
|
101
131
|
if (Array.isArray(parsed)) {
|
|
102
132
|
const results = parsed.map((call) => {
|
|
103
133
|
try {
|
|
104
|
-
const
|
|
134
|
+
const validated = validateParams(call.params);
|
|
135
|
+
const result = this.options.router.handle(call.method, validated);
|
|
105
136
|
return { id: call.id, result };
|
|
106
137
|
}
|
|
107
138
|
catch (err) {
|
|
108
|
-
|
|
139
|
+
const code = err instanceof ValidationError ? 'VALIDATION_ERROR' : 'ERROR';
|
|
140
|
+
return { id: call.id, error: err instanceof Error ? err.message : String(err), code };
|
|
109
141
|
}
|
|
110
142
|
});
|
|
111
143
|
this.json(res, 200, results);
|
|
@@ -116,11 +148,13 @@ export class BaseApiServer {
|
|
|
116
148
|
return;
|
|
117
149
|
}
|
|
118
150
|
try {
|
|
119
|
-
const
|
|
151
|
+
const validated = validateParams(parsed.params);
|
|
152
|
+
const result = this.options.router.handle(parsed.method, validated);
|
|
120
153
|
this.json(res, 200, { result });
|
|
121
154
|
}
|
|
122
155
|
catch (err) {
|
|
123
|
-
|
|
156
|
+
const status = err instanceof ValidationError ? 400 : 400;
|
|
157
|
+
this.json(res, status, { error: err instanceof Error ? err.message : String(err) });
|
|
124
158
|
}
|
|
125
159
|
return;
|
|
126
160
|
}
|
|
@@ -128,8 +162,12 @@ export class BaseApiServer {
|
|
|
128
162
|
let body = undefined;
|
|
129
163
|
if (method === 'POST' || method === 'PUT') {
|
|
130
164
|
try {
|
|
131
|
-
const
|
|
132
|
-
|
|
165
|
+
const bodyResult = await readBodyWithLimit(req, this.options.sizeLimit);
|
|
166
|
+
if (bodyResult.error) {
|
|
167
|
+
this.json(res, 413, { error: 'Payload Too Large', message: bodyResult.error });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
body = bodyResult.body ? JSON.parse(bodyResult.body) : {};
|
|
133
171
|
}
|
|
134
172
|
catch {
|
|
135
173
|
this.json(res, 400, { error: 'Bad Request', message: 'Invalid JSON body' });
|
package/dist/api/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/api/server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export { encodeMessage, MessageDecoder } from './ipc/protocol.js';
|
|
|
9
9
|
export { IpcServer } from './ipc/server.js';
|
|
10
10
|
export type { IpcRouter } from './ipc/server.js';
|
|
11
11
|
export { IpcClient } from './ipc/client.js';
|
|
12
|
+
export { validateParams, withValidation } from './ipc/validation.js';
|
|
13
|
+
export type { ValidationOptions } from './ipc/validation.js';
|
|
14
|
+
export { IpcError, ValidationError, NotFoundError, TimeoutError, ServiceUnavailableError } from './ipc/errors.js';
|
|
12
15
|
export { startMcpServer } from './mcp/server.js';
|
|
13
16
|
export type { McpServerOptions } from './mcp/server.js';
|
|
14
17
|
export { McpHttpServer } from './mcp/http-server.js';
|
|
@@ -16,6 +19,8 @@ export type { McpHttpServerOptions } from './mcp/http-server.js';
|
|
|
16
19
|
export { c, baseIcons, header, keyValue, statusBadge, progressBar, divider, table, stripAnsi } from './cli/colors.js';
|
|
17
20
|
export { BaseApiServer } from './api/server.js';
|
|
18
21
|
export type { ApiServerOptions, RouteDefinition } from './api/server.js';
|
|
22
|
+
export { RateLimiter, readBodyWithLimit, applySecurityHeaders } from './api/middleware.js';
|
|
23
|
+
export type { RateLimitConfig, SizeLimitConfig, SecurityHeadersConfig } from './api/middleware.js';
|
|
19
24
|
export { wilsonScore } from './math/wilson-score.js';
|
|
20
25
|
export { timeDecayFactor } from './math/time-decay.js';
|
|
21
26
|
export { deepMerge, loadConfigFile } from './config/loader.js';
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export { createConnection } from './db/connection.js';
|
|
|
9
9
|
export { encodeMessage, MessageDecoder } from './ipc/protocol.js';
|
|
10
10
|
export { IpcServer } from './ipc/server.js';
|
|
11
11
|
export { IpcClient } from './ipc/client.js';
|
|
12
|
+
export { validateParams, withValidation } from './ipc/validation.js';
|
|
13
|
+
export { IpcError, ValidationError, NotFoundError, TimeoutError, ServiceUnavailableError } from './ipc/errors.js';
|
|
12
14
|
// ── MCP ────────────────────────────────────────────────────
|
|
13
15
|
export { startMcpServer } from './mcp/server.js';
|
|
14
16
|
export { McpHttpServer } from './mcp/http-server.js';
|
|
@@ -16,6 +18,7 @@ export { McpHttpServer } from './mcp/http-server.js';
|
|
|
16
18
|
export { c, baseIcons, header, keyValue, statusBadge, progressBar, divider, table, stripAnsi } from './cli/colors.js';
|
|
17
19
|
// ── API ────────────────────────────────────────────────────
|
|
18
20
|
export { BaseApiServer } from './api/server.js';
|
|
21
|
+
export { RateLimiter, readBodyWithLimit, applySecurityHeaders } from './api/middleware.js';
|
|
19
22
|
// ── Math ───────────────────────────────────────────────────
|
|
20
23
|
export { wilsonScore } from './math/wilson-score.js';
|
|
21
24
|
export { timeDecayFactor } from './math/time-decay.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,8DAA8D;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAElH,8DAA8D;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,8DAA8D;AAC9D,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEtH,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3F,8DAA8D;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,8DAA8D;AAC9D,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQ/D,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,2DAA2D;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAU7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,4DAA4D;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error for IPC operations.
|
|
3
|
+
*/
|
|
4
|
+
export declare class IpcError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly statusCode: number;
|
|
7
|
+
constructor(message: string, code: string, statusCode?: number);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when IPC params fail validation.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ValidationError extends IpcError {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Thrown when a requested method or resource is not found.
|
|
17
|
+
*/
|
|
18
|
+
export declare class NotFoundError extends IpcError {
|
|
19
|
+
constructor(message: string);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when an IPC operation times out.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TimeoutError extends IpcError {
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Thrown when a required service is not available.
|
|
29
|
+
*/
|
|
30
|
+
export declare class ServiceUnavailableError extends IpcError {
|
|
31
|
+
constructor(message?: string);
|
|
32
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error for IPC operations.
|
|
3
|
+
*/
|
|
4
|
+
export class IpcError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
statusCode;
|
|
7
|
+
constructor(message, code, statusCode = 400) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'IpcError';
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.statusCode = statusCode;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when IPC params fail validation.
|
|
16
|
+
*/
|
|
17
|
+
export class ValidationError extends IpcError {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message, 'VALIDATION_ERROR', 400);
|
|
20
|
+
this.name = 'ValidationError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Thrown when a requested method or resource is not found.
|
|
25
|
+
*/
|
|
26
|
+
export class NotFoundError extends IpcError {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message, 'NOT_FOUND', 404);
|
|
29
|
+
this.name = 'NotFoundError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Thrown when an IPC operation times out.
|
|
34
|
+
*/
|
|
35
|
+
export class TimeoutError extends IpcError {
|
|
36
|
+
constructor(message = 'Operation timed out') {
|
|
37
|
+
super(message, 'TIMEOUT', 408);
|
|
38
|
+
this.name = 'TimeoutError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Thrown when a required service is not available.
|
|
43
|
+
*/
|
|
44
|
+
export class ServiceUnavailableError extends IpcError {
|
|
45
|
+
constructor(message = 'Service unavailable') {
|
|
46
|
+
super(message, 'SERVICE_UNAVAILABLE', 503);
|
|
47
|
+
this.name = 'ServiceUnavailableError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/ipc/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAS;IACb,UAAU,CAAS;IAE5B,YAAY,OAAe,EAAE,IAAY,EAAE,aAAqB,GAAG;QACjE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,QAAQ;IACxC,YAAY,UAAkB,qBAAqB;QACjD,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,QAAQ;IACnD,YAAY,UAAkB,qBAAqB;QACjD,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ValidationOptions {
|
|
2
|
+
maxStringLength?: number;
|
|
3
|
+
maxArrayLength?: number;
|
|
4
|
+
maxDepth?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Validate IPC method params. Ensures params is a plain object,
|
|
8
|
+
* string fields don't exceed length limits, arrays aren't too large,
|
|
9
|
+
* and nesting isn't too deep. Throws ValidationError on failure.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateParams(params: unknown, options?: ValidationOptions): Record<string, unknown>;
|
|
12
|
+
/**
|
|
13
|
+
* Create a validated IPC handler wrapper. Validates params before passing to the handler.
|
|
14
|
+
*/
|
|
15
|
+
export declare function withValidation<T>(handler: (params: Record<string, unknown>) => T, options?: ValidationOptions): (params: unknown) => T;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ValidationError } from './errors.js';
|
|
2
|
+
const MAX_STRING_LENGTH = 10_240; // 10KB per string field
|
|
3
|
+
const MAX_ARRAY_LENGTH = 1000;
|
|
4
|
+
const MAX_DEPTH = 10;
|
|
5
|
+
/**
|
|
6
|
+
* Validate IPC method params. Ensures params is a plain object,
|
|
7
|
+
* string fields don't exceed length limits, arrays aren't too large,
|
|
8
|
+
* and nesting isn't too deep. Throws ValidationError on failure.
|
|
9
|
+
*/
|
|
10
|
+
export function validateParams(params, options) {
|
|
11
|
+
const maxStr = options?.maxStringLength ?? MAX_STRING_LENGTH;
|
|
12
|
+
const maxArr = options?.maxArrayLength ?? MAX_ARRAY_LENGTH;
|
|
13
|
+
const maxDep = options?.maxDepth ?? MAX_DEPTH;
|
|
14
|
+
// Null/undefined → empty object (many methods accept no params)
|
|
15
|
+
if (params == null)
|
|
16
|
+
return {};
|
|
17
|
+
// Must be a plain object
|
|
18
|
+
if (typeof params !== 'object' || Array.isArray(params)) {
|
|
19
|
+
throw new ValidationError('Params must be a plain object');
|
|
20
|
+
}
|
|
21
|
+
// Deep validate
|
|
22
|
+
validateValue(params, 'params', maxStr, maxArr, maxDep, 0);
|
|
23
|
+
return params;
|
|
24
|
+
}
|
|
25
|
+
function validateValue(value, path, maxStr, maxArr, maxDep, depth) {
|
|
26
|
+
if (depth > maxDep) {
|
|
27
|
+
throw new ValidationError(`Maximum nesting depth exceeded at ${path}`);
|
|
28
|
+
}
|
|
29
|
+
if (typeof value === 'string') {
|
|
30
|
+
if (value.length > maxStr) {
|
|
31
|
+
throw new ValidationError(`String field "${path}" exceeds maximum length of ${maxStr}`);
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
if (value.length > maxArr) {
|
|
37
|
+
throw new ValidationError(`Array field "${path}" exceeds maximum length of ${maxArr}`);
|
|
38
|
+
}
|
|
39
|
+
for (let i = 0; i < value.length; i++) {
|
|
40
|
+
validateValue(value[i], `${path}[${i}]`, maxStr, maxArr, maxDep, depth + 1);
|
|
41
|
+
}
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (typeof value === 'object' && value !== null) {
|
|
45
|
+
const entries = Object.entries(value);
|
|
46
|
+
for (const [key, val] of entries) {
|
|
47
|
+
validateValue(val, `${path}.${key}`, maxStr, maxArr, maxDep, depth + 1);
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Primitives (number, boolean, null) are fine
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create a validated IPC handler wrapper. Validates params before passing to the handler.
|
|
55
|
+
*/
|
|
56
|
+
export function withValidation(handler, options) {
|
|
57
|
+
return (params) => {
|
|
58
|
+
const validated = validateParams(params, options);
|
|
59
|
+
return handler(validated);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/ipc/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmeck/brain-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Shared core infrastructure for the Brain ecosystem — IPC, MCP, CLI, DB connection, and utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
"./mcp/http-server": "./dist/mcp/http-server.js",
|
|
21
21
|
"./cli/colors": "./dist/cli/colors.js",
|
|
22
22
|
"./api/server": "./dist/api/server.js",
|
|
23
|
+
"./api/middleware": "./dist/api/middleware.js",
|
|
24
|
+
"./ipc/validation": "./dist/ipc/validation.js",
|
|
25
|
+
"./ipc/errors": "./dist/ipc/errors.js",
|
|
23
26
|
"./math/wilson-score": "./dist/math/wilson-score.js",
|
|
24
27
|
"./math/time-decay": "./dist/math/time-decay.js",
|
|
25
28
|
"./config/loader": "./dist/config/loader.js",
|