Skip to content

Commit 18a3bc7

Browse files
committed
SpecterOps: autonomous post-incident forensics agent (Gemini 2.5 Flash + Dynatrace)
0 parents  commit 18a3bc7

68 files changed

Lines changed: 11893 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# ── BACKEND (copy to backend/.env) ───────────────────────────────────────────
2+
3+
# Gemini — recommended. Without it, agents use the scenario-accurate offline mode.
4+
GEMINI_API_KEY=your_gemini_api_key_here
5+
# Optional: pin a specific model. Otherwise a resilient candidate chain is used.
6+
GEMINI_MODEL=
7+
GOOGLE_CLOUD_PROJECT=your_gcp_project_id
8+
9+
# Demo mode — true uses simulated Dynatrace telemetry (no account needed).
10+
DEMO_MODE=true
11+
12+
# Optional: real Dynatrace (only used when DEMO_MODE=false)
13+
DYNATRACE_URL=https://your-env-id.live.dynatrace.com
14+
DYNATRACE_API_TOKEN=your_dynatrace_api_token_here
15+
16+
# Optional: MongoDB Atlas for persistent incident history (graceful if unset)
17+
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/specterops
18+
19+
# Optional: Slack incoming webhook to deliver post-mortems to a channel
20+
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/your/webhook/url
21+
22+
PORT=8000
23+
FRONTEND_URL=http://localhost:5173

.github/workflows/ci.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
# Cancel superseded runs on the same ref.
10+
concurrency:
11+
group: ci-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
jobs:
15+
backend:
16+
name: Backend · tests (Python ${{ matrix.python-version }})
17+
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
python-version: ["3.11", "3.12"]
22+
defaults:
23+
run:
24+
working-directory: backend
25+
env:
26+
DEMO_MODE: "true"
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Set up Python
31+
uses: actions/setup-python@v5
32+
with:
33+
python-version: ${{ matrix.python-version }}
34+
cache: pip
35+
cache-dependency-path: backend/requirements.txt
36+
37+
- name: Install dependencies
38+
run: pip install -r requirements.txt
39+
40+
- name: Run pipeline test suite
41+
run: python -m pytest
42+
43+
frontend:
44+
name: Frontend · build
45+
runs-on: ubuntu-latest
46+
defaults:
47+
run:
48+
working-directory: frontend
49+
steps:
50+
- uses: actions/checkout@v4
51+
52+
- name: Set up Node
53+
uses: actions/setup-node@v4
54+
with:
55+
node-version: "20"
56+
cache: npm
57+
cache-dependency-path: frontend/package-lock.json
58+
59+
- name: Install dependencies
60+
run: npm ci
61+
62+
- name: Build production bundle
63+
run: npm run build

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Python
2+
__pycache__/
3+
*.pyc
4+
.env
5+
venv/
6+
.venv/
7+
.pytest_cache/
8+
9+
# Node / Vite
10+
node_modules/
11+
dist/
12+
.firebase/
13+
14+
# Misc
15+
.DS_Store
16+
*.log

INTEGRATIONS.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# SpecterOps — Integrations & Going Live
2+
3+
SpecterOps runs with **zero setup** (simulated telemetry + offline reasoning). Each
4+
integration below upgrades a part of the system from "demo" to "real". Add them in
5+
any order — everything degrades gracefully if a key is missing.
6+
7+
> After editing **`backend/.env`** restart the backend. After editing
8+
> **`frontend/.env`** restart the frontend (Vite only reads `VITE_*` at startup).
9+
10+
---
11+
12+
## 1. Gemini (AI reasoning) — free
13+
14+
Turns the agents from scripted offline output into **real LLM reasoning**.
15+
16+
1. Get a free key at **https://aistudio.google.com/apikey**.
17+
2. In `backend/.env`:
18+
```
19+
GEMINI_API_KEY=AIza... # your key
20+
GEMINI_MODEL=gemini-2.5-flash # recommended; blank = auto fallback chain
21+
```
22+
**Which model:** use **`gemini-2.5-flash`** — fast (keeps the live demo snappy), generous
23+
free tier. `gemini-2.5-pro` writes slightly richer post-mortems but is slower and has
24+
tighter free limits. If a model is unavailable the app auto-falls back down the chain.
25+
26+
---
27+
28+
## 2. Dynatrace (real incidents) — free trial
29+
30+
Lets SpecterOps pull **real open problems** from your tenant and analyze them.
31+
32+
1. Start a free **Dynatrace trial** (SaaS) — or use the public **Playground**.
33+
2. Find your environment URL. Whatever you log in at (e.g. `https://abc12345.apps.dynatrace.com`),
34+
the **API host** is the `.live.` form:
35+
```
36+
DYNATRACE_URL=https://abc12345.live.dynatrace.com
37+
```
38+
(No trailing slash, no `/api`. The Playground's value is `https://playground.live.dynatrace.com`.)
39+
3. Create an **Access token**: Settings → Access tokens → Generate. Tick these scopes:
40+
41+
| Scope (UI) | Internal | Used for | Priority |
42+
|---|---|---|---|
43+
| Read problems | `problems.read` | `GET /api/v2/problems` — auto-pull the incident | ⭐ required |
44+
| Read metrics | `metrics.read` | `GET /api/v2/metrics/query` — error rate & latency | ⭐ required |
45+
| Read entities | `entities.read` | `GET /api/v2/entities` — topology | recommended |
46+
| Read logs | `logs.read` | `GET /api/v2/logs/search` — log evidence (needs Log Management) | optional |
47+
| Write problem comments | `problems.write` | post the RCA **back** onto the problem | optional |
48+
4. In `backend/.env`:
49+
```
50+
DEMO_MODE=false
51+
DYNATRACE_URL=https://<env-id>.live.dynatrace.com
52+
DYNATRACE_API_TOKEN=dt0c01....
53+
```
54+
5. Restart the backend → the **"Investigate latest live Dynatrace problem"** button appears.
55+
56+
**Notes & honest limits**
57+
- Dynatrace has **no public "read traces" REST endpoint** (traces live in Grail/DQL), so
58+
the live path uses problems + metrics + entities + logs. Investigations still complete.
59+
- `response.time` is returned in **microseconds** and `errors.total.rate` as a **percent**
60+
SpecterOps normalizes both. If a value can't be resolved, the metric tile is hidden rather
61+
than shown wrong.
62+
- **Push to Dynatrace** (posting the RCA as a problem comment) needs `problems.write`. The
63+
read-only Playground token returns 403 — that's expected.
64+
- The richest visuals come from `DEMO_MODE=true` (full simulated scenarios) reasoned over by
65+
real Gemini. `DEMO_MODE=false` shows *real* problems, whose richness depends on your tenant.
66+
67+
---
68+
69+
## 3. MongoDB Atlas (persistent history) — free M0
70+
71+
Without it, incidents live in memory and reset on restart. With it, history persists.
72+
73+
1. Create a free account at **https://www.mongodb.com/atlas** and a free **M0** cluster.
74+
2. **Database Access** → Add a database user (username + password).
75+
3. **Network Access** → Add IP → allow your IP (or `0.0.0.0/0` for testing).
76+
4. **Connect → Drivers → Python** → copy the SRV connection string and insert your password:
77+
```
78+
MONGODB_URI=mongodb+srv://USER:PASSWORD@cluster0.xxxxx.mongodb.net/specterops
79+
```
80+
5. Put it in `backend/.env`, restart. The status badge flips to **DB · persisted**.
81+
82+
---
83+
84+
## 4. Firebase Auth (real Google / email sign-in) — free
85+
86+
> **Why does clicking sign-in jump straight to a "demo" user?** Because Firebase isn't
87+
> configured yet, the app uses a built-in **demo identity** so the flow works with zero setup.
88+
> Add the keys below to get **real Google + email/password** login.
89+
90+
1. Create a project at **https://console.firebase.google.com**.
91+
2. **Build → Authentication → Get started** → enable **Google** and **Email/Password**.
92+
3. **Project settings → General → Your apps →** add a **Web app** → copy the SDK config.
93+
4. **Authentication → Settings → Authorized domains** → add `localhost` (and your deployed domain).
94+
5. Create **`frontend/.env`** (copy from `frontend/.env.example`) and fill:
95+
```
96+
VITE_FIREBASE_API_KEY=...
97+
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
98+
VITE_FIREBASE_PROJECT_ID=your-project
99+
VITE_FIREBASE_APP_ID=1:...:web:...
100+
```
101+
6. Restart the frontend (`npm run dev`). Sign-in now uses real Google/email; the modal's
102+
"Demo auth active" note disappears.
103+
104+
Signed-in users' investigations are tagged to their account and shown in their **Profile**.
105+
106+
---
107+
108+
## 5. Slack delivery (optional) — free
109+
110+
1. Create an **Incoming Webhook** at https://api.slack.com/messaging/webhooks.
111+
2. In `backend/.env`: `SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...`
112+
3. Restart. A **Send to Slack** button appears on the post-mortem.
113+
114+
---
115+
116+
## About auto-remediation
117+
118+
SpecterOps generates the **exact fix** and can **push the RCA back onto the Dynatrace
119+
problem** as a comment (with `problems.write`). It deliberately does **not** auto-execute
120+
fixes (creating indexes, rolling back deploys, restarting pods) — that requires direct,
121+
privileged access to your infrastructure/CI and must stay behind a human approval gate.
122+
Auto-applying production changes from an AALU loop is unsafe; the responsible pattern is
123+
**diagnose autonomously → recommend the fix → human approves → automation applies it.**
124+
That approval-gated execution is the natural next step and can be wired to your CI/CD.
125+
126+
---
127+
128+
## Per-user Dynatrace (future)
129+
130+
Today SpecterOps connects to **one** Dynatrace tenant configured in `backend/.env`. Letting
131+
each signed-in user connect *their own* tenant (e.g. via OAuth + stored per-user tokens) is a
132+
multi-tenant feature — straightforward to add on top of the current auth, but out of scope for
133+
the single-tenant demo.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 SpecterOps Contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)