AI-native software supply chain security with autonomous remediation.
Scan, reason, decide, dispatch — in one governed pipeline.
- Why Sentinel
- What Sentinel does
- System architecture
- How a scan flows end-to-end
- AI risk enrichment pipeline
- Remediation approval lifecycle
- Data model
- Tech stack
- Feature matrix
- Quickstart (5 minutes)
- Testing & verification
- Deploying to production
- Repo layout
- Development
- Roadmap & status
- Documentation index
- License & sources
| Pain in 2026 | Concrete evidence | Sentinel's answer |
|---|---|---|
| Enterprises can't see their AI/ML supply chain | 62% of security teams have no visibility into where LLMs run | First-class detectors for HuggingFace models, datasets, MCP servers; ML-BOM in CycloneDX 1.6 |
| Regulation is no longer optional | EU Cyber Resilience Act (2027) + US EO 14028 / EO 14144 | Signed SBOMs + attestations in CI; auditable policy engine |
| CVE tools flood teams with low-signal alerts | Thousands of findings → no business context | LLM-powered re-ranking (CVSS × EPSS × license × reachability × fix availability) |
| License compliance across transitive deps is manual | Sonatype 2026 State of Supply Chain | Classifier + 20-license matrix + declarative policies (block AGPL, escalate SSPL, …) |
| Remediation is glue code nobody wants to own | Every team writes its own PR/Jira/Slack bot | Agentic dispatch through n8n — 500+ prebuilt integrations |
- Multi-ecosystem scanning — npm, PyPI, Go modules, Cargo, Maven, containers, HuggingFace models, datasets, and MCP servers (CycloneDX 1.6 + SPDX 3.0 AI profile).
- Business-aware risk scoring — Claude Opus 4.7 reasons over CVSS, EPSS, license risk, transitive flags and fix availability, with a deterministic fallback so the system works offline.
- Vector-indexed provenance — pgvector HNSW answers "what else is affected by something like log4shell?" in milliseconds.
- Agentic remediation — n8n workflows open PRs, file tickets, rotate tokens, or page on-call based on the risk class and your policies.
- Natural-language queries — "what's my exposure to CVE-2024-xxxx?" → instant answer grounded in your live SBOM graph.
- Drift monitoring — every release emits a signed SBOM; Sentinel diffs them so regressions surface before they hit production.
flowchart TB
classDef edge fill:#0b1220,stroke:#6aa2ff,color:#e8f0ff
classDef api fill:#0d1628,stroke:#aee571,color:#eafbd6
classDef worker fill:#1a0f24,stroke:#c86bff,color:#f3e6ff
classDef data fill:#0a1a14,stroke:#26d07c,color:#d2f3e1
classDef ai fill:#1b0d0d,stroke:#ff7676,color:#ffe0e0
classDef auto fill:#121a0c,stroke:#ffa726,color:#ffe9c7
subgraph CLIENTS["👤 Clients"]
WEB["SvelteKit 5 Dashboard<br/>:5173"]:::edge
CLI["sentinel-cli"]:::edge
CI["CI / CD Pipelines"]:::edge
end
subgraph GATEWAY["🌐 API Gateway (Bun + Hono)"]
API["REST + WebSocket<br/>:4000"]:::api
AUTH["JWT auth + RBAC"]:::api
RATE["Rate limit<br/>(Dragonfly)"]:::api
end
subgraph WORKERS["⚙️ Workers"]
SCAN["Go Scanner<br/>:4100"]:::worker
ANLZ["Bun Analyzer<br/>:4200"]:::worker
end
subgraph DATA["💾 Data plane"]
PG[("Postgres 17<br/>+ pgvector")]:::data
DF[("Dragonfly<br/>cache / RL")]:::data
NATS[("NATS JetStream<br/>events")]:::data
S3[("MinIO<br/>artifacts")]:::data
end
subgraph AI["🧠 AI & embeddings"]
CLAUDE["Claude Opus 4.7"]:::ai
EMB["Embeddings<br/>(Voyage / hash)"]:::ai
end
subgraph AUTO["🤖 Automation"]
N8N["n8n<br/>:5679"]:::auto
GH["GitHub / Jira / Slack / PagerDuty"]:::auto
end
WEB -- "HTTPS + WS" --> API
CLI -- "HTTPS" --> API
CI -- "HTTPS" --> API
API --> AUTH --> RATE
API -- "/v1/scan" --> SCAN
API -- "publish" --> NATS
API -- "SELECT / HNSW" --> PG
API -- "rate counters" --> DF
NATS -- "vuln.discovered" --> ANLZ
ANLZ -- "prompt + JSON" --> CLAUDE
ANLZ -- "embed()" --> EMB
ANLZ -- "UPDATE ai_risk_score" --> PG
ANLZ -- "INSERT proposed" --> PG
SCAN -- "SBOM artifact" --> S3
SCAN -- "CycloneDX 1.6" --> API
API -- "webhook" --> N8N
N8N --> GH
What this shows. Five stateless services behind one API gateway, three stateful data services, two optional AI providers, and one pluggable automation layer. Every box is horizontally scalable except the databases; every inter-service hop is observable (OpenTelemetry) and auditable (append-only events table).
sequenceDiagram
autonumber
participant U as User<br/>(Dashboard / CLI / CI)
participant A as API<br/>(Bun + Hono)
participant DB as Postgres<br/>+ pgvector
participant S as Scanner<br/>(Go)
participant N as NATS<br/>JetStream
participant W as Analyzer<br/>(Bun)
participant C as Claude<br/>Opus 4.7
participant NN as n8n
U->>A: POST /v1/scans { projectSlug, workDir }
A->>DB: INSERT scans {status=running, metadata.workDir}
A->>N: publish sentinel.scan.requested
A-->>U: 202 Accepted { scan.id }
A->>S: POST /v1/scan { workDir }
S->>S: walk tree · match detectors (npm · pypi · go · cargo · maven · ML-BOM · MCP)
S->>S: resolve advisories (offline catalog / OSV)
S->>S: emit CycloneDX 1.6 JSON
S-->>A: { components[], vulnerabilities[], sbomContent }
A->>A: embed every component (hash / Voyage)
A->>DB: INSERT components · vulnerabilities · baseline ai_risk_score
A->>N: publish sentinel.scan.completed
N-->>U: WebSocket: scan.completed
W->>DB: SELECT new vulnerabilities
W->>C: analyze risk (system prompt cached)
C-->>W: { ai_risk_score, exploitability, business_impact, reasoning }
W->>DB: UPDATE vulnerability enrichment
W->>C: propose remediation
C-->>W: { kind, parameters, requires_approval }
W->>DB: INSERT remediations {state=proposed}
W->>N: publish sentinel.remediation.proposed
U->>A: POST /v1/remediations/:id/approve
A->>DB: UPDATE remediations {state=queued}
A->>NN: POST /webhook/sentinel-<kind>
NN-->>A: { executionId }
A->>DB: UPDATE remediations {state=dispatched}
NN->>NN: open PR / file issue / page on-call
Every vulnerability goes through a two-stage pipeline. The deterministic baseline always runs; the LLM stage is optional.
flowchart LR
subgraph BASELINE["⚙️ Deterministic baseline (always on)"]
direction TB
CVSS[CVSS v3.1] --> FORMULA
EPSS[EPSS probability] --> FORMULA
LIC[License risk tier] --> FORMULA
TR[Transitive flag] --> FORMULA
FIX[Fix available?] --> FORMULA
FORMULA["Weighted blend<br/>0.6·CVSS·10 + 0.4·severity<br/>× EPSS × license × fix"]
FORMULA --> B0["baseline 0–100"]
end
subgraph LLM["🧠 LLM refinement (optional)"]
direction TB
VULN[Advisory + details]
CTX[Component context]
PRO[Project context]
VULN --> PROMPT
CTX --> PROMPT
PRO --> PROMPT
PROMPT["System prompt<br/>(prompt-cached)"]
PROMPT --> CLAUDE[Claude Opus 4.7]
CLAUDE --> ZOD["Zod-validated JSON<br/>{risk, exploitability,<br/>business_impact, reasoning}"]
end
B0 -.floor.-> DECIDE
ZOD -.refine.-> DECIDE
DECIDE["max(baseline, ai_score)<br/>(LLM can raise, never drop<br/>below the deterministic floor)"]
DECIDE --> FINAL["ai_risk_score 0–100<br/>+ reasoning text<br/>+ exploitability class<br/>+ business_impact tier"]
style DECIDE fill:#0d1628,stroke:#aee571,color:#eafbd6
style FINAL fill:#0a1a14,stroke:#26d07c,color:#d2f3e1
Safety property. The LLM can only raise the score, never drop it below the deterministic floor. A compromised or prompt-injected model cannot mark a critical CVE as low-risk (docs/AI_SECURITY.md).
stateDiagram-v2
[*] --> proposed : analyzer proposes kind+params
proposed --> queued : human approves
proposed --> suppressed : analyst overrides
queued --> dispatched : POST n8n webhook OK
queued --> failed : n8n/network error
dispatched --> succeeded : n8n reports 2xx + outcome
dispatched --> failed : n8n reports error
dispatched --> rolled_back : human revokes
failed --> proposed : retry after fix
succeeded --> [*]
suppressed --> [*]
note right of proposed
state chip in UI: brand green
"Approve & dispatch" button
end note
note right of dispatched
API records n8n executionId
for audit + post-mortem
end note
Approval by default, autonomy by policy. Every remediation starts in proposed; a human clicks Approve to advance. Policies can mark specific kinds (e.g. notify_slack for low-severity info) as auto-approved.
erDiagram
PROJECTS ||--o{ SCANS : "has"
SCANS ||--o{ COMPONENTS : "discovered"
SCANS ||--o{ VULNERABILITIES : "found"
COMPONENTS ||--o{ VULNERABILITIES : "affects"
VULNERABILITIES ||--o{ REMEDIATIONS : "proposes"
POLICIES }o--o{ VULNERABILITIES : "evaluates"
SCANS ||--o{ EVENTS : "emits"
PROJECTS {
uuid id PK
text slug UK
text name
text repo_url
text default_branch
text[] tags
jsonb metadata
timestamptz created_at
}
SCANS {
uuid id PK
uuid project_id FK
enum status
enum kind
int component_count
int vuln_count
int risk_score
text sbom_s3_key
jsonb metadata
timestamptz started_at
timestamptz completed_at
}
COMPONENTS {
uuid id PK
uuid scan_id FK
enum ecosystem
text name
text version
text purl UK
text license
enum license_risk
boolean is_transitive
vector embedding "HNSW index"
}
VULNERABILITIES {
uuid id PK
uuid component_id FK
text advisory_id
enum severity
real cvss_score
real epss_score
int ai_risk_score
text ai_reasoning
enum state
text[] fixed_versions
}
REMEDIATIONS {
uuid id PK
uuid vulnerability_id FK
enum kind
enum state
jsonb parameters
text workflow_id
text execution_id
timestamptz approved_at
}
POLICIES {
uuid id PK
text slug UK
text name
boolean enabled
jsonb rules
text[] tags
}
Every arrow is a FOREIGN KEY ... ON DELETE CASCADE. Every jsonb field has a corresponding Zod schema in packages/shared/src/. pgvector's HNSW index on components.embedding keeps similarity queries sub-millisecond up to hundreds of millions of rows.
| Layer | Tech | Version | Why |
|---|---|---|---|
| API runtime | Bun | 1.3 | ~3× Node's HTTP throughput · native TypeScript · zero build step · Hono on Bun does 130k+ req/s |
| API framework | Hono | 4.12 | Edge-ready (also runs on Cloudflare Workers, Deno) · tiny core, strict TypeScript |
| Scanner | Go | 1.22 | Whole SBOM ecosystem is Go (syft, grype, osv-scanner, Trivy, cosign) · 10 MB static binary |
| Frontend | SvelteKit 5 | 2.8 | Runes for fine-grained reactivity · adapter-node for Bun-served SSR |
| Styling | Tailwind v4 | alpha | CSS-first @theme tokens · OKLCH colour space · no JS config file |
| Store | Tech | Why |
|---|---|---|
| Relational + vectors | Postgres 17 + pgvector | Transactional consistency between components and their embeddings; HNSW is fast enough for hundreds of millions of rows |
| Cache / rate limit | Dragonfly | 25× Redis throughput on the same wire protocol · snapshot-based persistence |
| Events | NATS JetStream | Lightweight at-least-once · cleanly audited per-subject · survives broker restarts |
| Object storage | MinIO | S3-compatible · optional but simplifies artifact capture (SBOM JSON, logs) |
| Component | Tech | Fallback |
|---|---|---|
| Risk reasoning | Claude Opus 4.7 (Anthropic SDK) | computeBaselineRisk — deterministic weighted formula |
| Remediation planning | Claude Opus 4.7 | Rule-based (pr_bump if fix exists, else issue_ticket) |
| NL query planning | Claude Opus 4.7 | Regex router (CVE-* / GHSA-* / "exposure to X") |
| Embeddings | Voyage-3-large (configurable) | hashToVector deterministic L2-normalised hash (works offline) |
Important. Nothing is "trained" — Sentinel is a pure consumer of a hosted LLM. The deterministic fallbacks mean the whole platform runs fully offline with zero external dependencies. See docs/AI_SECURITY.md for OWASP-LLM Top-10 mapping.
| Concern | Library |
|---|---|
| ORM & migrations | Drizzle ORM — zero-overhead, type-safe, serverless-friendly |
| Schema validation | Zod — used everywhere data crosses a boundary |
| LLM output | Claude → extractJson → Zod parse (never blind-trusted) |
| Concern | Tech |
|---|---|
| Workflow engine | n8n — 500+ integrations, self-hostable, visual editor for security team |
| Container | Multi-stage Dockerfiles (Bun-alpine / Go-alpine), non-root, read-only rootfs, dropped caps |
| Orchestration | Docker Compose for local · Kubernetes manifests + Helm chart for prod |
| CI | GitHub Actions — lint, typecheck, Bun tests, Go tests, Postgres integration, 4-image matrix build |
| Security CI | gitleaks · Trivy FS · OSV-Scanner · CodeQL (Go + TS) · Syft SBOM + actions/attest-sbom |
| Release | Signed multi-arch images, cosign provenance + SBOM attestation |
| Feature | Status | Where |
|---|---|---|
| npm / pypi / go / cargo / maven detectors | ✅ Shipping | apps/scanner/internal/scan/detectors*.go |
| HuggingFace model / dataset detector | ✅ Shipping | detectors.go::mlModelDetector |
MCP server detector (.mcp.json) |
✅ Shipping | detectors.go::mcpDetector |
| CycloneDX 1.6 SBOM output | ✅ Shipping | cyclonedx.go |
| SPDX 3.0 output | 🟡 Roadmap v0.2 | — |
| Deterministic baseline risk | ✅ Shipping | packages/shared/src/risk.ts |
| Claude-refined risk score | ✅ Shipping | packages/ai/src/risk.ts |
| pgvector semantic search | ✅ Shipping | apps/api/src/routes/search.ts |
| Natural-language query planner | ✅ Shipping | apps/api/src/routes/nl-query.ts |
| Declarative policy engine | ✅ Shipping | packages/shared/src/policy.ts |
Policy dry-run (/v1/policy-eval) |
✅ Shipping | apps/api/src/routes/policy-eval.ts |
| Full per-scan policy audit | ✅ Shipping | policy-eval.ts::/scan |
| n8n workflow dispatch | ✅ Shipping | apps/api/src/services/n8n.ts |
| Live WebSocket activity feed | ✅ Shipping | apps/api/src/services/ws-hub.ts |
| Drift diff (CLI + API) | ✅ Shipping | apps/cli/src/commands/diff.ts |
sentinel-cli scan / diff / export |
✅ Shipping | apps/cli/ |
| Helm chart + K8s manifests | ✅ Shipping | infra/helm/ · infra/k8s/ |
| OIDC / SAML SSO | 🟡 Roadmap v0.3 | — |
| Tenant-scoped RBAC + audit export | 🟡 Roadmap v0.3 | — |
| Live OSV mirror (replacing built-in catalog) | 🟡 Roadmap v0.2 | — |
✅ = shipping and in CI · 🟡 = planned · see docs/ROADMAP.md.
Prerequisites: Docker 24+, Bun 1.3, (optional) an Anthropic API key.
# 1. Clone and configure
git clone https://github.com/theNeuralHorizon/sentinel
cd sentinel
cp .env.example .env
# Optional: add ANTHROPIC_API_KEY=sk-ant-... to .env
# 2. Bring up the full stack (Postgres, Dragonfly, NATS, MinIO, n8n, scanner, analyzer, api, web, otel)
docker compose up -d
# 3. Apply the schema (first run only) + seed demo data
docker compose exec -T postgres psql -U sentinel -d sentinel \
< packages/db/migrations/0000_init.sql
docker compose exec -T api bun run //app/scripts/seed.ts
# 4. Verify the whole stack end-to-end (18 live assertions)
bun run scripts/verify.ts
# 5. Open the dashboard
open http://localhost:5173You should see a populated dashboard with 3 projects, 4 real CVEs, an AI supply chain card tracking models + MCP servers, and a pulsing live activity feed.
Full walkthrough: docs/QUICKSTART.md. Demo script: docs/DEMO.md.
Sentinel ships three layers of verification. All three must pass before a PR can merge.
flowchart LR
classDef unit fill:#0a1a14,stroke:#26d07c,color:#d2f3e1
classDef int fill:#0d1628,stroke:#aee571,color:#eafbd6
classDef e2e fill:#1b0d0d,stroke:#ff7676,color:#ffe0e0
U1["Unit · 55 Bun tests<br/>bun test"]:::unit
U2["Unit · 8 Go tests<br/>go test ./..."]:::unit
U3["Typecheck · strict<br/>bun x tsc --noEmit"]:::unit
I1["Integration · Postgres<br/>apply 0000_init.sql<br/>→ seed.ts"]:::int
I2["Build matrix · 4 images<br/>docker buildx"]:::int
E1["Live verifier · 18 assertions<br/>bun run scripts/verify.ts"]:::e2e
U1 --> U3
U2 --> I1
U3 --> I1
I1 --> I2
I2 --> E1
bun test # 55 Bun tests
cd apps/scanner && go test ./... # 8 Go tests
(cd apps/api && bun x tsc --noEmit) # strict typecheckbun run scripts/verify.tsPrints a coloured table of 18 assertions covering liveness, auth, data plane, risk engine, policy engine, pgvector similarity, NL query routing and scanner reachability. Exits non-zero on any failure — drop-in for deploy gates.
ci.yml— lint + typecheck + unit tests + integration (live Postgres service) + 4-image build matrixsecurity.yml— gitleaks + Trivy FS + OSV-Scanner + CodeQL (Go + TS/JS) + SBOM attestationrelease.yml— onv*.*.*tags: build 4 images, push to GHCR with cosign provenance + SBOM, cut GitHub release with auto-generated notes
flowchart LR
DEV["git tag v0.x.0"] --> RELEASE
RELEASE["release.yml<br/>Buildx matrix"] --> GHCR[("ghcr.io/<org>/sentinel-*")]
GHCR --> HELM
HELM["helm install sentinel<br/>./infra/helm/sentinel"] --> K8S["Kubernetes"]
K8S --> ING["Ingress<br/>(cert-manager)"]
K8S --> HPA["HPA<br/>2–10 replicas · 70% CPU"]
K8S --> PG["Postgres StatefulSet<br/>+ pgvector"]
K8S --> NATSC["NATS StatefulSet"]
K8S --> DFC["Dragonfly Deployment"]
style GHCR fill:#0d1628,stroke:#aee571,color:#eafbd6
style K8S fill:#0a1a14,stroke:#26d07c,color:#d2f3e1
Every image ships with cosign provenance + SBOM attestation. See docs/DEPLOYMENT.md for air-gapped deploys, backup scripts, and the production hardening checklist.
sentinel/
├── apps/
│ ├── api/ Bun + Hono gateway — REST + WebSocket, JWT auth, rate limit
│ ├── analyzer/ Bun worker — Claude-powered risk + remediation planner
│ ├── scanner/ Go service — multi-ecosystem SBOM generation
│ ├── cli/ Bun CLI — sentinel-cli scan | diff | export
│ └── web/ SvelteKit 5 + Tailwind v4 — live dashboard
├── packages/
│ ├── db/ Drizzle schema + migrations
│ ├── shared/ Zod schemas · risk formula · license matrix · purl
│ └── ai/ Claude SDK wrapper · prompts · embedders
├── infra/
│ ├── docker/ Dockerfiles · compose overrides · otel-collector config
│ ├── k8s/ Kustomize manifests (namespace, statefulset, deployment, ingress, HPA)
│ ├── helm/ Helm chart (Chart.yaml, values.yaml, templates/)
│ └── n8n/ Remediation workflow templates (pr-bump, issue-ticket, notify-slack, escalate-oncall)
├── .github/
│ └── workflows/ ci.yml · security.yml · release.yml + Dependabot
├── docs/ 12 markdown docs (architecture, API, policies, deploy, AI-security, …)
├── scripts/ seed.ts · verify.ts · smoke.sh
├── docker-compose.yml
├── CLAUDE.md Guidance for AI agents contributing
└── README.md
# Install everything (workspace-aware)
bun install
# Run each service in its own terminal
bun --cwd apps/api dev # API on :4000
bun --cwd apps/analyzer dev # Analyzer on :4200
bun --cwd apps/web dev # Web on :5173
cd apps/scanner && go run ./cmd/scanner # Go scanner on :4100Preferred loop is HMR on the web + Docker for everything else: docker compose up -d postgres dragonfly nats minio n8n otel-collector scanner analyzer api then bun --cwd apps/web dev locally.
Agent contributions: see CLAUDE.md for hard rules (don't bypass JWT, update all 4 enum locations together, etc.) and CONTRIBUTING.md for the human version.
- v0.1.x (now) — everything above, shipping with 63 tests + full CI
- v0.2 — syft library integration · Cargo/Maven/container scanners · live OSV mirror · Voyage-3 embedder · SPDX 3.0 export
- v0.3 — OIDC/SAML · multi-tenant RBAC · audit log export (SIEM-ready) · Slack app with interactive approvals
- v0.4 — confidence-gated auto-dispatch · outcome learning · drift budgets
Full detail in docs/ROADMAP.md. Everything we deliberately chose not to build is listed there too.
| Doc | What it covers |
|---|---|
| QUICKSTART | 5-minute local bring-up |
| ARCHITECTURE | Every service, every data flow, every design decision |
| API | Full REST + WebSocket reference |
| POLICIES | Authoring declarative governance rules |
| DEPLOYMENT | Kubernetes, Helm, hardening, backups, air-gapped |
| DEPLOY_VERCEL_RENDER | One-click public-cloud deploy via render.yaml + vercel.json |
| AI_SECURITY | OWASP LLM Top-10 coverage + threat model |
| BENCHMARKS | Numbers + reproduction commands |
| FAQ | Stack choices, ownership, compliance, performance |
| RESEARCH | The 2026 industry context driving this |
| ROADMAP | What's next, what's deliberately out of scope |
| DEMO | 10-minute buyer walkthrough script |
| CLAUDE.md | Guidance for AI agents working on this repo |
| CONTRIBUTING | For human contributors |
| SECURITY | How to report vulnerabilities |
| CHANGELOG | Per-release notes |
Apache-2.0. See LICENSE.
Grounded in the following 2026 industry work:
- Cloudsmith — The 2026 Guide to Software Supply Chain Security: From Static SBOMs to Agentic Governance
- Sonatype — 2026 State of the Software Supply Chain
- OpenSSF — Software Supply Chain Security WG
- Anchore — Syft & Grype
- Netrise — What EO 14028, EU CRA, and NIST CSF 2.0 Mean
- VentureBeat — Seven steps to AI supply chain visibility
- NIST — AI Risk Management Framework (AI-BOM / ML-BOM)
Built by theNeuralHorizon · Powered by Bun, Svelte 5, Postgres 17, pgvector, Claude Opus, n8n.