1
<template>
2
- <div class="flex flex-col gap-8 p-2">
2
+ <div class="flex flex-col gap-8">
3
<!-- Hero -->
4
<div class="flex flex-col items-center gap-3 py-6 text-center">
5
<div class="bg-primary/10 flex h-16 w-16 items-center justify-center rounded-2xl">
13
<div class="mt-1 flex items-center gap-2">
14
<n-tag size="small" round type="success">
15
<template #icon>
16
- <Icon name="carbon:checkmark-filled" :size="12" />
16
+ <Icon name="carbon:checkmark-filled" />
17
</template>
18
Integrated
19
</n-tag>
20
- <n-tag v-if="status" size="small" round :type="status === 'healthy' ? 'success' : 'warning'">
20
+ <n-tag
21
+ v-if="status"
22
+ size="small"
23
+ round
24
+ :type="status === 'healthy' ? 'success' : 'warning'"
25
+ class="animate-fade"
26
+ >
27
{{ status === "healthy" ? "Online" : status }}
28
</n-tag>
23
- <n-tag v-else-if="statusChecked" size="small" round type="error">Unreachable</n-tag>
29
+ <n-tag v-else-if="statusChecked" size="small" round type="error" class="animate-fade">
30
+ Unreachable
31
+ </n-tag>
32
</div>
33
<a
34
href="https://github.com/taylorwalton/talon"
35
target="_blank"
36
rel="noopener noreferrer"
29
- class="text-primary mt-1 inline-flex items-center gap-1.5 text-xs hover:underline"
37
+ class="text-primary mt-1 inline-flex items-center gap-1.5 text-xs no-underline hover:underline"
38
>
39
<Icon name="carbon:logo-github" :size="14" />
40
<span>github.com/taylorwalton/talon</span>
42
</a>
43
</div>
44
37
- <!-- How It Works -->
38
- <section>
39
- <SectionHeader title="How It Works" icon="carbon:flow" />
40
- <div class="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
41
- <StepCard
42
- v-for="item in investigationSteps"
43
- :key="item.step"
44
- :step="item.step"
45
- :title="item.title"
46
- :description="item.description"
47
- :icon="item.icon"
48
- />
49
- </div>
50
- </section>
51
-
52
- <!-- Capabilities -->
53
- <section>
54
- <SectionHeader title="Capabilities" icon="carbon:catalog" />
55
- <div class="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
56
- <FeatureCard
57
- v-for="feature in capabilities"
58
- :key="feature.title"
59
- :title="feature.title"
60
- :description="feature.description"
61
- :icon="feature.icon"
62
- />
63
- </div>
64
- </section>
65
-
66
- <!-- Architecture -->
67
- <section>
68
- <SectionHeader title="Architecture" icon="carbon:network-4" />
69
- <div class="bg-secondary mt-3 overflow-x-auto rounded-lg p-5">
45
+ <n-tabs type="card" placement="left" animated>
46
+ <n-tab-pane name="How It Works" tab="How It Works">
47
+ <div class="grid grid-cols-1 gap-3">
48
+ <StepCard
49
+ v-for="item in investigationSteps"
50
+ :key="item.step"
51
+ :step="item.step"
52
+ :title="item.title"
53
+ :description="item.description"
54
+ :icon="item.icon"
55
+ />
56
+ </div>
57
+ </n-tab-pane>
58
+ <n-tab-pane name="Capabilities" tab="Capabilities">
59
+ <div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
60
+ <FeatureCard
61
+ v-for="feature in capabilities"
62
+ :key="feature.title"
63
+ :title="feature.title"
64
+ :description="feature.description"
65
+ :icon="feature.icon"
66
+ />
67
+ </div>
68
+ </n-tab-pane>
69
+ <n-tab-pane name="Architecture" tab="Architecture">
70
<pre class="text-default text-xs leading-relaxed"><code>{{ architectureDiagram }}</code></pre>
71
- </div>
72
- </section>
73
-
74
- <!-- Integration Points -->
75
- <section>
76
- <SectionHeader title="CoPilot Integration" icon="carbon:connect" />
77
- <div class="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2">
78
- <FeatureCard
79
- v-for="point in integrationPoints"
80
- :key="point.title"
81
- :title="point.title"
82
- :description="point.description"
83
- :icon="point.icon"
84
- />
85
- </div>
86
- </section>
71
+ </n-tab-pane>
72
+ <n-tab-pane name="CoPilot Integration" tab="CoPilot Integration">
73
+ <div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
74
+ <FeatureCard
75
+ v-for="point in integrationPoints"
76
+ :key="point.title"
77
+ :title="point.title"
78
+ :description="point.description"
79
+ :icon="point.icon"
80
+ />
81
+ </div>
82
+ </n-tab-pane>
83
+ </n-tabs>
84
</div>
85
</template>
86
87
<script setup lang="ts">
91
-import { NTag } from "naive-ui"
88
+import { NTabPane, NTabs, NTag } from "naive-ui"
89
import { defineComponent, h, onMounted, ref } from "vue"
90
import Api from "@/api"
91
import Icon from "@/components/common/Icon.vue"
92
96
-// --- Inline sub-components ---
97
-
98
-const SectionHeader = defineComponent({
99
- props: { title: String, icon: String },
100
- setup(props) {
101
- return () =>
102
- h("div", { class: "flex items-center gap-2" }, [
103
- h(Icon, { name: props.icon, size: 18, class: "text-primary" }),
104
- h("h2", { class: "text-default text-lg font-semibold" }, props.title)
105
- ])
106
- }
107
-})
108
-
93
const StepCard = defineComponent({
94
props: { step: Number, title: String, description: String, icon: String },
95
setup(props) {
244
}
245
]
246
263
-const architectureDiagram = `┌──────────────────────────────────────────────────────┐
247
+const architectureDiagram = `┌───────────────────────────────────────────────────────┐
248
│ CoPilot (FastAPI) │
265
-│ │
266
-│ Alert created → POST /investigate ──────────────┐ │
267
-│ GET /status, GET /jobs/:alertId ← Talon HTTP API│ │
268
-│ │ │
269
-│ Write-back API (MCP tools): │ │
270
-│ POST /api/ai_analyst/jobs ←───────────┘ │
271
-│ POST /api/ai_analyst/reports │
272
-│ POST /api/ai_analyst/iocs │
273
-│ MySQL: ai_analyst_job / report / ioc │
274
-└───────────────────────┬──────────────────────────────┘
275
- │ read-only MCP ▲ REST write-back
276
- ▼ │
277
-┌──────────────────────────────────────────────────────┐
249
+│ │
250
+│ Alert created → POST /investigate ───────────────┐ │
251
+│ GET /status, GET /jobs/:alertId ← Talon HTTP API │ │
252
+│ │ │
253
+│ Write-back API (MCP tools): │ │
254
+│ POST /api/ai_analyst/jobs ←────────────┘ │
255
+│ POST /api/ai_analyst/reports │
256
+│ POST /api/ai_analyst/iocs │
257
+│ MySQL: ai_analyst_job / report / ioc │
258
+└───────────┬───────────────────────────────────────────┘
259
+ │ ▲ REST write-back
260
+ ▼ read-only MCP │
261
+┌────────────────────────────────┴──────────────────────┐
262
│ Talon (Node.js) │
279
-│ │
280
-│ HTTP channel (port 3100) │
281
-│ POST /investigate ← CoPilot triggers this │
282
-│ POST /message ← ad-hoc analyst prompts │
283
-│ GET /status ← queue + job overview │
284
-│ │
285
-│ Scheduled task (every 15 min) │
286
-│ Queries MySQL for OPEN alerts with no job row │
287
-│ Runs full investigation per alert │
288
-│ │
289
-│ SOC agent (containerized) │
290
-│ groups/copilot/CLAUDE.md ← investigation flow │
291
-│ groups/copilot/prompts/ ← per-alert templates │
292
-└──────────────────────────────────────────────────────┘
293
- │ MCP tools (read-only)
294
- ▼
295
-┌──────────────────────────────────────────────────────┐
296
-│ opensearch-mcp — raw SIEM queries │
297
-│ opensearch_anon — anonymizing proxy (PII→tokens) │
298
-│ mysql-mcp — CoPilot DB (alerts, assets) │
299
-│ copilot-mcp — CoPilot REST API write-back │
300
-│ ollama (optional) — local LLM for sensitive data │
301
-│ mempalace — persistent investigation memory │
302
-└──────────────────────────────────────────────────────┘`
263
+│ │
264
+│ HTTP channel (port 3100) │
265
+│ POST /investigate ← CoPilot triggers this │
266
+│ POST /message ← ad-hoc analyst prompts │
267
+│ GET /status ← queue + job overview │
268
+│ │
269
+│ Scheduled task (every 15 min) │
270
+│ Queries MySQL for OPEN alerts with no job row │
271
+│ Runs full investigation per alert │
272
+│ │
273
+│ SOC agent (containerized) │
274
+│ groups/copilot/CLAUDE.md ← investigation flow │
275
+│ groups/copilot/prompts/ ← per-alert templates │
276
+└───────────────┬───────────────────────────────────────┘
277
+ │
278
+ ▼ MCP tools (read-only)
279
+┌───────────────────────────────────────────────────────┐
280
+│ opensearch-mcp — raw SIEM queries │
281
+│ opensearch_anon — anonymizing proxy (PII→tokens) │
282
+│ mysql-mcp — CoPilot DB (alerts, assets) │
283
+│ copilot-mcp — CoPilot REST API write-back │
284
+│ ollama (optional) — local LLM for sensitive data │
285
+│ mempalace — persistent investigation memory │
286
+└───────────────────────────────────────────────────────┘`
287
</script>