Skip to content

Commit 7bf5851

Browse files
Merge pull request #19 from andreibesleaga/feat-fixes
Audit, verification & hardening — production-grade pass (v1.4.x)
2 parents 6101254 + 01cf9b4 commit 7bf5851

116 files changed

Lines changed: 9276 additions & 2831 deletions

File tree

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: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ PORT=3000
2020
# Service name used in telemetry/traces
2121
SERVICE_NAME=kaiban-worker
2222

23+
# Structured logging (pino). Default output is JSON (production-grade).
24+
# LOG_LEVEL: trace|debug|info|warn|error|fatal|silent (default: info)
25+
# LOG_PRETTY=true → human-readable colourised logs for local dev/demos (needs pino-pretty)
26+
# LOG_LEVEL=info
27+
# LOG_PRETTY=true
28+
2329
# Messaging driver: "bullmq" (default, uses Redis) or "kafka"
2430
MESSAGING_DRIVER=bullmq
2531

@@ -49,6 +55,11 @@ OPENAI_API_KEY=your_openai_api_key_here
4955
# OPENROUTER_API_KEY=your_openrouter_api_key_here
5056
# OPENAI_BASE_URL=
5157
# LLM_MODEL=gpt-4o-mini
58+
# Other LLM providers are also honored if set (passed through to KaibanJS):
59+
# ANTHROPIC_API_KEY=
60+
# GOOGLE_API_KEY=
61+
# MISTRAL_API_KEY=
62+
# GROQ_API_KEY=
5263

5364
# ── Security: mTLS (optional) ──────────────────────────────────
5465
# Paths to TLS certificates for Redis/Kafka mTLS connections
@@ -119,8 +130,10 @@ VALID_HITL_DECISIONS=PUBLISH,REVISE,REJECT,VIEW
119130
# AGENT_ID=writer (writer-node.ts — Atlas, Research Synthesiser)
120131
# AGENT_ID=reviewer (reviewer-node.ts — Sage, AI Ethics & Compliance Officer)
121132
# AGENT_ID=editor (editor-node.ts — Morgan, Chief Research Editor)
122-
# SEARCHER_ID=searcher (searcher-node.ts — Zara; all replicas share this ID by
123-
# default so they merge to one board entry)
133+
# SEARCHER_ID=searcher (searcher-node.ts — Zara; OPTIONAL. If unset, each replica
134+
# auto-assigns a unique id (searcher-0, searcher-1, … via a
135+
# Redis counter) and appears as a distinct board entry. Set
136+
# this only to pin a fixed id.)
124137
#
125138
AGENT_ID=researcher
126139

.github/dependabot.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
version: 2
2+
updates:
3+
# Root package (framework)
4+
- package-ecosystem: npm
5+
directory: "/"
6+
schedule:
7+
interval: weekly
8+
day: monday
9+
open-pull-requests-limit: 10
10+
groups:
11+
production-dependencies:
12+
dependency-type: production
13+
development-dependencies:
14+
dependency-type: development
15+
labels:
16+
- dependencies
17+
18+
# Board UI (separate lockfile)
19+
- package-ecosystem: npm
20+
directory: "/board"
21+
schedule:
22+
interval: weekly
23+
day: monday
24+
open-pull-requests-limit: 10
25+
groups:
26+
board-dependencies:
27+
patterns: ["*"]
28+
labels:
29+
- dependencies
30+
- board
31+
32+
- package-ecosystem: github-actions
33+
directory: "/"
34+
schedule:
35+
interval: weekly
36+
day: monday
37+
labels:
38+
- dependencies
39+
- github-actions

.github/workflows/ci.yml

Lines changed: 104 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
name: CI
22

3+
# Fast quality + security gates on every push/PR. Heavy e2e (Redis/Kafka) and
4+
# chaos/mutation/bench run in nightly.yml. Actions use version tags; Dependabot
5+
# (github-actions) + a follow-up SHA-pin pass harden these further.
6+
37
on:
48
push:
59
branches: [main, develop]
610
pull_request:
7-
branches: [main]
11+
branches: [main, develop]
812

913
concurrency:
1014
group: ${{ github.workflow }}-${{ github.ref }}
1115
cancel-in-progress: true
1216

17+
permissions:
18+
contents: read
19+
1320
jobs:
14-
# ── Gate 1-3: Lint, Typecheck, Unit Tests ─────────────────────────────
1521
quality:
16-
name: Quality Gates (lint / typecheck / coverage)
22+
name: Quality (lint · typecheck · 100% coverage · arch)
1723
runs-on: ubuntu-latest
1824
steps:
1925
- uses: actions/checkout@v4
@@ -22,84 +28,141 @@ jobs:
2228
node-version: "22"
2329
cache: "npm"
2430
- run: npm ci
25-
- name: Gate 1 — Lint (zero errors)
31+
- name: Lint (zero errors)
2632
run: npm run lint
27-
- name: Gate 2 — Type Safety (zero errors)
33+
- name: Typecheck (zero errors)
2834
run: npm run typecheck
29-
- name: Gate 3 — Unit Tests + Coverage (≥99%)
35+
- name: Architecture (no circular imports)
36+
run: npm run lint:arch
37+
- name: API surface gate (api-extractor — fails on undocumented public-API drift)
38+
run: npm run api:check
39+
- name: Unit tests + coverage (enforced 100% of src/**)
3040
run: npm run test:coverage
31-
- name: Gate 6 — Architecture (no circular imports)
32-
run: npx madge --circular src/
3341
- name: Upload coverage report
3442
uses: actions/upload-artifact@v4
3543
if: always()
3644
with:
3745
name: coverage
3846
path: coverage/
3947

40-
# ── Gate 4a: BullMQ E2E (Redis) ───────────────────────────────────────
41-
e2e-bullmq:
42-
name: E2E — BullMQ / Redis
48+
board:
49+
name: Board UI (typecheck · build · tests)
4350
runs-on: ubuntu-latest
51+
defaults:
52+
run:
53+
working-directory: board
4454
steps:
4555
- uses: actions/checkout@v4
4656
- uses: actions/setup-node@v4
4757
with:
4858
node-version: "22"
4959
cache: "npm"
60+
cache-dependency-path: board/package-lock.json
5061
- run: npm ci
51-
- name: E2E Tests — BullMQ (Redis)
52-
run: npm run test:e2e
53-
env:
54-
REDIS_URL: redis://localhost:6379
55-
AGENT_IDS: test-agent
56-
REDIS_PASSWORD: ""
62+
# `build` is `tsc --noEmit && vite build` — typechecks then bundles.
63+
- run: npm run build
64+
- run: npm test
5765

58-
# ── Gate 4b: Kafka E2E ────────────────────────────────────────────────
59-
e2e-kafka:
60-
name: E2E — Kafka
66+
security:
67+
name: Security (audit · secrets · SBOM · OSV)
6168
runs-on: ubuntu-latest
69+
permissions:
70+
contents: read
71+
security-events: write
6272
steps:
6373
- uses: actions/checkout@v4
74+
with:
75+
fetch-depth: 0
6476
- uses: actions/setup-node@v4
6577
with:
6678
node-version: "22"
6779
cache: "npm"
6880
- run: npm ci
69-
- name: E2E Tests — Kafka
70-
run: npm run test:e2e:kafka
81+
- name: Dependency audit (fail on HIGH+; moderates triaged in SECURITY.md)
82+
run: npm audit --audit-level=high
83+
- name: Generate CycloneDX 1.6 SBOM
84+
run: npx --yes @cyclonedx/cyclonedx-npm@latest --output-format JSON --spec-version 1.6 --output-file sbom.json
85+
- name: Upload SBOM
86+
uses: actions/upload-artifact@v4
87+
with:
88+
name: sbom-cyclonedx
89+
path: sbom.json
90+
- name: Secret scan (gitleaks)
91+
uses: gitleaks/gitleaks-action@v2
7192
env:
72-
KAFKA_BROKERS: localhost:9092
73-
AGENT_IDS: test-agent
74-
REDIS_PASSWORD: ""
93+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
94+
- name: OSV-Scanner
95+
uses: google/osv-scanner-action/osv-scanner-action@v2.2.2
96+
continue-on-error: true
97+
with:
98+
scan-args: |-
99+
--lockfile=package-lock.json
100+
--format=sarif
101+
--output=osv.sarif
102+
- name: Upload OSV SARIF
103+
if: always()
104+
uses: github/codeql-action/upload-sarif@v3
105+
with:
106+
sarif_file: osv.sarif
107+
category: osv-scanner
75108

76-
# ── Gate 5: Security Audit ────────────────────────────────────────────
77-
security:
78-
name: Security Audit
109+
codeql:
110+
name: CodeQL (JS/TS static analysis)
79111
runs-on: ubuntu-latest
112+
permissions:
113+
contents: read
114+
security-events: write
80115
steps:
81116
- uses: actions/checkout@v4
82-
- uses: actions/setup-node@v4
117+
- uses: github/codeql-action/init@v3
83118
with:
84-
node-version: "22"
85-
cache: "npm"
86-
- run: npm ci
87-
- name: Gate 5 — Dependency Audit
88-
run: |
89-
npm audit --audit-level=moderate || echo "::warning::Audit issues found - see output above (known: kaibanjs transitive CVEs)"
119+
languages: javascript-typescript
120+
- uses: github/codeql-action/analyze@v3
90121

91-
# ── Gate 4c: Docker Build ─────────────────────────────────────────────
92122
docker:
93-
name: Docker Build
123+
name: Docker build + image scan (Trivy)
94124
runs-on: ubuntu-latest
95125
needs: [quality]
126+
permissions:
127+
contents: read
128+
security-events: write
96129
steps:
97130
- uses: actions/checkout@v4
98-
- name: Set up Docker Buildx
99-
uses: docker/setup-buildx-action@v3
100-
- name: Build Docker image
101-
uses: docker/build-push-action@v5
131+
- uses: docker/setup-buildx-action@v3
132+
- uses: docker/build-push-action@v6
102133
with:
103134
context: .
104135
push: false
136+
load: true # load into the local daemon so Trivy can scan the built image
105137
tags: kaiban-distributed:ci-${{ github.sha }}
138+
# Blocking gate: fail the build on a FIXABLE CRITICAL/HIGH OS or library CVE
139+
# in the runtime image (unfixed base-image CVEs are reported but don't block).
140+
- name: Scan image (Trivy — gate on fixable CRITICAL/HIGH)
141+
uses: aquasecurity/trivy-action@v0.36.0
142+
with:
143+
image-ref: kaiban-distributed:ci-${{ github.sha }}
144+
format: table
145+
severity: CRITICAL,HIGH
146+
ignore-unfixed: true
147+
exit-code: "1"
148+
env:
149+
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db
150+
# Always publish the full SARIF to the Security tab, even when the gate fails.
151+
- name: Scan image (Trivy — SARIF report)
152+
if: always()
153+
uses: aquasecurity/trivy-action@v0.36.0
154+
with:
155+
image-ref: kaiban-distributed:ci-${{ github.sha }}
156+
format: sarif
157+
output: trivy.sarif
158+
severity: CRITICAL,HIGH
159+
ignore-unfixed: true
160+
exit-code: "0"
161+
env:
162+
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db
163+
- name: Upload Trivy SARIF to code scanning
164+
if: always()
165+
uses: github/codeql-action/upload-sarif@v3
166+
with:
167+
sarif_file: trivy.sarif
168+
category: trivy-image

.github/workflows/nightly.yml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
name: Nightly (E2E · Kafka · chaos)
2+
3+
# Heavy integration suites kept out of the fast PR path. The e2e setup files
4+
# (tests/e2e/setup/*) auto-provision Redis/Kafka via Docker on the runner.
5+
6+
on:
7+
schedule:
8+
- cron: "0 2 * * *" # daily 02:00 UTC
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
e2e-bullmq:
16+
name: E2E — BullMQ / Redis
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
- uses: actions/setup-node@v4
21+
with:
22+
node-version: "22"
23+
cache: "npm"
24+
- run: npm ci
25+
- name: E2E (BullMQ/Redis)
26+
run: npm run test:e2e
27+
env:
28+
REDIS_URL: redis://localhost:6379
29+
AGENT_IDS: test-agent
30+
- name: Security E2E (firewall · JWT · channel signing)
31+
run: npm run test:e2e:security
32+
env:
33+
REDIS_URL: redis://localhost:6379
34+
AGENT_IDS: test-agent
35+
36+
e2e-kafka:
37+
name: E2E — Kafka
38+
runs-on: ubuntu-latest
39+
steps:
40+
- uses: actions/checkout@v4
41+
- uses: actions/setup-node@v4
42+
with:
43+
node-version: "22"
44+
cache: "npm"
45+
- run: npm ci
46+
- name: E2E (Kafka)
47+
run: npm run test:e2e:kafka
48+
env:
49+
KAFKA_BROKERS: localhost:9092
50+
AGENT_IDS: test-agent
51+
52+
chaos:
53+
name: Chaos — broker fault injection (Redis pause/unpause)
54+
runs-on: ubuntu-latest
55+
steps:
56+
- uses: actions/checkout@v4
57+
- uses: actions/setup-node@v4
58+
with:
59+
node-version: "22"
60+
cache: "npm"
61+
- run: npm ci
62+
- name: Broker resilience (pause Redis mid-flight, assert zero dropped)
63+
run: npm run test:e2e:chaos
64+
env:
65+
REDIS_URL: redis://localhost:6379
66+
AGENT_IDS: test-agent
67+
68+
mutation:
69+
name: Mutation testing (domain layer — Stryker)
70+
runs-on: ubuntu-latest
71+
steps:
72+
- uses: actions/checkout@v4
73+
- uses: actions/setup-node@v4
74+
with:
75+
node-version: "22"
76+
cache: "npm"
77+
- run: npm ci
78+
- name: Stryker mutation (break < 85% domain score)
79+
run: npm run test:mutation
80+
- name: Upload mutation HTML report
81+
uses: actions/upload-artifact@v4
82+
if: always()
83+
with:
84+
name: mutation-report
85+
path: reports/mutation/
86+
87+
bench:
88+
name: Micro-benchmarks (perf baseline)
89+
runs-on: ubuntu-latest
90+
steps:
91+
- uses: actions/checkout@v4
92+
- uses: actions/setup-node@v4
93+
with:
94+
node-version: "22"
95+
cache: "npm"
96+
- run: npm ci
97+
- run: npm run bench

0 commit comments

Comments
 (0)