Skip to content

Commit 3071d76

Browse files
authored
Fix documentation (#30)
1 parent 35b2450 commit 3071d76

9 files changed

Lines changed: 212 additions & 177 deletions

File tree

CONTRIBUTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ src/
7171
tools/ # McpTool implementations (one file per tool)
7272
output/ # Terminal insight listener
7373
runtime/ # In-process architecture (interceptor, capture, health)
74-
store/ # In-memory bounded stores, persistent finding store
74+
store/ # In-memory bounded stores, persistent issue store
7575
telemetry/ # Anonymous usage analytics
7676
types/ # TypeScript type definitions
7777
utils/ # Shared utilities (collections, format, math, endpoint)
@@ -243,6 +243,7 @@ interface SecurityRule {
243243
interface SecurityContext {
244244
requests: readonly TracedRequest[]; // all captured HTTP requests
245245
logs: readonly TracedLog[]; // all captured console output
246+
parsedBodies: ParsedBodyCache; // pre-parsed JSON bodies (avoids re-parsing per rule)
246247
}
247248
```
248249

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<p align="center">
4242
<img width="700" src="docs/images/vscode.png" alt="Claude reading Brakit findings in VS Code" />
4343
<br />
44-
<sub>Claude reads findings via MCP and fixes your code</sub>
44+
<sub>Claude reads issues via MCP and fixes your code</sub>
4545
</p>
4646

4747
## Quick Start
@@ -56,7 +56,7 @@ That's it. Brakit detects your framework, adds itself as a devDependency, and cr
5656
npm run dev
5757
```
5858

59-
Dashboard at `http://localhost:<port>/__brakit`. Insights in the terminal.
59+
Dashboard at `http://localhost:<port>/__brakit`. Issues in the terminal.
6060

6161
> **Requirements:** Node.js >= 18 and a project with `package.json`.
6262
@@ -74,7 +74,7 @@ Dashboard at `http://localhost:<port>/__brakit`. Insights in the terminal.
7474
- **Full server tracing** — fetch calls, DB queries, console logs, errors — zero code changes
7575
- **Response overfetch** — large JSON responses with many fields your client doesn't use
7676
- **Performance tracking** — health grades and p95 trends across dev sessions
77-
- **AI-native via MCP** — Claude Code and Cursor can query findings, inspect endpoints, and verify fixes directly
77+
- **AI-native via MCP** — Claude Code and Cursor can query issues, inspect endpoints, and verify fixes directly
7878

7979
---
8080

docs/design/analysis-engine.md

Lines changed: 90 additions & 80 deletions
Large diffs are not rendered by default.

docs/design/architecture.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ required. Each store holds up to 1,000 entries and evicts the oldest when full.
240240
| LogStore | Console output |
241241
| ErrorStore | Uncaught exceptions and unhandled rejections |
242242
| MetricsStore | Per-endpoint session statistics, persisted to `.brakit/metrics.json` |
243-
| FindingStore | Stateful security findings with lifecycle tracking, persisted to `.brakit/findings.json` |
243+
| IssueStore | Stateful issue tracking with lifecycle (open/fixing/resolved/stale/regressed), persisted to `.brakit/issues.json` |
244244

245245
Stores are registered in a typed ServiceRegistry and accessed through it —
246246
no module-level singletons. The EventBus delivers new entries to all
@@ -349,8 +349,8 @@ traceable.
349349
**Why bounded in-memory stores, not a database?** Brakit is a zero-config dev
350350
tool. Requiring a database (even SQLite) adds setup friction. Bounded arrays
351351
with oldest-eviction give predictable memory usage without configuration. The
352-
MetricsStore and FindingStore persist to JSON files for cross-session features
353-
(regression detection, finding lifecycle) everything else is ephemeral.
352+
MetricsStore and IssueStore persist to JSON files for cross-session features
353+
(regression detection, issue lifecycle): everything else is ephemeral.
354354

355355
**Why debounced analysis, not real-time?** A single request can generate 20+
356356
telemetry events (queries, fetches, logs). Recomputing insights on every event

docs/design/dashboard.md

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Dashboard
22

3-
Brakit serves a live dashboard at `/__brakit` that shows requests, queries, errors, performance insights, and security findings in real time. This document covers how it's built.
3+
Brakit serves a live dashboard at `/__brakit` that shows requests, queries, errors, performance issues, and security issues in real time. This document covers how it's built.
44

55
## Table of contents
66

@@ -39,12 +39,12 @@ Brakit serves a live dashboard at `/__brakit` that shows requests, queries, erro
3939
│ │ SSE handler ──▶ EventBus ──▶ Subscribe to channels │ │
4040
│ └─────────────────────────────────────────────────────────┘ │
4141
│ │
42-
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────┐ │
43-
│ │ EventBus │ │ Stores │ │ Analysis │ │ MCP Server │ │
44-
│ │ (channels│ │ (7 total)│ │ Engine │ │ (separate │ │
45-
│ │ + subs) │ │ │ │ │ │ process, │ │
46-
│ └──────────┘ └──────────┘ └────────────┘ │ same API) │ │
47-
└──────────────┘ │
42+
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────┐
43+
│ │ EventBus │ │ Stores │ │ Analysis │ │ MCP Server │
44+
│ │ (channels│ │ (8 total)│ │ Engine │ │ (separate │
45+
│ │ + subs) │ │ │ │ │ │ process, │
46+
│ └──────────┘ └──────────┘ └────────────┘ │ same API) │
47+
│ └──────────────┘
4848
└──────────────────────────────────────────────────────────────────┘
4949
│ SSE stream │ REST API
5050
▼ ▼
@@ -65,24 +65,26 @@ Real-time updates use Server-Sent Events. When brakit captures a new request or
6565

6666
`src/dashboard/router.ts` creates a route table mapping URL paths to handler functions:
6767

68-
| Path | Handler | Purpose |
69-
|------|---------|---------|
70-
| `/__brakit` | HTML page | Serves the dashboard |
71-
| `/__brakit/api/requests` | `createRequestsHandler` | List captured requests |
72-
| `/__brakit/api/flows` | `createFlowsHandler` | List request flows (user actions) |
73-
| `/__brakit/api/events` | `createSSEHandler` | SSE stream for real-time updates |
74-
| `/__brakit/api/logs` | `createLogsHandler` | List captured console logs |
75-
| `/__brakit/api/fetches` | `createFetchesHandler` | List outgoing fetch calls |
76-
| `/__brakit/api/errors` | `createErrorsHandler` | List captured errors |
77-
| `/__brakit/api/queries` | `createQueriesHandler` | List database queries |
78-
| `/__brakit/api/metrics` | `createMetricsHandler` | Per-endpoint session metrics |
79-
| `/__brakit/api/metrics/live` | `createLiveMetricsHandler` | Current session live metrics |
80-
| `/__brakit/api/activity` | `createActivityHandler` | Timeline of events for a request |
81-
| `/__brakit/api/insights` | `createInsightsHandler` | Performance insights |
82-
| `/__brakit/api/security` | `createSecurityHandler` | Security findings |
83-
| `/__brakit/api/findings` | `createFindingsHandler` | Stateful findings with lifecycle |
84-
| `/__brakit/api/ingest` | `createIngestHandler` | External SDK event ingestion |
85-
| `/__brakit/api/clear` | `createClearHandler` | Clear all stores |
68+
| Path | Handler | Purpose |
69+
| ------------------------------- | ----------------------------- | ------------------------------------------------ |
70+
| `/__brakit` | HTML page | Serves the dashboard |
71+
| `/__brakit/api/requests` | `createRequestsHandler` | List captured requests |
72+
| `/__brakit/api/flows` | `createFlowsHandler` | List request flows (user actions) |
73+
| `/__brakit/api/events` | `createSSEHandler` | SSE stream for real-time updates |
74+
| `/__brakit/api/logs` | `createLogsHandler` | List captured console logs |
75+
| `/__brakit/api/fetches` | `createFetchesHandler` | List outgoing fetch calls |
76+
| `/__brakit/api/errors` | `createErrorsHandler` | List captured errors |
77+
| `/__brakit/api/queries` | `createQueriesHandler` | List database queries |
78+
| `/__brakit/api/metrics` | `createMetricsHandler` | Per-endpoint session metrics |
79+
| `/__brakit/api/metrics/live` | `createLiveMetricsHandler` | Current session live metrics |
80+
| `/__brakit/api/activity` | `createActivityHandler` | Timeline of events for a request |
81+
| `/__brakit/api/insights` | `createInsightsHandler` | Performance and reliability issues |
82+
| `/__brakit/api/security` | `createSecurityHandler` | Security issues |
83+
| `/__brakit/api/findings` | `createFindingsHandler` | All stateful issues with lifecycle (used by MCP) |
84+
| `/__brakit/api/findings/report` | `createFindingsReportHandler` | Record AI fix result (POST) |
85+
| `/__brakit/api/tab` | `createTabHandler` | Track active dashboard tab |
86+
| `/__brakit/api/ingest` | `createIngestHandler` | External SDK event ingestion |
87+
| `/__brakit/api/clear` | `createClearHandler` | Clear all stores |
8688

8789
Every handler is a factory function that receives the `ServiceRegistry`. No global imports, no singletons.
8890

@@ -113,16 +115,16 @@ Response shapes are defined in `src/types/api-contracts.ts` and shared between t
113115
4. Send heartbeat comments every 30 seconds to keep the connection alive
114116
5. On disconnect, call `subs.dispose()` to clean up all subscriptions
115117

116-
| Bus channel | SSE event type | What it carries |
117-
|-------------|---------------|-----------------|
118-
| `request:completed` | (default) | Completed request record |
119-
| `telemetry:fetch` | `fetch` | Outgoing fetch call |
120-
| `telemetry:log` | `log` | Console log entry |
121-
| `telemetry:error` | `error_event` | Uncaught error |
122-
| `telemetry:query` | `query` | Database query |
123-
| `analysis:updated` | `insights` + `security` | Computed insights and findings |
118+
| Bus channel | SSE event type | What it carries |
119+
| ------------------- | ---------------------------------- | ---------------------------------------------------- |
120+
| `request:completed` | (default) | Completed request record |
121+
| `telemetry:fetch` | `fetch` | Outgoing fetch call |
122+
| `telemetry:log` | `log` | Console log entry |
123+
| `telemetry:error` | `error_event` | Uncaught error |
124+
| `telemetry:query` | `query` | Database query |
125+
| `analysis:updated` | `issues` + `insights` + `security` | Computed issues, raw insights, and security findings |
124126

125-
The `analysis:updated` channel emits two SSE events — one for insights, one for security findings — so the client can update each section independently.
127+
The `analysis:updated` channel emits three SSE events: `issues` (the unified StatefulIssue list with lifecycle state), `insights` (raw Insight objects from performance rules), and `security` (raw SecurityFinding objects). The client can update each section independently.
126128

127129
---
128130

@@ -149,6 +151,7 @@ The dashboard enforces several security measures:
149151
**Localhost-only access.** The interceptor only serves dashboard routes to localhost connections. Non-local IPs get a 404.
150152

151153
**Content Security Policy.** Every response includes a strict CSP header:
154+
152155
```
153156
default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; img-src data:
154157
```

docs/design/event-bus.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,15 @@ interface ChannelMap {
5252
"telemetry:error": Omit<TracedError, "id">;
5353
"request:completed": TracedRequest;
5454
"analysis:updated": AnalysisUpdate;
55-
"store:cleared": void;
55+
"issues:changed": readonly StatefulIssue[];
56+
"store:cleared": undefined;
57+
}
58+
59+
// AnalysisUpdate carries the full computed state after each recompute cycle:
60+
interface AnalysisUpdate {
61+
insights: readonly Insight[];
62+
findings: readonly SecurityFinding[];
63+
issues: readonly StatefulIssue[];
5664
}
5765
```
5866

@@ -69,6 +77,7 @@ Channels follow a `domain:event` convention:
6977
| `telemetry:*` | Raw telemetry from hooks and SDKs | `telemetry:fetch`, `telemetry:query` |
7078
| `request:*` | HTTP request lifecycle | `request:completed` |
7179
| `analysis:*` | Computed insights and findings | `analysis:updated` |
80+
| `issues:*` | Issue lifecycle state changes | `issues:changed` |
7281
| `store:*` | Store-level operations | `store:cleared` |
7382

7483
Prefer this convention when adding new channels. It keeps the bus scannable and groups related events.
@@ -143,10 +152,9 @@ The analysis engine emits computed results after recompute:
143152

144153
```typescript
145154
bus.emit("analysis:updated", {
146-
insights,
147-
findings,
148-
statefulFindings,
149-
statefulInsights,
155+
insights, // Insight[] from performance rules
156+
findings, // SecurityFinding[] from security rules
157+
issues, // StatefulIssue[] with full lifecycle state
150158
});
151159
```
152160

@@ -171,8 +179,9 @@ subs.add(
171179
);
172180
subs.add(
173181
bus.on("analysis:updated", (u) => {
174-
writeEvent("insights", JSON.stringify(u.statefulInsights));
175-
writeEvent("security", JSON.stringify(u.statefulFindings));
182+
writeEvent("issues", JSON.stringify(u.issues));
183+
writeEvent("insights", JSON.stringify(u.insights));
184+
writeEvent("security", JSON.stringify(u.findings));
176185
}),
177186
);
178187

@@ -202,7 +211,7 @@ subs.add(bus.on("telemetry:log", handler2));
202211
subs.dispose();
203212
```
204213

205-
`bus.on()` returns a dispose function. `SubscriptionBag.add()` accepts it. This is the only way to manage subscriptions — never call `bus.off()` directly.
214+
`bus.on()` returns a dispose function. `SubscriptionBag.add()` accepts it. `bus.off(channel, fn)` also exists as a direct unsubscribe, but prefer `SubscriptionBag` for any code that manages multiple subscriptions — it avoids the error-prone manual pairing of every `on` with an `off`.
206215

207216
Used by:
208217

0 commit comments

Comments
 (0)