From 9b98ab96147f7b5fe0448b95a3a3c6cc9ea67039 Mon Sep 17 00:00:00 2001 From: mblanke Date: Thu, 19 Feb 2026 15:41:15 -0500 Subject: [PATCH] feat: interactive network map, IOC highlighting, AUP hunt selector, type filters - NetworkMap: hunt-scoped force-directed graph with click-to-inspect popover - NetworkMap: zoom/pan (wheel, drag, buttons), viewport transform - NetworkMap: clickable IP/Host/Domain/URL legend chips to filter node types - NetworkMap: brighter colors, 20% smaller nodes - DatasetViewer: IOC columns highlighted with colored headers + cell tinting - AUPScanner: hunt dropdown replacing dataset checkboxes, auto-select all - Rename 'Social Media (Personal)' theme to 'Social Media' with DB migration - Fix /api/hunts timeout: Dataset.rows lazy='noload' (was selectin cascade) - Add OS column mapping to normalizer - Full backend services, DB models, alembic migrations, new routes - New components: Dashboard, HuntManager, FileUpload, NetworkMap, etc. - Docker Compose deployment with nginx reverse proxy --- .env.example | 66 +- .gitignore | 56 + Dockerfile.backend | 18 +- Dockerfile.frontend | 23 +- SKILLS/00-operating-model.md | 21 + SKILLS/05-agent-taxonomy.md | 36 + SKILLS/10-definition-of-done.md | 24 + SKILLS/20-repo-map.md | 16 + SKILLS/25-algorithms-performance.md | 20 + SKILLS/26-vibe-coding-fundamentals.md | 31 + SKILLS/27-performance-profiling.md | 31 + SKILLS/30-implementation-rules.md | 16 + SKILLS/40-testing-quality.md | 14 + SKILLS/50-pr-review.md | 16 + SKILLS/56-ui-material-ui.md | 41 + SKILLS/60-security-safety.md | 15 + SKILLS/70-docs-artifacts.md | 13 + SKILLS/80-mcp-tools.md | 11 + SKILLS/82-mcp-server-design.md | 51 + SKILLS/83-fastmcp-3-patterns.md | 40 + backend/alembic.ini | 149 ++ backend/alembic/README | 1 + backend/alembic/env.py | 67 + backend/alembic/script.py.mako | 28 + .../versions/9790f482da06_initial_schema.py | 210 ++ ..._add_keyword_themes_and_keywords_tables.py | 64 + backend/app/agents/core_v2.py | 408 ++++ backend/app/agents/providers_v2.py | 362 +++ backend/app/agents/registry.py | 161 ++ backend/app/agents/router.py | 183 ++ backend/app/api/routes/agent_v2.py | 265 +++ backend/app/api/routes/annotations.py | 311 +++ backend/app/api/routes/auth.py | 197 ++ backend/app/api/routes/correlation.py | 83 + backend/app/api/routes/datasets.py | 295 +++ backend/app/api/routes/enrichment.py | 220 ++ backend/app/api/routes/hunts.py | 158 ++ backend/app/api/routes/keywords.py | 257 +++ backend/app/api/routes/reports.py | 67 + backend/app/config.py | 121 + backend/app/db/__init__.py | 12 + backend/app/db/engine.py | 54 + backend/app/db/models.py | 328 +++ backend/app/db/repositories/__init__.py | 1 + backend/app/db/repositories/datasets.py | 127 ++ backend/app/main.py | 69 +- backend/app/services/__init__.py | 1 + backend/app/services/auth.py | 201 ++ backend/app/services/correlation.py | 400 ++++ backend/app/services/csv_parser.py | 165 ++ backend/app/services/enrichment.py | 655 ++++++ backend/app/services/keyword_defaults.py | 145 ++ backend/app/services/normalizer.py | 196 ++ backend/app/services/reports.py | 425 ++++ backend/app/services/sans_rag.py | 346 +++ backend/app/services/scanner.py | 233 ++ backend/pyproject.toml | 12 + backend/requirements.txt | 42 +- backend/tests/__init__.py | 1 + backend/tests/conftest.py | 108 + backend/tests/test_agents.py | 117 + backend/tests/test_api.py | 189 ++ backend/tests/test_csv_parser.py | 104 + backend/tests/test_keywords.py | 199 ++ docker-compose.yml | 60 +- .../AGENT_IMPLEMENTATION.md | 0 .../COMPLETION_SUMMARY.md | 0 .../DOCUMENTATION_INDEX.md | 0 .../IMPLEMENTATION_SUMMARY.md | 0 .../INTEGRATION_GUIDE.md | 0 QUICK_REFERENCE.md => docs/QUICK_REFERENCE.md | 0 ROADMAP.md => docs/ROADMAP.md | 0 .../THREATHUNT_INTENT.md | 0 .../VALIDATION_CHECKLIST.md | 0 frontend/nginx.conf | 31 + frontend/package-lock.json | 1947 +++++++++++------ frontend/package.json | 8 + frontend/public/index.html | 30 +- frontend/src/App.tsx | 234 +- frontend/src/api/client.ts | 370 ++++ frontend/src/components/AUPScanner.tsx | 431 ++++ frontend/src/components/AgentPanel.tsx | 446 ++-- frontend/src/components/AnnotationPanel.tsx | 185 ++ frontend/src/components/CorrelationView.tsx | 178 ++ frontend/src/components/Dashboard.tsx | 152 ++ frontend/src/components/DatasetViewer.tsx | 200 ++ frontend/src/components/EnrichmentPanel.tsx | 119 + frontend/src/components/FileUpload.tsx | 223 ++ frontend/src/components/HuntManager.tsx | 156 ++ frontend/src/components/HypothesisTracker.tsx | 202 ++ frontend/src/components/NetworkMap.tsx | 777 +++++++ frontend/src/theme.ts | 86 + 92 files changed, 13042 insertions(+), 1089 deletions(-) create mode 100644 .gitignore create mode 100644 SKILLS/00-operating-model.md create mode 100644 SKILLS/05-agent-taxonomy.md create mode 100644 SKILLS/10-definition-of-done.md create mode 100644 SKILLS/20-repo-map.md create mode 100644 SKILLS/25-algorithms-performance.md create mode 100644 SKILLS/26-vibe-coding-fundamentals.md create mode 100644 SKILLS/27-performance-profiling.md create mode 100644 SKILLS/30-implementation-rules.md create mode 100644 SKILLS/40-testing-quality.md create mode 100644 SKILLS/50-pr-review.md create mode 100644 SKILLS/56-ui-material-ui.md create mode 100644 SKILLS/60-security-safety.md create mode 100644 SKILLS/70-docs-artifacts.md create mode 100644 SKILLS/80-mcp-tools.md create mode 100644 SKILLS/82-mcp-server-design.md create mode 100644 SKILLS/83-fastmcp-3-patterns.md create mode 100644 backend/alembic.ini create mode 100644 backend/alembic/README create mode 100644 backend/alembic/env.py create mode 100644 backend/alembic/script.py.mako create mode 100644 backend/alembic/versions/9790f482da06_initial_schema.py create mode 100644 backend/alembic/versions/98ab619418bc_add_keyword_themes_and_keywords_tables.py create mode 100644 backend/app/agents/core_v2.py create mode 100644 backend/app/agents/providers_v2.py create mode 100644 backend/app/agents/registry.py create mode 100644 backend/app/agents/router.py create mode 100644 backend/app/api/routes/agent_v2.py create mode 100644 backend/app/api/routes/annotations.py create mode 100644 backend/app/api/routes/auth.py create mode 100644 backend/app/api/routes/correlation.py create mode 100644 backend/app/api/routes/datasets.py create mode 100644 backend/app/api/routes/enrichment.py create mode 100644 backend/app/api/routes/hunts.py create mode 100644 backend/app/api/routes/keywords.py create mode 100644 backend/app/api/routes/reports.py create mode 100644 backend/app/config.py create mode 100644 backend/app/db/__init__.py create mode 100644 backend/app/db/engine.py create mode 100644 backend/app/db/models.py create mode 100644 backend/app/db/repositories/__init__.py create mode 100644 backend/app/db/repositories/datasets.py create mode 100644 backend/app/services/__init__.py create mode 100644 backend/app/services/auth.py create mode 100644 backend/app/services/correlation.py create mode 100644 backend/app/services/csv_parser.py create mode 100644 backend/app/services/enrichment.py create mode 100644 backend/app/services/keyword_defaults.py create mode 100644 backend/app/services/normalizer.py create mode 100644 backend/app/services/reports.py create mode 100644 backend/app/services/sans_rag.py create mode 100644 backend/app/services/scanner.py create mode 100644 backend/pyproject.toml create mode 100644 backend/tests/__init__.py create mode 100644 backend/tests/conftest.py create mode 100644 backend/tests/test_agents.py create mode 100644 backend/tests/test_api.py create mode 100644 backend/tests/test_csv_parser.py create mode 100644 backend/tests/test_keywords.py rename AGENT_IMPLEMENTATION.md => docs/AGENT_IMPLEMENTATION.md (100%) rename COMPLETION_SUMMARY.md => docs/COMPLETION_SUMMARY.md (100%) rename DOCUMENTATION_INDEX.md => docs/DOCUMENTATION_INDEX.md (100%) rename IMPLEMENTATION_SUMMARY.md => docs/IMPLEMENTATION_SUMMARY.md (100%) rename INTEGRATION_GUIDE.md => docs/INTEGRATION_GUIDE.md (100%) rename QUICK_REFERENCE.md => docs/QUICK_REFERENCE.md (100%) rename ROADMAP.md => docs/ROADMAP.md (100%) rename THREATHUNT_INTENT.md => docs/THREATHUNT_INTENT.md (100%) rename VALIDATION_CHECKLIST.md => docs/VALIDATION_CHECKLIST.md (100%) create mode 100644 frontend/nginx.conf create mode 100644 frontend/src/api/client.ts create mode 100644 frontend/src/components/AUPScanner.tsx create mode 100644 frontend/src/components/AnnotationPanel.tsx create mode 100644 frontend/src/components/CorrelationView.tsx create mode 100644 frontend/src/components/Dashboard.tsx create mode 100644 frontend/src/components/DatasetViewer.tsx create mode 100644 frontend/src/components/EnrichmentPanel.tsx create mode 100644 frontend/src/components/FileUpload.tsx create mode 100644 frontend/src/components/HuntManager.tsx create mode 100644 frontend/src/components/HypothesisTracker.tsx create mode 100644 frontend/src/components/NetworkMap.tsx create mode 100644 frontend/src/theme.ts diff --git a/.env.example b/.env.example index 38f5089..e37407f 100644 --- a/.env.example +++ b/.env.example @@ -1,27 +1,53 @@ -# Docker environment configuration -# Copy this to .env and customize for your deployment +# ── ThreatHunt Configuration ────────────────────────────────────────── +# All backend env vars are prefixed with TH_ and match AppConfig field names. +# Copy this file to .env and adjust values. -# Agent Configuration -# Choose one: local, networked, online, auto -THREAT_HUNT_AGENT_PROVIDER=auto +# ── General ─────────────────────────────────────────────────────────── +TH_DEBUG=false -# Local Provider (on-device or on-prem models) -# THREAT_HUNT_LOCAL_MODEL_PATH=/models/model.gguf +# ── Database ────────────────────────────────────────────────────────── +# SQLite for local dev (zero-config): +TH_DATABASE_URL=sqlite+aiosqlite:///./threathunt.db +# PostgreSQL for production: +# TH_DATABASE_URL=postgresql+asyncpg://threathunt:password@localhost:5432/threathunt -# Networked Provider (shared internal inference service) -# THREAT_HUNT_NETWORKED_ENDPOINT=http://inference-service:5000 -# THREAT_HUNT_NETWORKED_KEY=api-key-here +# ── CORS ────────────────────────────────────────────────────────────── +TH_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8000 -# Online Provider (external hosted APIs) -# THREAT_HUNT_ONLINE_API_KEY=sk-your-api-key -# THREAT_HUNT_ONLINE_PROVIDER=openai -# THREAT_HUNT_ONLINE_MODEL=gpt-3.5-turbo +# ── File uploads ────────────────────────────────────────────────────── +TH_MAX_UPLOAD_SIZE_MB=500 -# Agent Behavior -THREAT_HUNT_AGENT_MAX_TOKENS=1024 -THREAT_HUNT_AGENT_REASONING=true -THREAT_HUNT_AGENT_HISTORY_LENGTH=10 -THREAT_HUNT_AGENT_FILTER_SENSITIVE=true +# ── LLM Cluster (Wile & Roadrunner) ────────────────────────────────── +TH_OPENWEBUI_URL=https://ai.guapo613.beer +TH_OPENWEBUI_API_KEY= +TH_WILE_HOST=100.110.190.12 +TH_WILE_OLLAMA_PORT=11434 +TH_ROADRUNNER_HOST=100.110.190.11 +TH_ROADRUNNER_OLLAMA_PORT=11434 -# Frontend +# ── Default models (auto-selected by TaskRouter) ───────────────────── +TH_DEFAULT_FAST_MODEL=llama3.1:latest +TH_DEFAULT_HEAVY_MODEL=llama3.1:70b-instruct-q4_K_M +TH_DEFAULT_CODE_MODEL=qwen2.5-coder:32b +TH_DEFAULT_VISION_MODEL=llama3.2-vision:11b +TH_DEFAULT_EMBEDDING_MODEL=bge-m3:latest + +# ── Agent behaviour ────────────────────────────────────────────────── +TH_AGENT_MAX_TOKENS=2048 +TH_AGENT_TEMPERATURE=0.3 +TH_AGENT_HISTORY_LENGTH=10 +TH_FILTER_SENSITIVE_DATA=true + +# ── Enrichment API keys (optional) ─────────────────────────────────── +TH_VIRUSTOTAL_API_KEY= +TH_ABUSEIPDB_API_KEY= +TH_SHODAN_API_KEY= + +# ── Auth ───────────────────────────────────────────────────────────── +TH_JWT_SECRET=CHANGE-ME-IN-PRODUCTION-USE-A-REAL-SECRET +TH_JWT_ACCESS_TOKEN_MINUTES=60 +TH_JWT_REFRESH_TOKEN_DAYS=7 + +# ── Frontend ───────────────────────────────────────────────────────── REACT_APP_API_URL=http://localhost:8000 + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3cb1044 --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# ── Python ──────────────────────────────────── +__pycache__/ +*.py[cod] +*$py.class +*.egg-info/ +dist/ +build/ +*.egg +.eggs/ + +# ── Virtual environments ───────────────────── +venv/ +.venv/ +env/ + +# ── IDE / Editor ───────────────────────────── +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# ── OS ──────────────────────────────────────── +.DS_Store +Thumbs.db + +# ── Environment / Secrets ──────────────────── +.env +*.env.local + +# ── Database ───────────────────────────────── +*.db +*.sqlite3 + +# ── Uploads ────────────────────────────────── +uploads/ + +# ── Node / Frontend ────────────────────────── +node_modules/ +frontend/build/ +frontend/.env.local +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# ── Docker ─────────────────────────────────── +docker-compose.override.yml + +# ── Test / Coverage ────────────────────────── +.coverage +htmlcov/ +.pytest_cache/ +.mypy_cache/ + +# ── Alembic ────────────────────────────────── +alembic/versions/*.pyc diff --git a/Dockerfile.backend b/Dockerfile.backend index cf1011b..999eca4 100644 --- a/Dockerfile.backend +++ b/Dockerfile.backend @@ -1,11 +1,11 @@ -# ThreatHunt Backend API - Python 3.11 -FROM python:3.11-slim +# ThreatHunt Backend API - Python 3.13 +FROM python:3.13-slim WORKDIR /app # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ - gcc \ + gcc curl \ && rm -rf /var/lib/apt/lists/* # Copy requirements @@ -17,16 +17,16 @@ RUN pip install --no-cache-dir -r requirements.txt # Copy backend code COPY backend/ . -# Create non-root user -RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app +# Create non-root user & data directory +RUN useradd -m -u 1000 appuser && mkdir -p /app/data && chown -R appuser:appuser /app USER appuser # Expose port EXPOSE 8000 # Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD python -c "import requests; requests.get('http://localhost:8000/api/agent/health')" +HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:8000/ || exit 1 -# Run application -CMD ["python", "run.py"] +# Run Alembic migrations then start Uvicorn +CMD ["sh", "-c", "python -m alembic upgrade head && python run.py"] diff --git a/Dockerfile.frontend b/Dockerfile.frontend index e28fab3..c99551c 100644 --- a/Dockerfile.frontend +++ b/Dockerfile.frontend @@ -1,5 +1,5 @@ # ThreatHunt Frontend - Node.js React -FROM node:18-alpine AS builder +FROM node:20-alpine AS builder WORKDIR /app @@ -17,20 +17,14 @@ COPY frontend/tsconfig.json ./ # Build application RUN npm run build -# Production stage -FROM node:18-alpine +# Production stage — nginx reverse-proxy + static files +FROM nginx:alpine -WORKDIR /app +# Copy built React app +COPY --from=builder /app/build /usr/share/nginx/html -# Install serve to serve the static files -RUN npm install -g serve - -# Copy built application from builder -COPY --from=builder /app/build ./build - -# Create non-root user -RUN addgroup -g 1000 appuser && adduser -D -u 1000 -G appuser appuser -USER appuser +# Copy custom nginx config (proxies /api to backend) +COPY frontend/nginx.conf /etc/nginx/conf.d/default.conf # Expose port EXPOSE 3000 @@ -39,5 +33,4 @@ EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget --quiet --tries=1 --spider http://localhost:3000/ || exit 1 -# Serve application -CMD ["serve", "-s", "build", "-l", "3000"] +CMD ["nginx", "-g", "daemon off;"] diff --git a/SKILLS/00-operating-model.md b/SKILLS/00-operating-model.md new file mode 100644 index 0000000..98d16b4 --- /dev/null +++ b/SKILLS/00-operating-model.md @@ -0,0 +1,21 @@ + +# Operating Model + +## Default cadence +- Prefer iterative progress over big bangs. +- Keep diffs small: target ≤ 300 changed lines per PR unless justified. +- Update tests/docs as part of the same change when possible. + +## Working agreement +- Start with a PLAN for non-trivial tasks. +- Implement the smallest slice that satisfies acceptance criteria. +- Verify via DoD. +- Write a crisp PR summary: what changed, why, and how verified. + +## Stop conditions (plan first) +Stop and produce a PLAN (do not code yet) if: +- scope is unclear +- more than 3 files will change +- data model changes +- auth/security boundaries +- performance-critical paths diff --git a/SKILLS/05-agent-taxonomy.md b/SKILLS/05-agent-taxonomy.md new file mode 100644 index 0000000..5063494 --- /dev/null +++ b/SKILLS/05-agent-taxonomy.md @@ -0,0 +1,36 @@ +# Agent Types & Roles (Practical Taxonomy) + +Use this skill to choose the *right* kind of agent workflow for the job. + +## Common agent "types" (in practice) + +### 1) Chat assistant (no tools) +Best for: explanations, brainstorming, small edits. +Risk: can hallucinate; no grounding in repo state. + +### 2) Tool-using single agent +Best for: well-scoped tasks where the agent can read/write files and run commands. +Key control: strict DoD gates + minimal permissions. + +### 3) Planner + Executor (2-role pattern) +Best for: medium complexity work (multi-file changes, feature work). +Flow: Planner writes plan + acceptance criteria → Executor implements → Reviewer checks. + +### 4) Multi-agent (specialists) +Best for: bigger features with separable workstreams (UI, backend, docs, tests). +Rule: isolate context per role; use separate branches/worktrees. + +### 5) Supervisor / orchestrator +Best for: long-running workflows with checkpoints (pipelines, report generation, PAD docs). +Rule: supervisor delegates, enforces gates, and composes final output. + +## Decision rules (fast) +- If you can describe it in ≤ 5 steps → single tool-using agent. +- If you need tradeoffs/design → Planner + Executor. +- If UI + backend + docs/tests all move → multi-agent specialists. +- If it's a pipeline that runs repeatedly → orchestrator. + +## Guardrails (always) +- DoD is the truth gate. +- Separate branches/worktrees for parallel work. +- Log decisions + commands in AGENT_LOG.md. diff --git a/SKILLS/10-definition-of-done.md b/SKILLS/10-definition-of-done.md new file mode 100644 index 0000000..d99148e --- /dev/null +++ b/SKILLS/10-definition-of-done.md @@ -0,0 +1,24 @@ + +# Definition of Done (DoD) + +A change is "done" only when: + +## Code correctness +- Builds successfully (if applicable) +- Tests pass +- Linting/formatting passes +- Types/checks pass (if applicable) + +## Quality +- No new warnings introduced +- Edge cases handled (inputs validated, errors meaningful) +- Hot paths not regressed (if applicable) + +## Hygiene +- No secrets committed +- Docs updated if behavior or usage changed +- PR summary includes verification steps + +## Commands +- macOS/Linux: `./scripts/dod.sh` +- Windows: `\scripts\dod.ps1` diff --git a/SKILLS/20-repo-map.md b/SKILLS/20-repo-map.md new file mode 100644 index 0000000..810f986 --- /dev/null +++ b/SKILLS/20-repo-map.md @@ -0,0 +1,16 @@ + +# Repo Mapping Skill + +When entering a repo: +1) Read README.md +2) Identify entrypoints (app main / server startup / CLI) +3) Identify config (env vars, .env.example, config files) +4) Identify test/lint scripts (package.json, pyproject.toml, Makefile, etc.) +5) Write a 10-line "repo map" in the PLAN before changing code + +Output format: +- Purpose: +- Key modules: +- Data flow: +- Commands: +- Risks: diff --git a/SKILLS/25-algorithms-performance.md b/SKILLS/25-algorithms-performance.md new file mode 100644 index 0000000..4bbe6b2 --- /dev/null +++ b/SKILLS/25-algorithms-performance.md @@ -0,0 +1,20 @@ +# Algorithms & Performance + +Use this skill when performance matters (large inputs, hot paths, or repeated calls). + +## Checklist +- Identify the **state** you're recomputing. +- Add **memoization / caching** when the same subproblem repeats. +- Prefer **linear scans** + caches over nested loops when possible. +- If you can write it as a **recurrence**, you can test it. + +## Practical heuristics +- Measure first when possible (timing + input sizes). +- Optimize the biggest wins: avoid repeated I/O, repeated parsing, repeated network calls. +- Keep caches bounded (size/TTL) and invalidate safely. +- Choose data structures intentionally: dict/set for membership, heap for top-k, deque for queues. + +## Review notes (for PRs) +- Call out accidental O(n²) patterns. +- Suggest table/DP or memoization when repeated work is obvious. +- Add tests that cover base cases + typical cases + worst-case size. diff --git a/SKILLS/26-vibe-coding-fundamentals.md b/SKILLS/26-vibe-coding-fundamentals.md new file mode 100644 index 0000000..01c4b4e --- /dev/null +++ b/SKILLS/26-vibe-coding-fundamentals.md @@ -0,0 +1,31 @@ +# Vibe Coding With Fundamentals (Safety Rails) + +Use this skill when you're using "vibe coding" (fast, conversational building) but want production-grade outcomes. + +## The good +- Rapid scaffolding and iteration +- Fast UI prototypes +- Quick exploration of architectures and options + +## The failure mode +- "It works on my machine" code with weak tests +- Security foot-guns (auth, input validation, secrets) +- Performance cliffs (accidental O(n²), repeated I/O) +- Unmaintainable abstractions + +## Safety rails (apply every time) +- Always start with acceptance criteria (what "done" means). +- Prefer small PRs; never dump a huge AI diff. +- Require DoD gates (lint/test/build) before merge. +- Write tests for behavior changes. +- For anything security/data related: do a Reviewer pass. + +## When to slow down +- Auth/session/token work +- Anything touching payments, PII, secrets +- Data migrations/schema changes +- Performance-critical paths +- "It's flaky" or "it only fails in CI" + +## Practical prompt pattern (use in PLAN) +- "State assumptions, list files to touch, propose tests, and include rollback steps." diff --git a/SKILLS/27-performance-profiling.md b/SKILLS/27-performance-profiling.md new file mode 100644 index 0000000..6dc5504 --- /dev/null +++ b/SKILLS/27-performance-profiling.md @@ -0,0 +1,31 @@ +# Performance Profiling (Bun/Node) + +Use this skill when: +- a hot path feels slow +- CPU usage is high +- you suspect accidental O(n²) or repeated work +- you need evidence before optimizing + +## Bun CPU profiling +Bun supports CPU profiling via `--cpu-prof` (generates a `.cpuprofile` you can open in Chrome DevTools). + +Upcoming: `bun --cpu-prof-md