brakit 0.7.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -52
- package/dist/api.d.ts +47 -2
- package/dist/api.js +275 -94
- package/dist/bin/brakit.js +1143 -48
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +737 -0
- package/dist/runtime/index.js +302 -66
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Every request, query, and security issue — before you ship.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
<h1 align="center"><img src="docs/images/icon.png" height="24" alt="" /> Brakit</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<b>See what your app is actually doing.</b> <br />
|
|
5
|
+
Every request, query, and security issue — before you ship. <br />
|
|
6
|
+
<b>Open source · Local first · Zero config · 2 dependencies</b>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<h3 align="center">
|
|
10
|
+
<a href="docs/design/architecture.md">Architecture</a> •
|
|
11
|
+
<a href="https://brakit.ai">Website</a> •
|
|
12
|
+
<a href="CONTRIBUTING.md">Contributing</a>
|
|
13
|
+
</h3>
|
|
14
|
+
|
|
15
|
+
<h4 align="center">
|
|
16
|
+
<a href="LICENSE">
|
|
17
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" />
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://nodejs.org">
|
|
20
|
+
<img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg" alt="Node >= 18" />
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://typescriptlang.org">
|
|
23
|
+
<img src="https://img.shields.io/badge/built%20with-TypeScript-3178c6.svg" alt="TypeScript" />
|
|
24
|
+
</a>
|
|
25
|
+
<a href="CONTRIBUTING.md">
|
|
26
|
+
<img src="https://img.shields.io/badge/PRs-Welcome-brightgreen" alt="PRs welcome!" />
|
|
27
|
+
</a>
|
|
28
|
+
</h4>
|
|
12
29
|
|
|
13
30
|
---
|
|
14
31
|
|
|
32
|
+
<p align="center">
|
|
33
|
+
<img width="700" src="docs/images/dashboard.png" alt="Brakit Dashboard" />
|
|
34
|
+
</p>
|
|
35
|
+
|
|
15
36
|
## Quick Start
|
|
16
37
|
|
|
17
38
|
```bash
|
|
@@ -28,19 +49,21 @@ Dashboard at `http://localhost:<port>/__brakit`. Insights in the terminal.
|
|
|
28
49
|
|
|
29
50
|
> **Requirements:** Node.js >= 18 and a project with `package.json`.
|
|
30
51
|
|
|
31
|
-
[Documentation](https://brakit.ai/docs) · [Website](https://brakit.ai)
|
|
32
|
-
|
|
33
52
|
---
|
|
34
53
|
|
|
35
54
|
## What You Get
|
|
36
55
|
|
|
37
|
-
- **
|
|
56
|
+
- **Live dashboard** at `/__brakit` — performance overview, request history, scatter charts, real-time via SSE
|
|
57
|
+
- **8 security rules** scanned against live traffic — leaked secrets, PII in responses, missing auth flags
|
|
58
|
+
- **Time breakdown** — every endpoint shows where time goes: DB, Fetch, or App code
|
|
59
|
+
- **N+1 query detection** — same query pattern repeated 5+ times in a single request
|
|
60
|
+
- **Regression detection** — p95 latency or query count increased vs. previous session
|
|
38
61
|
- **Action-level visibility** — see "Sign Up" and "Load Dashboard", not 47 raw HTTP requests
|
|
39
62
|
- **Duplicate detection** — same API called twice? Flagged with redundancy percentage
|
|
40
|
-
- **N+1 query detection** — same query pattern repeated 5+ times in a single request? That's an N+1
|
|
41
63
|
- **Full server tracing** — fetch calls, DB queries, console logs, errors — zero code changes
|
|
42
|
-
- **
|
|
64
|
+
- **Response overfetch** — large JSON responses with many fields your client doesn't use
|
|
43
65
|
- **Performance tracking** — health grades and p95 trends across dev sessions
|
|
66
|
+
- **AI-native via MCP** — Claude, Cursor, and other AI tools can query findings, inspect endpoints, and verify fixes directly
|
|
44
67
|
|
|
45
68
|
---
|
|
46
69
|
|
|
@@ -56,22 +79,24 @@ Brakit watches every action your app takes — not raw HTTP noise, but what actu
|
|
|
56
79
|
|
|
57
80
|
8 high-confidence rules that scan your live traffic and flag real issues — not theoretical ones:
|
|
58
81
|
|
|
59
|
-
| | Rule
|
|
60
|
-
| ------------ |
|
|
61
|
-
| **Critical** | Exposed Secret
|
|
62
|
-
| **Critical** | Token in URL
|
|
63
|
-
| **Critical** | Stack Trace Leak
|
|
64
|
-
| **Critical** | Error Info Leak
|
|
65
|
-
| Warning | PII in Response
|
|
66
|
-
| Warning | Insecure Cookie
|
|
67
|
-
| Warning | Sensitive Logs
|
|
68
|
-
| Warning | CORS + Credentials | `credentials: true` with wildcard origin
|
|
82
|
+
| | Rule | What it catches |
|
|
83
|
+
| ------------ | ------------------ | -------------------------------------------------------------------------------- |
|
|
84
|
+
| **Critical** | Exposed Secret | Response contains `password`, `api_key`, `client_secret` fields with real values |
|
|
85
|
+
| **Critical** | Token in URL | Auth tokens in query parameters instead of headers |
|
|
86
|
+
| **Critical** | Stack Trace Leak | Internal stack traces sent to the client |
|
|
87
|
+
| **Critical** | Error Info Leak | DB connection strings, SQL queries, or secret values in error responses |
|
|
88
|
+
| Warning | PII in Response | API echoes back emails, returns full user records with internal IDs |
|
|
89
|
+
| Warning | Insecure Cookie | Missing `HttpOnly` or `SameSite` flags |
|
|
90
|
+
| Warning | Sensitive Logs | Passwords, secrets, or token values in console output |
|
|
91
|
+
| Warning | CORS + Credentials | `credentials: true` with wildcard origin |
|
|
69
92
|
|
|
70
93
|
---
|
|
71
94
|
|
|
72
95
|
## Who Is This For
|
|
73
96
|
|
|
74
|
-
|
|
97
|
+
- **AI-assisted developers** — Using Cursor, Copilot, or Claude Code to generate API code you don't fully review? Brakit catches the issues they introduce.
|
|
98
|
+
- **Console.log debuggers** — Wish you could just see every action your API executes without adding log statements everywhere? That's literally what brakit does.
|
|
99
|
+
- **Anyone shipping Node.js APIs** — If you want to catch security and performance issues before they reach production, brakit surfaces them as you develop.
|
|
75
100
|
|
|
76
101
|
---
|
|
77
102
|
|
|
@@ -83,6 +108,7 @@ import 'brakit' → hooks into http.Server → captures everything
|
|
|
83
108
|
+-- Dashboard UI (/__brakit)
|
|
84
109
|
+-- Live SSE stream (real-time updates)
|
|
85
110
|
+-- Terminal output (insights as you develop)
|
|
111
|
+
+-- MCP server (AI assistant integration)
|
|
86
112
|
```
|
|
87
113
|
|
|
88
114
|
`import 'brakit'` runs inside your process. It patches `http.Server.prototype.emit` to intercept all requests — capturing request/response pairs, grouping them into actions, and streaming everything to the dashboard at `/__brakit` on your existing port. No proxy, no second process, no different port.
|
|
@@ -93,27 +119,27 @@ Instrumentation hooks capture fetch calls, DB queries, console output, and error
|
|
|
93
119
|
|
|
94
120
|
Brakit never runs in production. 7 independent layers ensure it:
|
|
95
121
|
|
|
96
|
-
| #
|
|
97
|
-
|
|
98
|
-
| 1
|
|
99
|
-
| 2
|
|
100
|
-
| 3
|
|
101
|
-
| 4
|
|
102
|
-
| 5
|
|
103
|
-
| 6
|
|
104
|
-
| 7
|
|
122
|
+
| # | Layer | How it blocks |
|
|
123
|
+
| --- | ---------------------------- | ----------------------------------------- |
|
|
124
|
+
| 1 | `shouldActivate()` | Checks `NODE_ENV` + 15 cloud/CI env vars |
|
|
125
|
+
| 2 | `instrumentation.ts` guard | Its own `NODE_ENV !== 'production'` check |
|
|
126
|
+
| 3 | devDependency | Pruned in production builds |
|
|
127
|
+
| 4 | `try/catch` on import | Missing module = silent no-op |
|
|
128
|
+
| 5 | Localhost-only dashboard | Non-local IPs get 404 on `/__brakit` |
|
|
129
|
+
| 6 | `safeWrap` + circuit breaker | 10 errors = brakit self-disables |
|
|
130
|
+
| 7 | `BRAKIT_DISABLE=true` | Manual kill switch |
|
|
105
131
|
|
|
106
132
|
### Supported Frameworks
|
|
107
133
|
|
|
108
|
-
| Framework
|
|
109
|
-
|
|
|
110
|
-
| Next.js
|
|
111
|
-
| Remix
|
|
112
|
-
| Nuxt
|
|
113
|
-
| Vite
|
|
114
|
-
| Astro
|
|
115
|
-
| Express
|
|
116
|
-
| Fastify
|
|
134
|
+
| Framework | Status |
|
|
135
|
+
| --------- | -------------------------- |
|
|
136
|
+
| Next.js | Full support (auto-detect) |
|
|
137
|
+
| Remix | Auto-detect |
|
|
138
|
+
| Nuxt | Auto-detect |
|
|
139
|
+
| Vite | Auto-detect |
|
|
140
|
+
| Astro | Auto-detect |
|
|
141
|
+
| Express | Auto-detect |
|
|
142
|
+
| Fastify | Auto-detect |
|
|
117
143
|
|
|
118
144
|
### Supported Databases
|
|
119
145
|
|
|
@@ -134,7 +160,7 @@ Brakit never runs in production. 7 independent layers ensure it:
|
|
|
134
160
|
npx brakit uninstall
|
|
135
161
|
```
|
|
136
162
|
|
|
137
|
-
Removes the instrumentation file and devDependency. Your app is unchanged.
|
|
163
|
+
Removes the instrumentation file, MCP configuration, `.brakit` data directory, `.gitignore` entry, and devDependency. Your app is unchanged.
|
|
138
164
|
|
|
139
165
|
---
|
|
140
166
|
|
|
@@ -157,35 +183,44 @@ Only 2 production dependencies: `citty` (CLI) and `picocolors` (terminal colors)
|
|
|
157
183
|
|
|
158
184
|
```
|
|
159
185
|
src/
|
|
160
|
-
runtime/ In-process entry point,
|
|
161
|
-
analysis/
|
|
186
|
+
runtime/ In-process entry point, interceptor, capture, safety
|
|
187
|
+
analysis/ Insights engine and security scanner
|
|
188
|
+
insights/ InsightRule implementations (one file per rule)
|
|
162
189
|
rules/ SecurityRule implementations (one file per rule)
|
|
163
190
|
cli/ CLI commands (install, uninstall)
|
|
191
|
+
constants/ Shared thresholds, route paths, limits
|
|
164
192
|
dashboard/
|
|
165
193
|
api/ REST handlers — requests, flows, telemetry, metrics
|
|
166
194
|
client/ Browser JS generated as template strings
|
|
167
195
|
views/ Tab renderers (overview, flows, graph, etc.)
|
|
168
196
|
styles/ CSS modules
|
|
169
197
|
detect/ Framework auto-detection
|
|
170
|
-
instrument/
|
|
198
|
+
instrument/ Database adapters and instrumentation hooks
|
|
171
199
|
adapters/ BrakitAdapter implementations (one file per library)
|
|
172
200
|
hooks/ Core hooks (fetch, console, errors, context)
|
|
201
|
+
mcp/ MCP server for AI tool integration (Claude, Cursor)
|
|
202
|
+
tools/ Tool implementations (one file per tool)
|
|
203
|
+
output/ Terminal insight listener
|
|
173
204
|
store/ In-memory telemetry stores + persistent metrics
|
|
174
205
|
types/ TypeScript definitions by domain
|
|
206
|
+
utils/ Shared utilities (collections, format, math, endpoint)
|
|
175
207
|
```
|
|
176
208
|
|
|
177
209
|
---
|
|
178
210
|
|
|
179
211
|
## Contributing
|
|
180
212
|
|
|
181
|
-
Brakit is early and moving fast. The most common contributions — adding a
|
|
182
|
-
database adapter
|
|
183
|
-
interface. See [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
213
|
+
Brakit is early and moving fast. The most common contributions — adding a
|
|
214
|
+
database adapter, a security rule, or an insight rule — each require exactly
|
|
215
|
+
one file and one interface. See [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
216
|
+
step-by-step guides.
|
|
184
217
|
|
|
185
218
|
Some areas where help would be great:
|
|
186
219
|
|
|
187
220
|
- **Database adapters** — Drizzle, Mongoose, SQLite, MongoDB
|
|
221
|
+
- **Insight rules** — New performance patterns, custom thresholds
|
|
188
222
|
- **Security rules** — More patterns, configurable severity
|
|
223
|
+
- **MCP tools** — New AI-facing tools for the MCP server
|
|
189
224
|
- **Dashboard** — Request diff, timeline view, HAR export
|
|
190
225
|
|
|
191
226
|
Please open an issue first for larger changes so we can discuss the approach.
|
package/dist/api.d.ts
CHANGED
|
@@ -160,6 +160,50 @@ interface SecurityFinding {
|
|
|
160
160
|
count: number;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
type FindingState = "open" | "fixing" | "resolved";
|
|
164
|
+
type FindingSource = "passive";
|
|
165
|
+
interface StatefulFinding {
|
|
166
|
+
/** Stable ID derived from rule + endpoint + description hash */
|
|
167
|
+
findingId: string;
|
|
168
|
+
state: FindingState;
|
|
169
|
+
source: FindingSource;
|
|
170
|
+
finding: SecurityFinding;
|
|
171
|
+
firstSeenAt: number;
|
|
172
|
+
lastSeenAt: number;
|
|
173
|
+
resolvedAt: number | null;
|
|
174
|
+
occurrences: number;
|
|
175
|
+
}
|
|
176
|
+
interface FindingsData {
|
|
177
|
+
version: 1;
|
|
178
|
+
findings: StatefulFinding[];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
declare class FindingStore {
|
|
182
|
+
private rootDir;
|
|
183
|
+
private findings;
|
|
184
|
+
private flushTimer;
|
|
185
|
+
private dirty;
|
|
186
|
+
private writing;
|
|
187
|
+
private readonly findingsPath;
|
|
188
|
+
private readonly tmpPath;
|
|
189
|
+
private readonly metricsDir;
|
|
190
|
+
constructor(rootDir: string);
|
|
191
|
+
start(): void;
|
|
192
|
+
stop(): void;
|
|
193
|
+
upsert(finding: SecurityFinding, source: FindingSource): StatefulFinding;
|
|
194
|
+
transition(findingId: string, state: FindingState): boolean;
|
|
195
|
+
reconcilePassive(currentFindings: readonly SecurityFinding[]): void;
|
|
196
|
+
getAll(): readonly StatefulFinding[];
|
|
197
|
+
getByState(state: FindingState): readonly StatefulFinding[];
|
|
198
|
+
get(findingId: string): StatefulFinding | undefined;
|
|
199
|
+
clear(): void;
|
|
200
|
+
private load;
|
|
201
|
+
private flush;
|
|
202
|
+
private flushSync;
|
|
203
|
+
private writeAsync;
|
|
204
|
+
private ensureDir;
|
|
205
|
+
}
|
|
206
|
+
|
|
163
207
|
interface BrakitAdapter {
|
|
164
208
|
name: string;
|
|
165
209
|
detect(): boolean;
|
|
@@ -285,6 +329,7 @@ declare class MetricsStore {
|
|
|
285
329
|
type AnalysisListener = (insights: Insight[], findings: SecurityFinding[]) => void;
|
|
286
330
|
declare class AnalysisEngine {
|
|
287
331
|
private metricsStore;
|
|
332
|
+
private findingStore?;
|
|
288
333
|
private debounceMs;
|
|
289
334
|
private scanner;
|
|
290
335
|
private cachedInsights;
|
|
@@ -295,7 +340,7 @@ declare class AnalysisEngine {
|
|
|
295
340
|
private boundQueryListener;
|
|
296
341
|
private boundErrorListener;
|
|
297
342
|
private boundLogListener;
|
|
298
|
-
constructor(metricsStore: MetricsStore, debounceMs?: number);
|
|
343
|
+
constructor(metricsStore: MetricsStore, findingStore?: FindingStore | undefined, debounceMs?: number);
|
|
299
344
|
start(): void;
|
|
300
345
|
stop(): void;
|
|
301
346
|
onUpdate(fn: AnalysisListener): void;
|
|
@@ -308,4 +353,4 @@ declare class AnalysisEngine {
|
|
|
308
353
|
|
|
309
354
|
declare const VERSION: string;
|
|
310
355
|
|
|
311
|
-
export { AdapterRegistry, AnalysisEngine, type BrakitAdapter, type BrakitConfig, type DetectedProject, type FlatHeaders, type Framework, type HttpMethod, type Insight, type InsightContext, type InsightRule, InsightRunner, type NormalizedOp, type RequestCategory, type RequestListener, type SecurityContext, type SecurityFinding, type SecurityRule, SecurityScanner, type SecuritySeverity, type TracedRequest, VERSION, computeInsights, createDefaultInsightRunner, createDefaultScanner, detectProject };
|
|
356
|
+
export { AdapterRegistry, AnalysisEngine, type BrakitAdapter, type BrakitConfig, type DetectedProject, type FindingSource, type FindingState, FindingStore, type FindingsData, type FlatHeaders, type Framework, type HttpMethod, type Insight, type InsightContext, type InsightRule, InsightRunner, type NormalizedOp, type RequestCategory, type RequestListener, type SecurityContext, type SecurityFinding, type SecurityRule, SecurityScanner, type SecuritySeverity, type StatefulFinding, type TracedRequest, VERSION, computeInsights, createDefaultInsightRunner, createDefaultScanner, detectProject };
|