infrawise 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.
- package/README.md +425 -0
- package/dist/index.js +3462 -0
- package/package.json +92 -0
package/README.md
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
# Infrawise
|
|
2
|
+
|
|
3
|
+
**Understand your infrastructure, not just your code.**
|
|
4
|
+
|
|
5
|
+
Infrawise is a CLI tool that scans your TypeScript codebase, maps every function-to-database relationship into a graph, detects anti-patterns (full table scans, missing indexes, hot partitions, N+1 queries), and exposes all of it as an MCP server — so AI coding assistants like Claude Code have live, deterministic knowledge of your infrastructure when helping you write database code.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why this exists
|
|
10
|
+
|
|
11
|
+
When AI coding assistants help you write database queries, they read your source files but have no knowledge of your actual infrastructure. They don't know your DynamoDB partition keys, which GSIs exist, or which functions are already doing expensive scans. They guess.
|
|
12
|
+
|
|
13
|
+
Infrawise fixes that. It runs a static analysis of your repo, builds an infrastructure graph, and starts a local MCP server. Claude Code can then call tools like `get_graph_summary`, `analyze_function`, and `suggest_gsi` in real time — giving it exact knowledge of your schema and access patterns before writing a single line of database code.
|
|
14
|
+
|
|
15
|
+
**Without Infrawise**, Claude might:
|
|
16
|
+
- Suggest a `.scan()` on your Orders table that has 50M rows
|
|
17
|
+
- Recommend adding a GSI on `status` that you already have
|
|
18
|
+
- Write a `SELECT *` when you need to keep query cost low
|
|
19
|
+
- Not notice that 5 functions are already hammering the same partition key
|
|
20
|
+
|
|
21
|
+
**With Infrawise**, Claude knows:
|
|
22
|
+
- Your exact table schemas, partition keys, sort keys, and GSIs
|
|
23
|
+
- Which functions query which tables and how
|
|
24
|
+
- Which patterns are already flagged as high severity in your codebase
|
|
25
|
+
- The exact `CREATE INDEX` SQL or GSI config for your specific tables — not generic advice
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g infrawise
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
or use without installing:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx infrawise init
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
**1. Initialize in your repo**
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd your-project
|
|
49
|
+
infrawise init
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Detects your AWS profile and region, asks a few questions, writes `infrawise.yaml`. That's the only file it creates in your project.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
✔ Detected repository: payments-service
|
|
56
|
+
✔ Repository type: typescript
|
|
57
|
+
✔ AWS profile: default
|
|
58
|
+
✔ Found DynamoDB tables: Orders, Users, Sessions
|
|
59
|
+
✔ Created infrawise.yaml
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**2. Validate everything is connected**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
infrawise doctor
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**3. Run analysis**
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
infrawise analyze
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Findings (3 total)
|
|
76
|
+
|
|
77
|
+
1. [HIGH] Full table scan detected on DynamoDB table "Orders"
|
|
78
|
+
listAllOrders() scans without any filter — reads every item in the table.
|
|
79
|
+
Recommendation: Replace Scan with Query using a partition key or add a GSI.
|
|
80
|
+
|
|
81
|
+
2. [MEDIUM] PostgreSQL table "users" has no index on column "email"
|
|
82
|
+
Filtering on "email" causes sequential scans.
|
|
83
|
+
Recommendation: CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
|
|
84
|
+
|
|
85
|
+
3. [MEDIUM] DynamoDB table "Sessions" accessed by 6 distinct code paths
|
|
86
|
+
High access concentration may create hot partition issues at scale.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Using with Claude Code
|
|
92
|
+
|
|
93
|
+
This is where Infrawise becomes most useful. Once wired up, Claude Code has live access to your infrastructure graph — it stops guessing and starts knowing.
|
|
94
|
+
|
|
95
|
+
### Step 1: Start the MCP server
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
infrawise dev
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
✔ Tool server running
|
|
103
|
+
✔ Context engine initialized
|
|
104
|
+
|
|
105
|
+
MCP endpoint: http://localhost:3000/mcp
|
|
106
|
+
Available tools: http://localhost:3000/mcp/tools
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Step 2: Add to Claude Code settings
|
|
110
|
+
|
|
111
|
+
Edit `.claude/settings.json` in your repo (project-level) or `~/.claude/settings.json` (global):
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"mcpServers": {
|
|
116
|
+
"infrawise": {
|
|
117
|
+
"url": "http://localhost:3000/mcp"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Restart Claude Code. The tools are now available in every conversation.
|
|
124
|
+
|
|
125
|
+
Alternatively, let Claude Code manage the server lifecycle automatically:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"mcpServers": {
|
|
130
|
+
"infrawise": {
|
|
131
|
+
"command": "infrawise",
|
|
132
|
+
"args": ["dev"]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Step 3: What Claude can now do
|
|
139
|
+
|
|
140
|
+
Claude gains four tools it calls silently while helping you:
|
|
141
|
+
|
|
142
|
+
| Tool | What it gives Claude |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `get_graph_summary` | Full infrastructure graph — tables, GSIs, function relationships, all findings |
|
|
145
|
+
| `analyze_function` | Issues introduced by a specific function — scans, missing indexes, N+1 |
|
|
146
|
+
| `suggest_gsi` | Exact GSI config for a DynamoDB table + attribute |
|
|
147
|
+
| `postgres_index_suggestions` | Exact `CREATE INDEX` SQL for your actual table |
|
|
148
|
+
| `suggest_mongo_index` | Exact `createIndex` command for a MongoDB collection + field |
|
|
149
|
+
| `mysql_index_suggestions` | Exact `ALTER TABLE ADD INDEX` SQL for your MySQL table |
|
|
150
|
+
|
|
151
|
+
### What changes in practice
|
|
152
|
+
|
|
153
|
+
**Before Infrawise:**
|
|
154
|
+
> You: "Write a function to get all orders by userId"
|
|
155
|
+
> Claude: *writes a DynamoDB `.scan()` filtered client-side — no schema context*
|
|
156
|
+
|
|
157
|
+
**After Infrawise:**
|
|
158
|
+
> You: "Write a function to get all orders by userId"
|
|
159
|
+
> Claude: *calls `get_graph_summary` → sees Orders has a `userId-index` GSI → writes a `.query()` against the GSI → notes `listAllOrders()` already does a full scan and flags it proactively*
|
|
160
|
+
|
|
161
|
+
### Using with other AI editors
|
|
162
|
+
|
|
163
|
+
Infrawise works with any editor or tool that supports MCP or can call an HTTP API:
|
|
164
|
+
|
|
165
|
+
- **Cursor** — add `http://localhost:3000/mcp` as an MCP server in Cursor settings
|
|
166
|
+
- **Windsurf** — same, via MCP server configuration
|
|
167
|
+
- **Any Claude API project** — call the endpoint directly from your own tooling
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## CLI reference
|
|
172
|
+
|
|
173
|
+
| Command | What it does |
|
|
174
|
+
|---|---|
|
|
175
|
+
| `infrawise init` | Detect AWS + repo, generate `infrawise.yaml` |
|
|
176
|
+
| `infrawise auth` | Select or switch AWS profile |
|
|
177
|
+
| `infrawise analyze` | Scan repo + AWS, build graph, print findings |
|
|
178
|
+
| `infrawise dev` | Start MCP server at `http://localhost:3000/mcp` |
|
|
179
|
+
| `infrawise doctor` | Validate AWS access, DB connectivity, and config |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Configuration
|
|
184
|
+
|
|
185
|
+
`infrawise.yaml` is generated by `infrawise init` and lives in your repo root:
|
|
186
|
+
|
|
187
|
+
```yaml
|
|
188
|
+
project: payments-service
|
|
189
|
+
|
|
190
|
+
aws:
|
|
191
|
+
profile: default # AWS profile from ~/.aws/credentials
|
|
192
|
+
region: ap-south-1
|
|
193
|
+
|
|
194
|
+
dynamodb:
|
|
195
|
+
includeTables: # omit to include all tables
|
|
196
|
+
- Orders
|
|
197
|
+
- Users
|
|
198
|
+
|
|
199
|
+
postgres:
|
|
200
|
+
enabled: true
|
|
201
|
+
connectionString: postgresql://infrawise_ro:password@host:5432/mydb
|
|
202
|
+
|
|
203
|
+
analysis:
|
|
204
|
+
sampleSize: 100
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### AWS setup
|
|
208
|
+
|
|
209
|
+
Infrawise is **read-only**. Minimum IAM policy required:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"Version": "2012-10-17",
|
|
214
|
+
"Statement": [
|
|
215
|
+
{
|
|
216
|
+
"Effect": "Allow",
|
|
217
|
+
"Action": [
|
|
218
|
+
"dynamodb:ListTables",
|
|
219
|
+
"dynamodb:DescribeTable"
|
|
220
|
+
],
|
|
221
|
+
"Resource": "*"
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
For SSO profiles, log in before running infrawise:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
aws sso login --profile myprofile
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### PostgreSQL setup (optional)
|
|
234
|
+
|
|
235
|
+
Create a read-only user for infrawise:
|
|
236
|
+
|
|
237
|
+
```sql
|
|
238
|
+
CREATE USER infrawise_ro WITH PASSWORD 'yourpassword';
|
|
239
|
+
GRANT CONNECT ON DATABASE yourdb TO infrawise_ro;
|
|
240
|
+
GRANT USAGE ON SCHEMA public TO infrawise_ro;
|
|
241
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO infrawise_ro;
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
For Amazon RDS: allow inbound on port 5432 from your machine's IP in the security group.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## What gets analyzed
|
|
249
|
+
|
|
250
|
+
### DynamoDB
|
|
251
|
+
|
|
252
|
+
| Analyzer | Severity | What it detects |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| Full Table Scan | High | `.scan()` calls without filters |
|
|
255
|
+
| Missing GSI | Medium | Tables queried without a matching GSI |
|
|
256
|
+
| Hot Partition | Medium | 5+ distinct code paths hitting the same table |
|
|
257
|
+
|
|
258
|
+
### PostgreSQL
|
|
259
|
+
|
|
260
|
+
| Analyzer | Severity | What it detects |
|
|
261
|
+
|---|---|---|
|
|
262
|
+
| Missing Index | Medium/High | Columns filtered without indexes |
|
|
263
|
+
| N+1 Query | Medium | Repeated query patterns from ORM inefficiencies |
|
|
264
|
+
| Large SELECT | Low | `SELECT *` usage |
|
|
265
|
+
|
|
266
|
+
### MySQL
|
|
267
|
+
|
|
268
|
+
| Analyzer | Severity | What it detects |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| Missing MySQL Index | Medium | Tables queried without indexes |
|
|
271
|
+
| MySQL Full Table Scan | High | Scan operations on MySQL tables |
|
|
272
|
+
|
|
273
|
+
### MongoDB
|
|
274
|
+
|
|
275
|
+
| Analyzer | Severity | What it detects |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| Missing Mongo Index | Medium | Collections queried without secondary indexes |
|
|
278
|
+
| Collection Scan | High | Full collection scan operations |
|
|
279
|
+
|
|
280
|
+
### Terraform / CloudFormation (IaC Drift)
|
|
281
|
+
|
|
282
|
+
| Analyzer | Severity | What it detects |
|
|
283
|
+
|---|---|---|
|
|
284
|
+
| IaC Drift | Medium | DynamoDB tables defined in IaC but not deployed in AWS |
|
|
285
|
+
| IaC Drift | Medium | DynamoDB tables deployed in AWS but not defined in IaC |
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Security
|
|
290
|
+
|
|
291
|
+
- **Read-only** — never writes to AWS or your database, never executes DDL
|
|
292
|
+
- **Local-first** — everything runs on your machine, nothing sent to external servers
|
|
293
|
+
- **No telemetry** — zero data collection
|
|
294
|
+
- **Credentials** — uses your existing AWS credential chain, never stored by infrawise
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Architecture
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
Your TypeScript repo
|
|
302
|
+
↓
|
|
303
|
+
┌───────────────────────────────────────────────────────┐
|
|
304
|
+
│ infrawise analyze │
|
|
305
|
+
│ │
|
|
306
|
+
│ Repository Scanner AWS DynamoDB PostgreSQL │
|
|
307
|
+
│ (ts-morph AST) ↓ ↓ │
|
|
308
|
+
│ ↓ └──────┬───────┘ │
|
|
309
|
+
│ └────────────────────► │ │
|
|
310
|
+
│ Graph Engine │
|
|
311
|
+
│ (nodes + edges) │
|
|
312
|
+
│ ↓ │
|
|
313
|
+
│ Analyzer Engine │
|
|
314
|
+
│ (rule-based, deterministic) │
|
|
315
|
+
└──────────────────────────────┬────────────────────────┘
|
|
316
|
+
↓
|
|
317
|
+
┌──────────────────┐
|
|
318
|
+
│ MCP Server │ ◄── Claude Code
|
|
319
|
+
│ localhost:3000 │ ◄── Cursor
|
|
320
|
+
└──────────────────┘ ◄── Windsurf
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The analysis is entirely deterministic — no LLM is involved in extracting or analyzing your infrastructure. AI is only at the consumption layer.
|
|
324
|
+
|
|
325
|
+
### Package structure
|
|
326
|
+
|
|
327
|
+
| Package | Description |
|
|
328
|
+
|---|---|
|
|
329
|
+
| `@infrawise/shared` | Shared TypeScript types |
|
|
330
|
+
| `@infrawise/core` | Config (Zod + YAML), logger (Pino), local cache |
|
|
331
|
+
| `@infrawise/graph` | Graph engine — nodes, edges, builder |
|
|
332
|
+
| `@infrawise/adapters-dynamodb` | DynamoDB extractor (AWS SDK v3) |
|
|
333
|
+
| `@infrawise/adapters-postgres` | PostgreSQL extractor (pg) |
|
|
334
|
+
| `@infrawise/adapters-mysql` | MySQL extractor (mysql2) |
|
|
335
|
+
| `@infrawise/adapters-mongodb` | MongoDB extractor (mongodb driver) |
|
|
336
|
+
| `@infrawise/adapters-terraform` | Terraform and CloudFormation IaC schema extractor |
|
|
337
|
+
| `@infrawise/context` | Repository scanner (ts-morph AST) |
|
|
338
|
+
| `@infrawise/analyzers` | 11 rule-based analyzers |
|
|
339
|
+
| `@infrawise/server` | Fastify MCP HTTP server |
|
|
340
|
+
| `infrawise` | CLI (Commander.js) |
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Roadmap
|
|
345
|
+
|
|
346
|
+
- [x] MySQL adapter
|
|
347
|
+
- [x] MongoDB adapter
|
|
348
|
+
- [x] Terraform / CloudFormation schema correlation
|
|
349
|
+
- [ ] Latency tracing integration
|
|
350
|
+
- [ ] VS Code extension
|
|
351
|
+
- [ ] Kubernetes workload graph
|
|
352
|
+
- [ ] Infra drift detection
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Contributing
|
|
357
|
+
|
|
358
|
+
### Prerequisites
|
|
359
|
+
|
|
360
|
+
| Requirement | Version |
|
|
361
|
+
|---|---|
|
|
362
|
+
| Node.js | 22+ |
|
|
363
|
+
| pnpm | 9+ |
|
|
364
|
+
| AWS CLI | any (for integration testing) |
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
# Install pnpm if you don't have it
|
|
368
|
+
npm install -g pnpm
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Setup
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
git clone https://github.com/Sidd27/infrawise
|
|
375
|
+
cd infrawise
|
|
376
|
+
pnpm install
|
|
377
|
+
pnpm build
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Development workflow
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
pnpm build # build all packages
|
|
384
|
+
pnpm test # run all tests
|
|
385
|
+
pnpm typecheck # TypeScript strict check
|
|
386
|
+
pnpm lint # ESLint
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Tests live in:
|
|
390
|
+
- `packages/core/src/__tests__/` — config validation
|
|
391
|
+
- `packages/graph/src/__tests__/` — graph builder
|
|
392
|
+
- `packages/analyzers/src/__tests__/` — all 6 analyzers
|
|
393
|
+
|
|
394
|
+
### Adding a new analyzer
|
|
395
|
+
|
|
396
|
+
1. Create your analyzer in `packages/analyzers/src/`
|
|
397
|
+
2. Implement the `Analyzer` interface:
|
|
398
|
+
```ts
|
|
399
|
+
export class MyAnalyzer implements Analyzer {
|
|
400
|
+
name = 'MyAnalyzer';
|
|
401
|
+
async analyze(graph: SystemGraph): Promise<Finding[]> { ... }
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
3. Register it in `packages/analyzers/src/index.ts`
|
|
405
|
+
4. Add tests in `packages/analyzers/src/__tests__/`
|
|
406
|
+
|
|
407
|
+
### Adding a new database adapter
|
|
408
|
+
|
|
409
|
+
1. Create a new package under `packages/adapters/yourdb/`
|
|
410
|
+
2. Export a function returning `Promise<YourTableMetadata[]>`
|
|
411
|
+
3. Extend `SystemGraph` node types in `@infrawise/shared` if needed
|
|
412
|
+
4. Wire it into `packages/cli/src/commands/analyze.ts`
|
|
413
|
+
|
|
414
|
+
### PR checklist
|
|
415
|
+
|
|
416
|
+
- `pnpm test` passes
|
|
417
|
+
- `pnpm typecheck` passes
|
|
418
|
+
- New analyzers have unit tests with mock graph data
|
|
419
|
+
- No hardcoded AWS regions or credentials
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## License
|
|
424
|
+
|
|
425
|
+
MIT
|