feat: add NIS2 landing page, roadmap page, and compliance section
- New /nis2 page: full Art. 21 mapping with covered/partial/roadmap/n-a tags, evidence-by-trigger breakdown, and roadmap callout - New /roadmap page: planned and under-consideration items, NIS2-tagged items highlighted with monospace badge - Home: new NIS2 section between screenshots and plugin block — Art. 21 mapping list + MockCompliance UI + link to /nis2 - Features: new "Compliance & Audit (NIS2)" section - Nav: Roadmap link added; NIS2 in Docs dropdown - Footer: Roadmap and NIS2 links added - docs/PRODUCT.md: NIS2 evidence foundation as value proposition #9 - docs/PAGES.md: /nis2, /roadmap, and NIS2 home section documented Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
0f6ec6241f
commit
f194c379e4
@@ -13,6 +13,8 @@ structure, and draft copy. Use this as the brief for implementation.
|
||||
| `/features` | Full feature list | P1 |
|
||||
| `/drivers` | Supported devices | P1 |
|
||||
| `/docs/getting-started` | Installation guide | P1 |
|
||||
| `/roadmap` | Roadmap — planned + under consideration | P1 |
|
||||
| `/nis2` | NIS2 landing page — Art. 21 mapping, evidence, roadmap | P1 |
|
||||
| `/docs/architecture` | Technical overview | P2 |
|
||||
| `/plugins` | Plugin system | P2 |
|
||||
|
||||
@@ -147,6 +149,33 @@ Each badge uses the `Driver / Integration Badge` component from DESIGN.md.
|
||||
|
||||
---
|
||||
|
||||
### Section 5b — NIS2
|
||||
|
||||
**Purpose:** Hook for organizations evaluating netOrk in a NIS2 context.
|
||||
|
||||
**Layout:** Left column — label + Art. 21 mapping list. Right column — mock compliance overview UI.
|
||||
|
||||
**Label (eyebrow):** `NIS2 · Art. 21` (sky-500, uppercase, tracking-widest)
|
||||
|
||||
**Heading:** `Evidence, not paperwork.`
|
||||
|
||||
**Copy:**
|
||||
```
|
||||
NIS2 Art. 21 mandates asset inventory, patch management, access control,
|
||||
and audit trails as baseline technical measures. netOrk doesn't bolt on a
|
||||
compliance layer — these are its day-to-day outputs.
|
||||
```
|
||||
|
||||
**Art. 21 mapping (4 rows, icon = monospace article ref in sky-500):**
|
||||
- Art. 21 (2e) → Patch & vulnerability management — Per-device update status, Wazuh CVE counts by severity
|
||||
- Art. 21 (2h) → Asset management & access control — Full device inventory, RBAC with four roles, complete audit log
|
||||
- Art. 21 (2a) → Risk analysis baseline — Config drift detection, SNMP health metrics, security agent coverage
|
||||
- Art. 21 (2b) → Incident detection — Wazuh alert history, CrowdSec decisions, Graylog syslog per device
|
||||
|
||||
**Mock UI (right column):** `MockCompliance` — per-site checklist with ✓/⚠ rows, each showing label + detail stat. Label: `netork.local / compliance / HQ`.
|
||||
|
||||
---
|
||||
|
||||
### Section 6 — Plugin System (brief)
|
||||
|
||||
**Purpose:** Signal extensibility without going deep.
|
||||
@@ -285,6 +314,43 @@ feature items as a clean list with `text-slate-400` body.
|
||||
|
||||
---
|
||||
|
||||
## `/roadmap` — Roadmap
|
||||
|
||||
**Purpose:** Show what's being built and what's under consideration. Signal NIS2 investment clearly.
|
||||
|
||||
**Layout:** Page header + two vertical groups ("Planned" / "Under consideration"), each a list of items.
|
||||
|
||||
**NIS2 badge:** `NIS2` monospace tag (sky-500/10 bg, sky-400 text, sky-500/20 border) inline next to item title.
|
||||
|
||||
**Intro copy:**
|
||||
```
|
||||
What's being built and what's being evaluated. Items tagged NIS2 directly
|
||||
address NIS2 Art. 21 technical baseline requirements.
|
||||
```
|
||||
|
||||
**Planned items (NIS2-tagged):**
|
||||
- CVE tracking per device — NVD / OSV cross-reference
|
||||
- Configuration backup & versioning — git-backed snapshots, change detection
|
||||
- Compliance dashboard — per-site Art. 21 checklist view
|
||||
- Audit log export — PDF / CSV with filters
|
||||
|
||||
**Planned items (general):**
|
||||
- Webhook engine — outbound events with HMAC signing
|
||||
- Live job log streaming — WebSocket for all long-running tasks
|
||||
- NetBox sync — manual trigger + status view
|
||||
|
||||
**Under consideration (NIS2-tagged):**
|
||||
- Incident workflow — structured record + NIS2 Art. 23 Fristen-Tracker
|
||||
- EOL tracking — endoflife.date integration for firmware / OS
|
||||
- MFA (TOTP) — second factor for netOrk logins
|
||||
|
||||
**Under consideration (general):**
|
||||
- mDNS scanner — media device discovery
|
||||
- Prometheus + Grafana — metrics and dashboards
|
||||
- Kubernetes Helm chart
|
||||
|
||||
---
|
||||
|
||||
## `/docs/architecture` — Technical Overview
|
||||
|
||||
**Purpose:** Give engineers the mental model before they look at code.
|
||||
|
||||
@@ -65,6 +65,11 @@ hardware and want operational visibility beyond what consumer dashboards offer.
|
||||
8. **Self-hosted, no SaaS** — Runs in Docker Compose. Your data stays on your
|
||||
infrastructure. No telemetry, no cloud dependency.
|
||||
|
||||
9. **NIS2 evidence foundation** — NIS2 Art. 21 mandates asset inventory, patch
|
||||
management, access control, and audit trails. netOrk produces all of these as
|
||||
day-to-day operational outputs: full device inventory, per-device update status,
|
||||
Wazuh CVE tracking, RBAC, config drift detection, and a complete audit log.
|
||||
|
||||
---
|
||||
|
||||
## Feature List
|
||||
|
||||
@@ -5,6 +5,8 @@ import Home from './pages/Home'
|
||||
import Features from './pages/Features'
|
||||
import Drivers from './pages/Drivers'
|
||||
import GettingStarted from './pages/GettingStarted'
|
||||
import Roadmap from './pages/Roadmap'
|
||||
import Nis2 from './pages/Nis2'
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -17,6 +19,8 @@ export default function App() {
|
||||
<Route path="/features" element={<Features />} />
|
||||
<Route path="/drivers" element={<Drivers />} />
|
||||
<Route path="/docs/getting-started" element={<GettingStarted />} />
|
||||
<Route path="/roadmap" element={<Roadmap />} />
|
||||
<Route path="/nis2" element={<Nis2 />} />
|
||||
</Routes>
|
||||
</main>
|
||||
<Footer />
|
||||
|
||||
@@ -22,6 +22,7 @@ export default function Footer() {
|
||||
<li><Link to="/features" className="text-slate-500 hover:text-slate-100 transition-colors">Features</Link></li>
|
||||
<li><Link to="/drivers" className="text-slate-500 hover:text-slate-100 transition-colors">Drivers</Link></li>
|
||||
<li><Link to="/plugins" className="text-slate-500 hover:text-slate-100 transition-colors">Plugins</Link></li>
|
||||
<li><Link to="/roadmap" className="text-slate-500 hover:text-slate-100 transition-colors">Roadmap</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
@@ -30,6 +31,7 @@ export default function Footer() {
|
||||
<li><Link to="/docs/getting-started" className="text-slate-500 hover:text-slate-100 transition-colors">Getting Started</Link></li>
|
||||
<li><Link to="/docs/architecture" className="text-slate-500 hover:text-slate-100 transition-colors">Architecture</Link></li>
|
||||
<li><span className="text-slate-600">Changelog</span></li>
|
||||
<li><Link to="/nis2" className="text-slate-500 hover:text-slate-100 transition-colors">NIS2</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
+12
-1
@@ -28,7 +28,7 @@ export default function Nav() {
|
||||
: 'text-slate-400 hover:text-slate-100'
|
||||
}`
|
||||
|
||||
const isDocsActive = location.pathname.startsWith('/docs')
|
||||
const isDocsActive = location.pathname.startsWith('/docs') || location.pathname === '/nis2'
|
||||
|
||||
return (
|
||||
<nav className="sticky top-0 z-10 bg-slate-900/80 backdrop-blur border-b border-slate-800">
|
||||
@@ -74,6 +74,13 @@ export default function Nav() {
|
||||
>
|
||||
Architecture
|
||||
</Link>
|
||||
<div className="my-1 border-t border-slate-800" />
|
||||
<Link
|
||||
to="/nis2"
|
||||
className="block px-4 py-2 text-sm text-slate-400 hover:text-slate-100 hover:bg-slate-800 transition-colors"
|
||||
>
|
||||
NIS2
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -82,6 +89,10 @@ export default function Nav() {
|
||||
Plugins
|
||||
</Link>
|
||||
|
||||
<Link to="/roadmap" className={linkCls('/roadmap')}>
|
||||
Roadmap
|
||||
</Link>
|
||||
|
||||
<div className="ml-auto">
|
||||
<Link
|
||||
to="/docs/getting-started"
|
||||
|
||||
@@ -127,6 +127,19 @@ const SECTIONS = [
|
||||
'VM interfaces and disks for Proxmox hosts',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Compliance & Audit (NIS2)',
|
||||
items: [
|
||||
'Full audit log of all orchestration actions — who changed what, when (Art. 21 (2h))',
|
||||
'RBAC with four built-in roles and custom permission sets — access control evidence',
|
||||
'Per-device patch status and installed package list — patch management baseline (Art. 21 (2e))',
|
||||
'Wazuh CVE counts by severity (critical / high / medium) linked to each device record',
|
||||
'Config drift tracking: desired state vs. polled state — detect unauthorized changes',
|
||||
'Security agent coverage report: which devices have Wazuh, Graylog, CrowdSec active',
|
||||
'SNMP health metrics as continuous monitoring baseline (Art. 21 (2a))',
|
||||
'Incident-relevant data per device: Wazuh alerts, CrowdSec decisions, syslog forwarding status (Art. 21 (2b))',
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Developer Experience',
|
||||
items: [
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
ChartBarIcon,
|
||||
WrenchScrewdriverIcon,
|
||||
PuzzlePieceIcon,
|
||||
ShieldCheckIcon,
|
||||
} from '@heroicons/react/24/outline'
|
||||
|
||||
const DRIVERS = [
|
||||
@@ -163,6 +164,38 @@ function MockVlans() {
|
||||
)
|
||||
}
|
||||
|
||||
function MockCompliance() {
|
||||
const checks = [
|
||||
{ label: 'Asset inventory', detail: '18 / 18 devices tracked', ok: true },
|
||||
{ label: 'Patch status', detail: 'All devices polled < 60 min', ok: true },
|
||||
{ label: 'Wazuh agents', detail: '15 / 18 agents active', ok: false },
|
||||
{ label: 'Syslog forwarding', detail: '14 / 18 forwarding to Graylog', ok: false },
|
||||
{ label: 'Config drift', detail: '0 drifted devices', ok: true },
|
||||
{ label: 'Audit log', detail: '23 actions logged (24 h)', ok: true },
|
||||
]
|
||||
return (
|
||||
<div className="bg-slate-950 p-4">
|
||||
<div className="mb-3 flex items-center justify-between">
|
||||
<span className="text-xs font-semibold text-slate-100">Compliance overview — HQ</span>
|
||||
<span className="text-xs font-mono text-sky-500">Art. 21 NIS2</span>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
{checks.map((c) => (
|
||||
<div key={c.label} className="flex items-center justify-between rounded-lg border border-slate-800 bg-slate-900 px-3 py-2">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<span className={`text-xs font-semibold w-3 ${c.ok ? 'text-green-400' : 'text-yellow-400'}`}>
|
||||
{c.ok ? '✓' : '⚠'}
|
||||
</span>
|
||||
<span className="text-xs text-slate-300">{c.label}</span>
|
||||
</div>
|
||||
<span className="text-xs text-slate-500">{c.detail}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function MockSecurity() {
|
||||
return (
|
||||
<div className="bg-slate-950 p-4">
|
||||
@@ -384,6 +417,68 @@ export default function Home() {
|
||||
|
||||
<div className="border-t border-slate-800" />
|
||||
|
||||
{/* 5b — NIS2 */}
|
||||
<section className="py-24">
|
||||
<div className="max-w-7xl mx-auto px-6">
|
||||
<div className="grid md:grid-cols-2 gap-12 items-center">
|
||||
<div>
|
||||
<p className="text-xs font-semibold tracking-widest uppercase text-sky-500 mb-3">NIS2 · Art. 21</p>
|
||||
<h2 className="text-2xl md:text-3xl font-bold text-slate-100 mb-4">
|
||||
Evidence, not paperwork.
|
||||
</h2>
|
||||
<p className="text-base text-slate-400 leading-relaxed mb-8">
|
||||
NIS2 Art. 21 mandates asset inventory, patch management, access
|
||||
control, and audit trails as baseline technical measures. netOrk
|
||||
doesn't bolt on a compliance layer — these are its day-to-day outputs.
|
||||
</p>
|
||||
<div className="mb-8">
|
||||
<Link to="/nis2" className="inline-flex items-center gap-2 text-sky-400 hover:text-sky-300 transition-colors text-sm font-medium">
|
||||
<ShieldCheckIcon className="h-4 w-4" />
|
||||
Full Art. 21 mapping →
|
||||
</Link>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{
|
||||
art: 'Art. 21 (2e)',
|
||||
label: 'Patch & vulnerability management',
|
||||
detail: 'Per-device update status, Wazuh CVE counts by severity',
|
||||
},
|
||||
{
|
||||
art: 'Art. 21 (2h)',
|
||||
label: 'Asset management & access control',
|
||||
detail: 'Full device inventory, RBAC with four roles, complete audit log',
|
||||
},
|
||||
{
|
||||
art: 'Art. 21 (2a)',
|
||||
label: 'Risk analysis baseline',
|
||||
detail: 'Config drift detection, SNMP health metrics, security agent coverage',
|
||||
},
|
||||
{
|
||||
art: 'Art. 21 (2b)',
|
||||
label: 'Incident detection',
|
||||
detail: 'Wazuh alert history, CrowdSec decisions, Graylog syslog per device',
|
||||
},
|
||||
].map((m) => (
|
||||
<div key={m.art} className="flex gap-4">
|
||||
<span className="mt-0.5 shrink-0 w-28 text-xs font-mono text-sky-500">{m.art}</span>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">{m.label}</p>
|
||||
<p className="text-xs text-slate-500 mt-0.5">{m.detail}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<BrowserFrame label="netork.local / compliance / HQ">
|
||||
<MockCompliance />
|
||||
</BrowserFrame>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="border-t border-slate-800" />
|
||||
|
||||
{/* 6 — Plugin System */}
|
||||
<section className="py-24">
|
||||
<div className="max-w-7xl mx-auto px-6">
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { ShieldCheckIcon } from '@heroicons/react/24/outline'
|
||||
|
||||
type Coverage = 'covered' | 'partial' | 'roadmap' | 'na'
|
||||
|
||||
type Requirement = {
|
||||
article: string
|
||||
label: string
|
||||
coverage: Coverage
|
||||
netork: string
|
||||
}
|
||||
|
||||
const REQUIREMENTS: Requirement[] = [
|
||||
{
|
||||
article: 'Art. 21 (2a)',
|
||||
label: 'Risk analysis & information system security policies',
|
||||
coverage: 'partial',
|
||||
netork:
|
||||
'Config drift detection, SNMP health metrics, and security agent coverage across all devices provide a continuous risk baseline. A formal risk register is out of scope for netOrk.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2b)',
|
||||
label: 'Incident handling',
|
||||
coverage: 'partial',
|
||||
netork:
|
||||
'Wazuh alert history, CrowdSec decisions, and Graylog syslog per device surface incidents at the network layer. A structured incident record with NIS2 Art. 23 reporting timers is on the roadmap.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2c)',
|
||||
label: 'Business continuity, backup management, disaster recovery',
|
||||
coverage: 'roadmap',
|
||||
netork:
|
||||
'Git-backed configuration snapshots (on roadmap) provide config-level recovery. Backup monitoring for individual devices is not yet implemented.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2d)',
|
||||
label: 'Supply chain security',
|
||||
coverage: 'partial',
|
||||
netork:
|
||||
'Vendor, model, firmware, and OS version are tracked per device after every poll. EOL tracking against endoflife.date is on the roadmap to flag unsupported software.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2e)',
|
||||
label: 'Vulnerability handling in acquisition, development & maintenance',
|
||||
coverage: 'covered',
|
||||
netork:
|
||||
'Per-device update status and installed package list tracked on every poll. Wazuh CVE counts by severity (critical / high / medium) linked directly to each device record. CVE cross-reference against NVD/OSV (without Wazuh) is on the roadmap.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2f)',
|
||||
label: 'Assessing effectiveness of cybersecurity measures',
|
||||
coverage: 'partial',
|
||||
netork:
|
||||
'The audit log records all orchestration actions. A per-site compliance dashboard (on roadmap) will aggregate security agent coverage, drift status, and patch metrics into a single view.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2g)',
|
||||
label: 'Basic cyber hygiene & cybersecurity training',
|
||||
coverage: 'na',
|
||||
netork:
|
||||
'Out of scope for a network orchestration platform. Training and hygiene policies are handled at the organizational level.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2h)',
|
||||
label: 'Access control, asset management, human resources security',
|
||||
coverage: 'covered',
|
||||
netork:
|
||||
'Full device inventory maintained automatically via discovery and continuous polling. RBAC with four built-in roles (viewer / operator / engineer / administrator) and custom role combinations. Complete audit log of all orchestration actions.',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2i)',
|
||||
label: 'Multi-factor authentication',
|
||||
coverage: 'roadmap',
|
||||
netork:
|
||||
'TOTP-based MFA for netOrk user accounts is on the roadmap. Current authentication is JWT-based (username + password).',
|
||||
},
|
||||
{
|
||||
article: 'Art. 21 (2j)',
|
||||
label: 'Physical and environmental security',
|
||||
coverage: 'na',
|
||||
netork:
|
||||
'Out of scope. Physical security of the infrastructure hosting netOrk is an organizational and facility concern.',
|
||||
},
|
||||
]
|
||||
|
||||
const EVIDENCE = [
|
||||
{
|
||||
trigger: 'Every device poll',
|
||||
produces: [
|
||||
'Installed package list with versions',
|
||||
'Available update count',
|
||||
'Interface status, ARP table, DHCP leases',
|
||||
'VLAN membership vs. desired state (drift)',
|
||||
'SNMP health metrics (CPU, memory, interface counters)',
|
||||
'Wazuh agent status and CVE counts by severity',
|
||||
'Graylog syslog forwarding status',
|
||||
'CrowdSec decisions and ban counts',
|
||||
],
|
||||
},
|
||||
{
|
||||
trigger: 'Every user action',
|
||||
produces: [
|
||||
'Audit log entry: user, timestamp, resource, action',
|
||||
'Before/after values for configuration changes',
|
||||
],
|
||||
},
|
||||
{
|
||||
trigger: 'On demand',
|
||||
produces: [
|
||||
'Topology graph — network segmentation view',
|
||||
'Subnet browser — IP space coverage',
|
||||
'VLAN matrix — which devices carry which VLANs',
|
||||
'Audit log export to PDF / CSV (roadmap)',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
function CoverageTag({ coverage }: { coverage: Coverage }) {
|
||||
if (coverage === 'covered')
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-green-500/15 text-green-400 border border-green-500/20 whitespace-nowrap">
|
||||
✓ Covered
|
||||
</span>
|
||||
)
|
||||
if (coverage === 'partial')
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-yellow-500/15 text-yellow-400 border border-yellow-500/20 whitespace-nowrap">
|
||||
⚠ Partial
|
||||
</span>
|
||||
)
|
||||
if (coverage === 'roadmap')
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-sky-500/15 text-sky-400 border border-sky-500/20 whitespace-nowrap">
|
||||
→ Roadmap
|
||||
</span>
|
||||
)
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-slate-700/50 text-slate-500 border border-slate-700 whitespace-nowrap">
|
||||
— N/A
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Nis2() {
|
||||
return (
|
||||
<div className="py-16 md:py-24">
|
||||
<div className="max-w-4xl mx-auto px-6">
|
||||
|
||||
{/* Header */}
|
||||
<div className="mb-16">
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-lg bg-sky-600/10">
|
||||
<ShieldCheckIcon className="h-5 w-5 text-sky-400" />
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">
|
||||
NIS2 & netOrk
|
||||
</h1>
|
||||
<p className="text-base text-slate-400 leading-relaxed max-w-2xl">
|
||||
NIS2 Art. 21 defines ten categories of technical and organizational
|
||||
measures. Some of them are directly addressed by what netOrk does
|
||||
every day. This page maps each requirement to netOrk's current
|
||||
capabilities — honestly, including what's partial and what's not
|
||||
applicable.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Art. 21 mapping */}
|
||||
<div className="mb-20">
|
||||
<h2 className="text-xl font-semibold text-slate-200 mb-6 pb-2 border-b border-slate-800">
|
||||
Art. 21 — requirement by requirement
|
||||
</h2>
|
||||
<div className="space-y-0 rounded-xl border border-slate-800 overflow-hidden">
|
||||
{REQUIREMENTS.map((r, i) => (
|
||||
<div
|
||||
key={r.article}
|
||||
className={`p-5 ${i < REQUIREMENTS.length - 1 ? 'border-b border-slate-800' : ''}`}
|
||||
>
|
||||
<div className="flex flex-wrap items-start justify-between gap-3 mb-2">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xs font-mono text-sky-500 shrink-0">{r.article}</span>
|
||||
<span className="text-sm font-medium text-slate-200">{r.label}</span>
|
||||
</div>
|
||||
<CoverageTag coverage={r.coverage} />
|
||||
</div>
|
||||
<p className="text-sm text-slate-500 leading-relaxed pl-0 md:pl-24">{r.netork}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Legend */}
|
||||
<div className="mt-4 flex flex-wrap gap-4 text-xs text-slate-500">
|
||||
<span className="flex items-center gap-1.5"><CoverageTag coverage="covered" /> netOrk covers this today</span>
|
||||
<span className="flex items-center gap-1.5"><CoverageTag coverage="partial" /> partially covered — see description</span>
|
||||
<span className="flex items-center gap-1.5"><CoverageTag coverage="roadmap" /> planned — see roadmap</span>
|
||||
<span className="flex items-center gap-1.5"><CoverageTag coverage="na" /> outside scope of a network management tool</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Evidence produced */}
|
||||
<div className="mb-20">
|
||||
<h2 className="text-xl font-semibold text-slate-200 mb-2 pb-2 border-b border-slate-800">
|
||||
What netOrk produces as evidence
|
||||
</h2>
|
||||
<p className="text-sm text-slate-500 mb-6">
|
||||
NIS2 audits require demonstrable outputs, not just claimed controls. Here's
|
||||
what netOrk generates automatically.
|
||||
</p>
|
||||
<div className="space-y-6">
|
||||
{EVIDENCE.map((e) => (
|
||||
<div key={e.trigger} className="rounded-xl border border-slate-800 bg-slate-900 p-5">
|
||||
<p className="text-xs font-semibold text-sky-500 uppercase tracking-widest mb-3">
|
||||
{e.trigger}
|
||||
</p>
|
||||
<ul className="space-y-1.5">
|
||||
{e.produces.map((item) => (
|
||||
<li key={item} className="flex items-start gap-2 text-sm text-slate-400">
|
||||
<span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-sky-500" />
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Roadmap callout */}
|
||||
<div className="mb-20">
|
||||
<h2 className="text-xl font-semibold text-slate-200 mb-6 pb-2 border-b border-slate-800">
|
||||
What's coming
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{
|
||||
title: 'CVE tracking per device',
|
||||
detail: 'Automatic cross-reference of installed packages against NVD / OSV — no Wazuh agent required.',
|
||||
},
|
||||
{
|
||||
title: 'Configuration backup & versioning',
|
||||
detail: 'Git-backed config snapshots after every poll. Detect unauthorized changes, compare over time.',
|
||||
},
|
||||
{
|
||||
title: 'Compliance dashboard',
|
||||
detail: 'Per-site Art. 21 checklist: asset coverage, patch status, agent deployment, drift, syslog, audit activity.',
|
||||
},
|
||||
{
|
||||
title: 'Audit log export',
|
||||
detail: 'PDF and CSV export filtered by date range, device, user, or action — ready to hand to an auditor.',
|
||||
},
|
||||
{
|
||||
title: 'Incident workflow',
|
||||
detail: 'Structured incident records with NIS2 Art. 23 reporting timers (24 h / 72 h) and external webhook delivery.',
|
||||
},
|
||||
{
|
||||
title: 'EOL tracking',
|
||||
detail: 'Flag devices running end-of-life firmware or OS versions via the endoflife.date API.',
|
||||
},
|
||||
{
|
||||
title: 'MFA (TOTP)',
|
||||
detail: 'Time-based one-time passwords as a second factor for netOrk user accounts (Art. 21 (2i)).',
|
||||
},
|
||||
].map((item) => (
|
||||
<div key={item.title} className="flex gap-4">
|
||||
<div className="mt-2 shrink-0 h-1.5 w-1.5 rounded-full bg-sky-500" />
|
||||
<div>
|
||||
<p className="text-sm font-medium text-slate-200">{item.title}</p>
|
||||
<p className="text-sm text-slate-500 mt-0.5">{item.detail}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-8">
|
||||
<Link to="/roadmap" className="text-sky-400 hover:text-sky-300 transition-colors text-sm font-medium">
|
||||
Full roadmap →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
<div className="rounded-xl border border-slate-800 bg-slate-900 p-8 text-center">
|
||||
<h2 className="text-xl font-semibold text-slate-100 mb-3">
|
||||
Start with the foundation.
|
||||
</h2>
|
||||
<p className="text-sm text-slate-400 leading-relaxed mb-6 max-w-md mx-auto">
|
||||
Asset inventory, continuous polling, drift detection, RBAC, and a full
|
||||
audit log — deployed in one command.
|
||||
</p>
|
||||
<Link
|
||||
to="/docs/getting-started"
|
||||
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg bg-sky-600 hover:bg-sky-500 text-white text-sm font-medium transition-colors"
|
||||
>
|
||||
Get started →
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
type Item = {
|
||||
title: string
|
||||
detail: string
|
||||
nis2?: boolean
|
||||
}
|
||||
|
||||
type Group = {
|
||||
label: string
|
||||
items: Item[]
|
||||
}
|
||||
|
||||
const GROUPS: Group[] = [
|
||||
{
|
||||
label: 'Planned',
|
||||
items: [
|
||||
{
|
||||
title: 'CVE tracking per device',
|
||||
detail:
|
||||
'Cross-reference installed packages and OS versions against NVD / OSV. Surfaces "this device has 3 unpatched CVEs (CVSS ≥ 7)" without leaving netOrk.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'Configuration backup & versioning',
|
||||
detail:
|
||||
'Git-backed config snapshots on every poll. Detect unauthorized changes between snapshots and provide rollback targets.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'Compliance dashboard',
|
||||
detail:
|
||||
'Per-site Art. 21 checklist: asset coverage, patch status, security agent deployment, config drift, syslog forwarding, audit activity — aggregated into a single view.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'Audit log export',
|
||||
detail:
|
||||
'PDF and CSV export of the audit log, filtered by date range, device, user, or action type. For NIS2 audit submissions and internal reviews.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'Webhook engine',
|
||||
detail:
|
||||
'Outbound HTTP webhooks for events: device discovered, config change detected, job failed, alert threshold exceeded. HMAC-SHA256 payload signing. Integrates with n8n, Slack, PagerDuty.',
|
||||
},
|
||||
{
|
||||
title: 'Live job log streaming',
|
||||
detail:
|
||||
'WebSocket endpoint for real-time Celery task output in the UI. Currently streamed via SSE for fix-flows; full job log streaming for all long-running operations.',
|
||||
},
|
||||
{
|
||||
title: 'NetBox sync — manual trigger & status view',
|
||||
detail:
|
||||
'POST /api/v1/netbox/sync endpoint with progress feedback and a sync history view in the UI. Currently sync runs automatically; the manual trigger and status are missing.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Under consideration',
|
||||
items: [
|
||||
{
|
||||
title: 'Incident workflow',
|
||||
detail:
|
||||
'Structured incident record tied to devices and security events. Fristen-Tracker for NIS2 Art. 23 reporting windows (24 h early warning, 72 h full notification). Webhook to external ticketing systems.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'EOL tracking for firmware and OS',
|
||||
detail:
|
||||
'Flag devices running end-of-life software via the endoflife.date API. Covers OPNsense, OpenWRT, Debian, Ubuntu, and more — matched to the OS versions netOrk already polls.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'MFA (TOTP) for netOrk login',
|
||||
detail:
|
||||
'Time-based one-time passwords as a second factor for netOrk user accounts. Directly covers NIS2 Art. 21 (2i) MFA requirement for administrative access.',
|
||||
nis2: true,
|
||||
},
|
||||
{
|
||||
title: 'mDNS scanner',
|
||||
detail:
|
||||
'Discover media devices (Apple TV, Chromecast, Sonos) via mDNS/Bonjour without needing a NAPALM driver. Inventory visibility and firewall segmentation suggestions.',
|
||||
},
|
||||
{
|
||||
title: 'Prometheus metrics + Grafana dashboards',
|
||||
detail:
|
||||
'Expose per-device SNMP health metrics as a Prometheus scrape endpoint. Pre-built Grafana dashboard for interface counters, CPU, memory, and poll lag.',
|
||||
},
|
||||
{
|
||||
title: 'Kubernetes Helm chart',
|
||||
detail:
|
||||
'Helm chart for production-grade deployments: horizontal scaling for the API and worker pods, Secrets via Vault Agent Injector, Ingress with TLS termination.',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
function Nis2Badge() {
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 px-1.5 py-0.5 rounded text-xs font-mono font-semibold bg-sky-500/10 text-sky-400 border border-sky-500/20">
|
||||
NIS2
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Roadmap() {
|
||||
return (
|
||||
<div className="py-16 md:py-24">
|
||||
<div className="max-w-4xl mx-auto px-6">
|
||||
<div className="mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-slate-100 mb-4">Roadmap</h1>
|
||||
<p className="text-base text-slate-400 leading-relaxed max-w-xl">
|
||||
What's being built and what's being evaluated. Items tagged{' '}
|
||||
<Nis2Badge /> directly address NIS2 Art. 21 technical baseline requirements.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-14">
|
||||
{GROUPS.map((group) => (
|
||||
<div key={group.label}>
|
||||
<h2 className="text-xl font-semibold text-slate-200 mb-6 pb-2 border-b border-slate-800">
|
||||
{group.label}
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
{group.items.map((item) => (
|
||||
<div key={item.title} className="flex gap-4">
|
||||
<div className="mt-1 shrink-0 h-1.5 w-1.5 rounded-full bg-sky-500 mt-2" />
|
||||
<div>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span className="text-sm font-medium text-slate-200">{item.title}</span>
|
||||
{item.nis2 && <Nis2Badge />}
|
||||
</div>
|
||||
<p className="text-sm text-slate-500 leading-relaxed">{item.detail}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user