From d539c5ccc62aa548a1568d4398caec265ffb3c5a Mon Sep 17 00:00:00 2001 From: Navaneeth K Date: Sat, 6 Jun 2026 02:20:57 +0530 Subject: [PATCH 1/4] chore: containerize app for deployment Add a multi-stage Dockerfile (Next.js standalone output), .dockerignore, and docker-compose.yml. Enables output: standalone in next.config.mjs for a lean runtime image. Secrets are injected at runtime via .env.local, never baked into the image. Verified: image builds and the container serves HTTP 200. --- .dockerignore | 41 +++++++++++++++++++++++++++++++++++++++++ Dockerfile | 42 ++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 25 +++++++++++++++++++++++++ next.config.mjs | 6 +++++- 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..021d9f0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,41 @@ +# Dependencies / build artifacts (rebuilt inside the image) +node_modules +.next +out +build + +# Local env & secrets — never bake these into the image +.env +.env*.local + +# Git & CI +.git +.gitignore + +# Editor / OS noise +.vscode +.idea +.DS_Store +Thumbs.db + +# Logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Docker files themselves +Dockerfile +.dockerignore +docker-compose.yml + +# Project scratch / demo evidence not needed at runtime +.page*.png +.pf*.png +.nf*.png +.vp*.png +bin/ +tsconfig.tsbuildinfo +demo-evidence-pack +demo-complete-evidence-pack +demo-complete-evidence-pack-README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a2f8718 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ +# syntax=docker/dockerfile:1 + +# ---- Stage 1: install dependencies (incl. dev deps for the build) ---------- +FROM node:22-alpine AS deps +WORKDIR /app +# libc6-compat keeps some native Node addons happy on Alpine. +RUN apk add --no-cache libc6-compat +COPY package.json package-lock.json ./ +RUN npm ci + +# ---- Stage 2: build the Next.js standalone output -------------------------- +FROM node:22-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +# Telemetry off for reproducible CI builds. No secrets are needed at build time; +# OPENAI_API_KEY is supplied at runtime only. +ENV NEXT_TELEMETRY_DISABLED=1 +RUN npm run build + +# ---- Stage 3: minimal runtime image --------------------------------------- +FROM node:22-alpine AS runner +WORKDIR /app + +ENV NODE_ENV=production \ + NEXT_TELEMETRY_DISABLED=1 \ + PORT=3000 \ + HOSTNAME=0.0.0.0 + +# Run as a non-root user. +RUN addgroup --system --gid 1001 nodejs \ + && adduser --system --uid 1001 nextjs + +# Copy the standalone server, static assets, and (if present) public files. +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs +EXPOSE 3000 + +# server.js is produced by Next's standalone output and honors PORT/HOSTNAME. +CMD ["node", "server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..67c3d07 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,25 @@ +services: + verric: + build: + context: . + dockerfile: Dockerfile + image: verric:latest + container_name: verric + ports: + - "3000:3000" + # Secrets are injected at runtime, never baked into the image. + # Reuses your existing .env.local (OPENAI_API_KEY / OPENAI_MODEL / USE_MOCK_REPORT). + env_file: + - .env.local + environment: + NODE_ENV: production + # Sensible fallbacks if a value is absent from .env.local. + OPENAI_MODEL: ${OPENAI_MODEL:-gpt-4o-mini} + USE_MOCK_REPORT: ${USE_MOCK_REPORT:-false} + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 20s diff --git a/next.config.mjs b/next.config.mjs index 4678774..4840825 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,8 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + // Emit a self-contained server bundle (.next/standalone) so the Docker + // runtime image only needs the traced files, not the full node_modules. + output: "standalone" +}; export default nextConfig; From d9ba0b63757be08cc726206235cf73fb3755fb17 Mon Sep 17 00:00:00 2001 From: Navaneeth K Date: Sat, 6 Jun 2026 02:47:33 +0530 Subject: [PATCH 2/4] fix(docker): correct healthcheck for Alpine busybox + IPv4 bind Alpine's busybox wget lacks --spider/--no-verbose, and the standalone server binds to IPv4 0.0.0.0, so the probe must hit 127.0.0.1 not localhost (::1). Also add the nginx reverse-proxy vhost used to serve the app behind the shared nginx as a name-based virtual host. --- deploy/verric.cyberkunju.com.conf | 56 +++++++++++++++++++++++++++++++ docker-compose.yml | 4 ++- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 deploy/verric.cyberkunju.com.conf diff --git a/deploy/verric.cyberkunju.com.conf b/deploy/verric.cyberkunju.com.conf new file mode 100644 index 0000000..d90c045 --- /dev/null +++ b/deploy/verric.cyberkunju.com.conf @@ -0,0 +1,56 @@ +# /etc/nginx/conf.d/verric.cyberkunju.com.conf +# Verric reporting studio - name-based virtual host on the shared nginx. +# Routes verric.cyberkunju.com -> Verric Docker container at 127.0.0.1:3000. +# Self-contained: does NOT modify the versifine.com vhost or the default +# catch-all (00-base.conf). Relies on the $connection_upgrade map and +# client_max_body_size declared in 00-base.conf. + +upstream verric_app { + server 127.0.0.1:3000; + keepalive 16; +} + +# --- Plain HTTP -> redirect to HTTPS --- +server { + listen 80; + listen [::]:80; + server_name verric.cyberkunju.com; + return 301 https://$host$request_uri; +} + +# --- HTTPS --- +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name verric.cyberkunju.com; + + ssl_certificate /etc/ssl/verric.cyberkunju.com/cert.pem; + ssl_certificate_key /etc/ssl/verric.cyberkunju.com/key.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 1d; + + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + access_log /var/log/nginx/verric.access.log; + error_log /var/log/nginx/verric.error.log warn; + + location / { + proxy_pass http://verric_app; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + # /api/generate-report calls OpenAI and can take ~25s; allow headroom. + proxy_read_timeout 120s; + proxy_connect_timeout 10s; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 67c3d07..7832d7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,9 @@ services: USE_MOCK_REPORT: ${USE_MOCK_REPORT:-false} restart: unless-stopped healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"] + # Alpine ships busybox wget (no --spider/--no-verbose), and the server + # binds to IPv4 0.0.0.0, so probe 127.0.0.1 rather than localhost (::1). + test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:3000/"] interval: 30s timeout: 5s retries: 3 From 3125e4f6c80d755937187e9e8898594d74e0edf0 Mon Sep 17 00:00:00 2001 From: Navaneeth K Date: Sat, 6 Jun 2026 03:04:06 +0530 Subject: [PATCH 3/4] feat: add New Report reset button Adds a 'New Report' button in the header that clears the project brief, evidence artifacts, manual notes, and generated draft, returning the studio to the setup step. Confirms before discarding in-progress work, resets the file input, and clears any auto-saved draft from localStorage. --- src/app/page.tsx | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index f8dd4f8..0b8d815 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -376,6 +376,30 @@ export default function Home() { setActiveEvidenceIds(claim.evidenceIds); } + function resetStudio() { + const hasWork = artifacts.length > 0 || manualNotes.trim().length > 0 || hasReviewed; + if (hasWork && !window.confirm("Start a new report? This clears the current brief, evidence, and draft.")) { + return; + } + setStep("setup"); + setProject(emptyProjectDetails); + setArtifacts([]); + setManualNotes(""); + setReport(validateReport(createMockReport([], emptyProjectDetails), [], emptyProjectDetails)); + setMode("mock"); + setHasReviewed(false); + setError(null); + setActiveEvidenceIds([]); + setActiveClaimId(null); + if (inputRef.current) inputRef.current.value = ""; + // Also clear any auto-saved draft (no-op if persistence isn't enabled). + try { + localStorage.removeItem("verric:draft-brief"); + } catch { + // storage unavailable — nothing to clear + } + } + return (
@@ -385,9 +409,14 @@ export default function Home() { Verric
AI reporting studio · proof before polish
- +
+ + +
From 4374ca231ffe4ef96913c9585210bc8155c32cf0 Mon Sep 17 00:00:00 2001 From: Navaneeth K Date: Sat, 6 Jun 2026 11:13:41 +0530 Subject: [PATCH 4/4] docs: add deep-dive documentation (vision, architecture, innovations) Three detailed documents plus an index covering the product vision and competitive positioning, the full A-to-Z architecture and engine pipeline, and a catalog of innovations with their real-world rationale and moat analysis. --- docs/01-VISION-AND-PRODUCT.md | 218 ++++++++++++ docs/02-ARCHITECTURE-AND-ENGINE.md | 368 ++++++++++++++++++++ docs/03-INNOVATIONS-AND-COMPETITIVE-EDGE.md | 170 +++++++++ docs/README.md | 26 ++ 4 files changed, 782 insertions(+) create mode 100644 docs/01-VISION-AND-PRODUCT.md create mode 100644 docs/02-ARCHITECTURE-AND-ENGINE.md create mode 100644 docs/03-INNOVATIONS-AND-COMPETITIVE-EDGE.md create mode 100644 docs/README.md diff --git a/docs/01-VISION-AND-PRODUCT.md b/docs/01-VISION-AND-PRODUCT.md new file mode 100644 index 0000000..c71afb3 --- /dev/null +++ b/docs/01-VISION-AND-PRODUCT.md @@ -0,0 +1,218 @@ +# Verric — Vision & Product + +> **Pentest reports you can prove.** +> Drop the raw mess of a finished engagement. Get a client-ready report where every claim is traceable to its evidence — and anything the AI can't prove is flagged, never shipped. + +This document is the "why." It covers the problem, the thesis, who Verric is for, how it's used in the real world, the competitive landscape, and where the product is going. For the "how," see [`02-ARCHITECTURE-AND-ENGINE.md`](./02-ARCHITECTURE-AND-ENGINE.md). For the defensible differentiators, see [`03-INNOVATIONS-AND-COMPETITIVE-EDGE.md`](./03-INNOVATIONS-AND-COMPETITIVE-EDGE.md). + +--- + +## 1. The one-sentence pitch + +Verric is an evidence-grounded reporting engine that turns the raw output of a penetration test — nmap dumps, Burp request/response pairs, sqlmap logs, terminal scrollback, screenshots, and rough notes — into a professional, client-ready report in which **every factual sentence is linked to the exact evidence behind it**, and **anything the AI cannot prove is automatically pulled out of the deliverable** and surfaced for human review. + +It is not "AI that writes reports." It is **AI that is forced to prove every line it writes**. + +--- + +## 2. The problem + +### 2.1 Reporting is the tax on every engagement + +In professional offensive security, the actual hacking is only half the job. The other half — often **up to 60% of the billable hours on an engagement** — is writing the report. A penetration test that found nothing is worthless to a client; a penetration test that found everything but was never written up credibly is *also* worthless. The report **is** the product. + +Report writing is slow, repetitive, and cognitively expensive: + +- Re-reading scrollback to reconstruct what actually happened. +- Re-deriving CVSS vectors and scores by hand (and getting them subtly wrong). +- Translating raw tool output into executive language without losing technical precision. +- Formatting everything into a consulting-grade deliverable: cover page, executive summary, scope, methodology, severity distribution, per-finding detail, evidence appendix, disclaimer. + +### 2.2 The obvious fix — "just use an LLM" — is a trap + +Large language models are extremely good at producing fluent, professional-sounding security prose. So why hasn't AI already eaten this market? + +**Because the bottleneck was never speed. It's trust.** + +A penetration test report is a legal and commercial artifact. A client makes remediation decisions, budget decisions, and sometimes compliance attestations based on it. If an AI: + +- **hallucinates a finding** that was never demonstrated, +- **invents a CVE** or an exploitation outcome that didn't happen, +- **assigns a CVSS score that contradicts its own vector**, or +- **fabricates an impact** ("full account takeover") that the evidence doesn't support — + +…then the consultancy has shipped a **liability** to a paying client. One hallucinated line can cost a firm its credibility, its client, and potentially expose it legally. That risk is so unacceptable that most serious teams simply **won't let a generative model near the deliverable** — even though they desperately want the time back. + +### 2.3 The real problem statement + +> The pentest reporting bottleneck is not "writing is slow." It is **"we cannot trust generated text in a document where a single fabricated claim is a business-ending event."** + +Solve trust, and the speed gain follows. That is the entire premise of Verric. + +--- + +## 3. The thesis: proof before polish + +Most AI security tools optimize for **polish** — make the text read well. Verric inverts the priority: **proof first, polish second.** + +The core design commitments: + +1. **Every factual claim must cite its evidence.** Each generated sentence carries a list of `evidenceIds` pointing to exact source chunks. +2. **The model's self-citation is not trusted.** A *second, independent* LLM pass re-checks whether the cited evidence actually supports each sentence. +3. **Scores are computed, not guessed.** The CVSS base score is calculated in code from the vector, so score, vector, and severity can never disagree. +4. **Unproven material never reaches the client.** Confirmed findings go in the body; unconfirmed observations and unsupported claims are partitioned into clearly-labeled "needs validation" sections. +5. **The tool degrades safely.** If the AI is unavailable, a deterministic, hand-grounded report is produced instead, so a live demo or a real workflow never collapses into an error screen. + +The product's emotional promise to the user is: **"You don't have to trust the AI. You can see the proof behind every line — and we already removed the lines we couldn't prove."** + +--- + +## 4. What Verric actually is (the product) + +Verric is a web application — a **reporting studio** — structured as a five-step workflow: + +| Step | Name | What happens | +|---|---|---| +| 01 | **Project Setup** | Capture the engagement brief: client, scope, dates, methodology, tester, classification. This is what makes the export feel like a real consulting deliverable rather than a tool dump. | +| 02 | **Evidence Intake** | Drop up to 10 raw artifacts (nmap, Burp, sqlmap, HAR, JSON, XML, logs, screenshots, PDFs, Markdown notes) plus free-form manual notes. Verric parses what it can (e.g. nmap → a structured Hosts & Services table). | +| 03 | **Verric Review** | The core layer. The AI reviews the evidence and tells the tester **what is missing** before a report can ship — missing PoC, missing CVSS rationale, unsupported claims, missing project detail — as a per-finding readiness checklist. | +| 04 | **Report Draft** | The client-ready draft: executive summary, findings summary, per-finding detail. Every claim is hover-to-source: hover a sentence and the exact evidence chunk lights up. Unverified claims wear an inline `⚠` badge. | +| 05 | **Export** | One-click PDF, DOCX, or TXT — formatted to match a real consulting deliverable, with the honesty partitioning baked in. | + +The defining experience is **Step 03 (Review)** and the **provenance + grounding** woven through Steps 04–05. That is where Verric stops being "a generator" and becomes "a reviewer that happens to also draft." + +--- + +## 5. Who it's for + +### 5.1 Primary persona — the boutique / mid-size pentest firm + +Small and mid-size offensive security consultancies live and die on throughput and reputation. They run many engagements with a lean team. For them Verric is: + +- **Time back:** the reporting tax drops dramatically because the first credible draft is automatic. +- **Reputation insurance:** the grounding gate means a junior consultant can't accidentally ship a hallucinated or overstated finding. +- **Consistency:** every report comes out in the same professional structure with computed scores. + +### 5.2 The solo consultant / freelancer + +A one-person shop has no second reviewer. Verric *is* the second reviewer — it independently checks every claim against evidence and tells the consultant exactly what proof is still missing. + +### 5.3 Internal red / purple teams + +In-house teams reporting to their own security leadership need fast, credible, repeatable write-ups. The grounding trail also makes findings auditable: "show me the evidence for this claim" is one hover away. + +### 5.4 Adjacent (roadmap) personas + +- **SOC analysts** writing incident write-ups (same grounding engine, different input). +- **Engineering teams** wanting security-annotated, evidence-traceable living documentation of a codebase. + +--- + +## 6. Real-world use: a concrete walkthrough + +Consider the bundled demo engagement (`demo-complete-evidence-pack/`), which mirrors a real external web-app test. The tester finishes the engagement with a folder of mess: + +``` +01-nmap-external-scan.txt # service enumeration +02-burp-admin-unauthenticated-poc.http # /admin returns 200 without auth +03-burp-idor-user-export-poc.http # IDOR on a user-export endpoint +04-sqlmap-login-confirmed.txt # confirmed SQLi from sqlmap +05-login-sqli-request-response.http # manual true/false request/response proof +06-tester-notes.md # rough hypotheses and context +07-admin-panel-screenshot.png # visual PoC +08-idor-response-screenshot.png # visual PoC +09-sqlmap-confirmed-screenshot.png # visual PoC +10-api-export-response.json # raw API response +``` + +**Without Verric:** the tester spends hours reconstructing the narrative, hand-writing findings, hand-deriving CVSS, formatting a Word document, and proofreading for overstatement. + +**With Verric:** + +1. They fill the brief (Step 01) once. +2. They drag all 10 files into the drop zone (Step 02). Verric parses the nmap output into a Hosts & Services table on the spot. +3. They click **Run Verric Review** (Step 03). The engine: + - drafts structured findings (unauth admin panel, IDOR, SQL injection, MySQL exposure), + - computes CVSS from each vector, + - maps every sentence to evidence, + - runs a **second independent grounding pass**, + - and produces a per-finding readiness checklist: *affected asset ✓, CVSS rationale ✓, description evidence ✓, PoC ✓, impact ✓, remediation ✓.* + Because this pack contains confirmed sqlmap output **and** manual request/response proof **and** screenshots, no finding is flagged "needs PoC." +4. They review the draft (Step 04), hovering claims to confirm provenance, and read the inline grounding badges. +5. They export a PDF/DOCX (Step 05). Confirmed findings are in the polished body; anything the grounding pass couldn't confirm is in a clearly-labeled "Claims Pending Independent Verification" section — visible to the reviewer, never silently shipped. + +The output is a deliverable the consultant can stand behind, produced in minutes, with an evidence trail for every line. + +--- + +## 7. Why this is competitive + +### 7.1 The landscape + +| Category | Examples (class of tool) | What they do well | Where they fall short for this job | +|---|---|---|---| +| **Generic LLM chat** | ChatGPT, Claude, etc. | Fluent prose, fast | No provenance, no grounding check, invents CVEs/impacts, no computed CVSS, no professional export, no honesty gate. Self-citation only. | +| **Report-management platforms** | PlexTrac / Dradis / AttackForge-style | Templating, finding libraries, collaboration, exports | Human still writes every word; AI features (where present) are generative, not *grounded* and *independently verified*. The trust problem is unsolved. | +| **"Pentest GPT" assistants** | LLM agents for offensive tasks | Help *do* the testing / suggest commands | Aimed at the attack phase, not the credibility-critical reporting deliverable. | +| **Verric** | — | **Grounds and independently verifies every claim, computes CVSS, partitions unproven material out of the deliverable, and exports consulting-grade documents.** | Scope is deliberately focused on the reporting/credibility layer (by design). | + +### 7.2 The differentiation in one line + +Everyone else makes the AI **write**. Verric makes the AI **prove**, then makes a **second AI check the proof**, then **removes what fails the check** before a human ever exports it. + +### 7.3 Why it's defensible (the moat) + +The defensibility isn't the prompt — prompts are copyable. It's the **trust-engineering system** around the model: + +1. **Provenance data model** — claims are first-class objects with `evidenceIds`, threaded from generation through validation, UI, and every exporter. +2. **Independent grounding pass** — a separate, temperature-0 verification call with a strict supported/partial/unsupported rubric, mapped onto claim status. +3. **Computed scoring** — a pure-TypeScript CVSS 3.1 engine that makes score/vector/severity internally consistent by construction. +4. **Honesty partitioning** — confirmed vs. unconfirmed findings, verified vs. unverified claims, enforced consistently across PDF/DOCX/TXT. +5. **Structured evidence parsing** — turning raw tool text into semantic chunks the model can ground against, not just blobs. + +Each piece is individually buildable; the **product value is in their integration into a single honest pipeline that a security professional will actually trust.** That integration, plus domain credibility ("we've written these reports by hand"), is the moat. + +--- + +## 8. The value, quantified + +- **Time:** reporting can consume up to ~60% of an engagement. Automating the credible first draft attacks the single largest non-billable-feeling cost in the business. +- **Risk:** the grounding gate converts "hope nobody hallucinated" into "the system removed anything it couldn't prove." That is risk *reduction*, not just speed. +- **Consistency & onboarding:** junior testers produce senior-grade, consistently-structured reports because the engine enforces structure, scoring, and an evidence trail. +- **Auditability:** every claim's evidence is one hover (or one appendix lookup) away — useful for QA, client pushback, and internal review. + +--- + +## 9. Honest limitations (what Verric is *not*) + +Credibility requires naming the boundaries: + +- Verric does **not** perform the penetration test. It reports on evidence you supply. +- Grounding verification reduces hallucination risk dramatically but is itself an LLM judgment; **a human reviewer is still in the loop by design** — the product surfaces uncertainty rather than hiding it. +- It currently parses nmap plain-text into structure; other formats are ingested as text/semantic chunks (richer structured parsers are on the roadmap). +- PDF/screenshot artifacts are treated as evidence references, not OCR'd. +- The exported document is a strong first draft plus an honesty report — it is meant to be reviewed and signed off by the testing team, not blindly shipped. + +These aren't weaknesses to hide; they are the reason the design keeps a human in control and makes uncertainty visible. + +--- + +## 10. Vision & roadmap + +Verric's grounding engine is general. "Map claims to evidence, independently verify them, and refuse to ship the unprovable" applies far beyond pentest reports. + +| Horizon | Focus | +|---|---| +| **Now** | The pentest report engine: raw evidence → grounded, client-ready report (PDF/DOCX/TXT). | +| **Next** | More structured parsers (Burp XML, Nessus `.nessus`, Nuclei JSONL); **SOC incident write-ups** using the same grounding engine; richer reviewer collaboration. | +| **Later** | **Security-annotated code documentation** — point the engine at a repository to produce living docs with traceable, evidence-backed security flags. | + +The throughline: **a trust layer for AI-generated technical documents in domains where a single fabricated claim is unacceptable.** + +--- + +## 11. Why this team + +Verric was built by people who have **written these reports by hand**. They know what a credible finding looks like, where the CVSS math goes wrong, and exactly where an AI must be kept on a leash. The product is not a guess at a problem from the outside — it encodes lived domain knowledge into a system that keeps generative AI honest. + +> Built by Team Stratosix. Submitted to HackArena 2.0 — Hyderabad Zonals. diff --git a/docs/02-ARCHITECTURE-AND-ENGINE.md b/docs/02-ARCHITECTURE-AND-ENGINE.md new file mode 100644 index 0000000..24bf773 --- /dev/null +++ b/docs/02-ARCHITECTURE-AND-ENGINE.md @@ -0,0 +1,368 @@ +# Verric — Architecture & Engine (A → Z) + +This is the complete technical reference: the stack, the data model, the engine pipeline, the grounding system, the export renderers, and the production deployment. For the product rationale see [`01-VISION-AND-PRODUCT.md`](./01-VISION-AND-PRODUCT.md); for the defensible innovations see [`03-INNOVATIONS-AND-COMPETITIVE-EDGE.md`](./03-INNOVATIONS-AND-COMPETITIVE-EDGE.md). + +--- + +## 1. Stack & rationale + +| Layer | Choice | Why | +|---|---|---| +| Framework | **Next.js 16 (App Router)** | One codebase for the studio UI and the server-side API routes (LLM calls, document rendering). Server routes keep the OpenAI key off the client. | +| UI | **React 19 + TypeScript 5.7** | Strong typing across the entire claim/evidence data model — provenance is type-checked end to end. | +| Styling | **Tailwind 3** with a custom editorial palette | A deliberate "consulting deck" aesthetic (paper/ink/serif), not a generic SaaS look. | +| LLM | **OpenAI Chat Completions** (`gpt-4o-mini` default) | Used for **both** drafting and the independent grounding pass. | +| PDF | **`@react-pdf/renderer`** | Multi-page, typographically controlled PDF built from React components. | +| DOCX | **`docx`** | Programmatic Word documents with tables, shading, embedded images. | +| Core logic | **Pure TypeScript** (no deps) | CVSS 3.1 scorer and nmap parser are dependency-free and unit-testable. | + +Runtime note: all API routes declare `export const runtime = "nodejs"` because PDF/DOCX rendering and the OpenAI fetch require the Node runtime (not edge). + +--- + +## 2. Repository map + +``` +src/ +├── app/ +│ ├── page.tsx # The 5-step studio (client component, all UI state) +│ ├── layout.tsx # Root layout, fonts (Cormorant Garamond, IBM Plex Sans/Mono) +│ ├── globals.css # Theme tokens +│ └── api/ +│ ├── generate-report/route.ts # LLM draft + validateReport + verifyGrounding (2nd pass) +│ ├── export-pdf/route.tsx # Multi-page React-PDF renderer +│ ├── export-docx/route.ts # docx renderer +│ └── export-txt/route.ts # Plain-text renderer +└── lib/ + └── report.ts # Types, CVSS engine, nmap parser, chunker, + # validateReport, deterministic mock report, + # renderPlainTextReport +demo-evidence-pack/ # Minimal demo artifacts +demo-complete-evidence-pack/ # 10 artifacts for the full demo flow +deploy/ +└── verric.cyberkunju.com.conf # nginx reverse-proxy vhost (production) +Dockerfile # Multi-stage, Next.js standalone output +docker-compose.yml # One-command deploy, runtime secrets, healthcheck +``` + +`src/lib/report.ts` is the heart of the system. It is shared by the client studio **and** every server route, which is why the data model and scoring stay perfectly consistent across UI, generation, and all three export formats. + +--- + +## 3. The data model + +Everything flows through a small set of strongly-typed structures defined in `report.ts`. + +### 3.1 Evidence + +```ts +type EvidenceKind = "text" | "json" | "xml" | "image" | "pdf" | "notes" | "unknown"; + +type EvidenceArtifact = { // a single uploaded file (or manual notes) + id: string; name: string; kind: EvidenceKind; + type: string; size: number; + content?: string; // text content (parsed/sliced) + preview?: string; // data URL for images +}; + +type EvidenceChunk = { // an atomic, citable unit of evidence + id: string; // "ev-001", "ev-002", … — the citation handle + artifactId: string; artifactName: string; + lineStart: number; lineEnd: number; + text: string; +}; +``` + +The `EvidenceChunk.id` is the linchpin of the whole system: it is the **handle every claim cites**. Provenance is literally "a claim holds a list of these IDs." + +### 3.2 Claims + +```ts +type ClaimStatus = "grounded" | "needs_review" | "flagged"; + +type ReportClaim = { + id: string; + text: string; // one factual sentence + evidenceIds: string[]; // exact chunks that back it + status: ClaimStatus; // set by validation + grounding pass + groundingNote?: string; // one-line reason when not fully grounded +}; +``` + +`ReportClaim` is the unit of trust. A finding is not a blob of text — it's arrays of claims, each independently citable and independently verifiable. + +### 3.3 Findings, gaps, and the report + +```ts +type Finding = { + id: string; title: string; + severity: Severity; // Critical | High | Medium | Low | Informational | Review + cvss: string; cvssVector: string; // score is recomputed from the vector + affectedAssets: string[]; + status: "Open" | "Ready for Report" | "Needs Review" | "Blocked"; + category: string; + readiness: "ready" | "needs_poc" | "needs_details" | "unsupported"; + readinessSummary: string; + gaps: EvidenceGap[]; // what's missing before this can ship + description: ReportClaim[]; + impact: ReportClaim[]; + proofOfConcept: ReportClaim[]; + remediation: ReportClaim[]; + references: string[]; +}; + +type EvidenceGap = { // a named "what proof is missing" item + id: string; type: /* missing_poc | missing_cvss | unsupported_claim | … */; + title: string; message: string; + suggestedEvidence: string[]; // concrete artifacts that would close the gap + severity: "blocking" | "warning" | "info"; +}; + +type VerricReport = { + project: ProjectDetails; + overallRisk: Severity; + reportReadiness: ReadinessStatus; + readinessSummary: string; + globalGaps: EvidenceGap[]; + executiveSummary: ReportClaim[]; + keyRecommendations: ReportClaim[]; + methodology: string[]; + findings: Finding[]; + remediationRoadmap: { immediate; shortTerm; mediumTerm; longTerm: string[] }; + flaggedClaims: FlaggedClaim[]; +}; +``` + +The shape is deliberately the shape of a **real penetration test report** — exec summary, methodology, findings with description/impact/PoC/remediation, a remediation roadmap, and references — but with every prose element decomposed into citable, verifiable claims. + +--- + +## 4. The engine pipeline + +The journey from raw files to a grounded report is a fixed pipeline. The "defensible work" is steps 3–6. + +``` +RAW EVIDENCE → 1. INGEST → 2. CHUNK → 3. DRAFT (LLM) → 4. VALIDATE → 5. GROUND (LLM #2) → 6. SCORE → OUTPUT +``` + +### 4.1 Ingestion & kind inference (`inferEvidenceKind`) + +On upload (client side, `handleFiles` in `page.tsx`), each file's kind is inferred from extension/MIME: + +- Images (`.png/.jpg/.jpeg`) → `image`, stored as a data-URL `preview` (for embedding in exports) plus a textual reference. +- `.pdf` → `pdf`, stored as a reference (not OCR'd). +- `.json/.har`, `.xml`, `.md`, and text/log/http types → text content, **sliced to 160,000 chars** to bound payloads. + +Manual notes are injected as a synthetic `manual-notes.md` artifact. + +### 4.2 The nmap parser (`isNmapContent`, `parseNmap`) + +A real, dependency-free parser for nmap `-sV` plain-text output: + +- `isNmapContent` cheaply sniffs the head of a file for the `Nmap scan report` / `PORT STATE SERVICE` table signature. +- `parseNmap` walks the lines, tracking the current host (`Nmap scan report for host (ip)`) and parsing each port row into `{ port, proto, state, service, version }`, producing structured `NmapHost[]`. + +This is used in two places: the **UI** renders a Hosts & Services table in the Evidence Intake card, and the **chunker** emits one *semantic* chunk per port. + +### 4.3 Chunking (`buildEvidenceChunks`) + +This is where evidence becomes citable. For each artifact: + +- **Images/PDFs** → a single descriptive chunk ("PNG artifact supplied: …"). +- **nmap content** → in addition to raw lines, **one semantic chunk per parsed port**, phrased so the model can ground against a *fact* rather than a raw line: + > `Nmap: 10.10.10.5 port 3306/tcp open mysql — MySQL 5.7.31` +- **All text** → one chunk per non-empty line, with `lineStart/lineEnd` recorded. + +Chunks get sequential IDs (`ev-001`, `ev-002`, …) and the list is **capped at 180** to bound the token budget. These IDs are the citation vocabulary the LLM must use. + +### 4.4 Drafting (the LLM, first pass — `generate-report/route.ts`) + +The route builds a compact evidence listing (`ev-id | artifact lines x-y: text`, sliced to ~16,000 chars) and an artifact summary, then sends a long, rule-dense system+user prompt to the model with `temperature: 0.15`, `response_format: { type: "json_object" }`. The prompt enforces, among other things: + +- **Every factual sentence must cite exact `evidenceIds`** from the input. +- **Readiness review before drafting**: if a finding lacks concrete PoC, set `readiness: "needs_poc"` and add a **blocking gap** with `suggestedEvidence`. +- **What counts as PoC**: a request/response pair, screenshot, terminal proof, scanner confirmation, or reproduction notes is valid PoC — do **not** demand exploit code. +- **No invention**: no fabricated CVEs, exploitation success, credentials, screenshots, data theft, business names, timelines, tools, or assets. Unproven-but-useful material goes to `flaggedClaims` / finding `gaps`, never into polished findings. +- **CVSS rules**: the score must be consistent with a full CVSS:3.1 vector that includes all 8 base metrics in canonical order (`AV/AC/PR/UI/S/C/I/A`), with explicit reference bands. +- **Reference rules**: the `references` array must match the finding's category (e.g. Broken Access Control → OWASP A01, not "Security Misconfiguration"). + +The model returns a `VerricReport`-shaped JSON object (`extractJson` strips any stray code fences). + +### 4.5 Validation & normalization (`validateReport`) + +Before anything is trusted, `validateReport` sanitizes the model output: + +- Builds a set of **valid chunk IDs** and **strips any `evidenceId` the model cited that doesn't actually exist** (anti-hallucinated-citation). +- Normalizes every claim: a claim with zero valid evidence IDs is forced to `needs_review` (it cannot be "grounded" with no evidence). +- Normalizes gaps, findings, severity defaults, and roadmap shape. +- **Recomputes CVSS from the vector** (see 4.7) so score and severity are derived, never trusted from the model. +- Recomputes `reportReadiness` from whether any blocking gaps exist. + +This step is the firewall between "what the model said" and "what the system will stand behind." + +### 4.6 Independent grounding (the LLM, second pass — `verifyGrounding`) + +This is the signature mechanism. After validation, a **separate** OpenAI call (temperature 0, JSON mode) audits the draft: + +1. `collectClaims` gathers only **factual/observational** claims — executive summary + each finding's description, impact, and proof of concept. Prescriptive guidance (remediation, key recommendations) is **deliberately excluded**, because "use parameterized queries" is correct advice whether or not those exact words appear in the evidence. +2. For each claim, a compact payload is built: `{ claimId, text, evidence: [citedChunkText…] }` (evidence text truncated to 400 chars per chunk to bound tokens). +3. The verifier prompt asks a strict question — *does the cited evidence actually support this exact sentence?* — with a precise rubric: + - **supported**: evidence directly proves it, or it's a conservative paraphrase / a standard impact that follows logically from the demonstrated condition. + - **partial**: evidence is related but the claim adds unsupported specifics (extra severity, scope, conflated facts). + - **unsupported**: a genuine factual leap (asserting exploitation when only access was shown, an unmentioned CVE, invented data exfiltration/takeover). +4. Verdicts are mapped back onto claim status, **mutating the report in place**: + - `supported` → `grounded`, note cleared. + - `partial` → `needs_review`, `groundingNote = "Verric: "`. + - `unsupported` → `flagged`, `groundingNote = "Verric: "`. + +Crucially, `verifyGrounding` is wrapped in try/catch by the caller — **a grounding failure never breaks report generation** (it just leaves validated statuses in place). + +### 4.7 The CVSS 3.1 engine (`cvssFromVector`) + +A pure, dependency-free CVSS 3.1 base-score implementation: + +- Parses a `CVSS:3.1/AV:…/AC:…/PR:…/UI:…/S:…/C:…/I:…/A:…` vector; returns `null` if any required metric is missing (so a malformed vector falls back to the model's text, not a wrong number). +- Uses the official metric weight tables, with **scope-dependent Privileged Required weights** (`PR_U` vs `PR_C`). +- Computes ISS → Impact (scope-aware formula) → Exploitability → base score, applying the spec's **roundup-to-one-decimal** function (`roundUp1`) with float-safety. +- Maps score → severity band (`severityFromScore`): ≥9 Critical, ≥7 High, ≥4 Medium, >0 Low, else Informational. + +Because `validateReport` always re-derives `cvss` and `severity` from `cvssVector`, **the score, the vector, and the severity label can never contradict each other** — a class of error that is endemic in hand-written and naively-generated reports. + +### 4.8 Deterministic fallback (`createMockReport`) + +`createMockReport` builds a fully-grounded report **in code** from whatever chunks are present, using an `ids()` helper to match real evidence (e.g. find the chunk mentioning `3306/tcp|mysql`) and attach it to the relevant claims. It encodes a realistic engagement (unauth admin panel, MySQL exposure, version disclosure) and even demonstrates the honesty model (it flags an unproven "specific CVE" claim). + +It's used: + +- as the **initial UI state** before any review runs, +- when `USE_MOCK_REPORT=true`, +- when **no OpenAI key** is configured, and +- when the **OpenAI call fails** (the route catches and returns the mock). + +This is why a demo or a real session **never** collapses into an error — there is always a credible, grounded report to show. + +--- + +## 5. Claim status lifecycle + +``` + ┌───────────────────────────── grounded (in polished body) +draft → validate ─ needs_review (partial) ──── needs_review (kept in body, ⚠ badge) + └─ no/invalid evidence ──┐ + ↓ + verifyGrounding overrides: + supported → grounded + partial → needs_review (⚠ "unverified") + unsupported → flagged (⚠ "unsupported", pulled from body) +``` + +The exporters and the UI treat `grounded` + `needs_review` as **"verified enough for the body"** and `flagged` as **"pull it out."** That single rule is applied identically in the studio, the PDF, and the DOCX. + +--- + +## 6. The honesty partitioning (two/three tiers) + +The deliverable is split so nothing shaky reaches the client unlabeled: + +1. **Confirmed findings → polished body.** A finding is "unconfirmed" if its text matches `/potential|candidate|unconfirmed|not confirmed|requires further|no successful payload|needs poc/i` or its readiness is `needs_poc`/`unsupported` (`isUnconfirmedFinding`). +2. **Unconfirmed observations → "Items Requiring Validation."** Listed with the reason more proof is needed — visible, but not presented as proven vulnerabilities. +3. **Unsupported individual claims → "Claims Pending Independent Verification."** Claims the grounding pass flagged are removed from the polished prose and tabulated (source, statement, status, reviewer note). + +This logic is implemented consistently in `export-pdf/route.tsx`, `export-docx/route.ts`, and reflected in `page.tsx`. + +--- + +## 7. The studio UI (`page.tsx`) + +A single client component holds all workflow state: `step`, `project`, `artifacts`, `manualNotes`, `report`, `mode` (`openai` | `mock`), `hasReviewed`, plus the active-claim selection that drives provenance highlighting. + +Key behaviors: + +- **`chunks` is derived** (`useMemo`) from artifacts + notes, so the citable evidence set is always in sync with what's uploaded. +- **`runVerricReview`** POSTs `{ project, artifacts, chunks }` to `/api/generate-report`, then re-runs `validateReport` on the response client-side for belt-and-suspenders consistency; on any failure it falls back to the mock and surfaces a friendly message. +- **Hover-to-source provenance:** each `ClaimBlock` calls `selectClaim` on hover/click, setting `activeEvidenceIds`; the Evidence Inspector highlights exactly those chunks. +- **Inline grounding badges:** claims with status `needs_review`/`flagged` render a `⚠ unverified`/`⚠ unsupported` badge carrying the `groundingNote` as a tooltip. +- **Readiness checklist per finding** (`FindingReviewCard`): affected asset, CVSS rationale, description evidence, PoC, impact, remediation — each shown Ready/Missing. +- **"New Report" reset:** clears the brief, evidence, notes, and draft back to the setup step (with a confirmation guard), resets the file input, and clears any saved draft from `localStorage`. + +--- + +## 8. Export renderers + +All three exporters consume the same `VerricReport` + `chunks` (+ `artifacts` for images) and apply the same honesty partitioning. + +### 8.1 PDF (`export-pdf/route.tsx`, `@react-pdf/renderer`) + +A six-section A4 document built from React components: + +1. **Cover** — title, client, project metadata grid, overall risk. +2. **Summary** — executive summary (verified claims only), assessment overview counts, severity distribution, key recommendations, scope & methodology table. +3. **Risk Rating Methodology** — the severity → CVSS band → remediation-timeline table. +4. **Findings Summary** — confirmed findings table, plus "Items Requiring Validation" and "Claims Pending Independent Verification" tables, plus remediation priority. +5. **Detailed Findings** — per finding: spec table (asset, CVSS score, **CVSS vector in monospace**, references), description/impact/PoC/remediation claim lists, and key evidence excerpts. +6. **Evidence Appendix** — cited evidence excerpts table + embedded screenshot images + disclaimer. + +A fixed footer (`classification · client`) is rendered on every page. `wrap={false}` is used on atomic blocks to avoid ugly page breaks. + +### 8.2 DOCX (`export-docx/route.ts`, `docx`) + +A programmatic Word document mirroring the PDF structure: cover paragraphs, document-control spec table, executive summary, key recommendations, scope & methodology, risk-rating table, findings summary, the two honesty sections, detailed findings, remediation roadmap, an evidence reference index, **embedded screenshot images** (decoded from data-URL previews via `imageDataFromDataUrl`), and a disclaimer. Styling uses a consistent palette (ink/red/muted) and monospace for vectors/evidence, matching real consulting typography. + +### 8.3 TXT (`renderPlainTextReport` in `report.ts`) + +A clean plain-text rendering (project header, exec summary, findings summary, per-finding detail including missing-evidence notes, evidence appendix). Generated **client-side** for instant download and as a dependency-free fallback if PDF/DOCX rendering ever fails. + +--- + +## 9. Production deployment + +The app is containerized and deployed behind an existing shared nginx + Cloudflare stack. + +### 9.1 Container (`Dockerfile`, `docker-compose.yml`) + +- **Multi-stage build** on `node:22-alpine`: `deps` (npm ci) → `builder` (`next build`) → `runner`. +- Uses **Next.js standalone output** (`output: "standalone"` in `next.config.mjs`), so the runtime image ships only the traced server + static assets — no full `node_modules`. +- Runs as a **non-root** `nextjs` user; `EXPOSE 3000`; `CMD ["node", "server.js"]`. +- `docker-compose.yml` injects secrets **at runtime** from `.env.local` (`OPENAI_API_KEY`, `OPENAI_MODEL`, `USE_MOCK_REPORT`) — never baked into the image — with `restart: unless-stopped` and a healthcheck. +- The healthcheck probes `http://127.0.0.1:3000/` (IPv4, busybox-`wget` compatible — `localhost` would resolve to IPv6 `::1`, which the IPv4-bound server doesn't answer). + +### 9.2 Reverse proxy (`deploy/verric.cyberkunju.com.conf`) + +The production host already serves another domain on one public IP. Verric coexists via **name-based virtual hosting**: + +- nginx routes by `Host` header: `verric.cyberkunju.com` → the container on `127.0.0.1:3000`; the existing domain is untouched. +- The container binds to **localhost only**, so it is reachable **only** through nginx, never directly from the internet. +- TLS uses a **Cloudflare Origin Certificate** for `*.cyberkunju.com` (Cloudflare proxied, Full-strict), mirroring the existing site's pattern. +- `proxy_read_timeout` is raised (the `/api/generate-report` call to OpenAI can take ~25s). + +### 9.3 Deploy flow + +```bash +cd ~/verric && git pull && sudo docker compose up -d --build +``` + +The image rebuilds (the build runs on the ARM/Graviton host to match architecture), the container is recreated, and nginx continues serving with zero changes to the co-located domain. + +--- + +## 10. Data-flow summary (one screen) + +``` +┌── Studio (page.tsx, client) ───────────────────────────────────────────────┐ +│ Step 1 Setup → Step 2 Evidence (inferKind, parseNmap, buildEvidenceChunks) │ +│ │ POST { project, artifacts, chunks } │ +└───────────────────────┼─────────────────────────────────────────────────────┘ + ▼ +┌── /api/generate-report (server) ───────────────────────────────────────────┐ +│ mock? → createMockReport → validateReport ──────────────► return │ +│ live? → OpenAI draft (#1) → extractJson → validateReport │ +│ → verifyGrounding (OpenAI #2, try/catch) → return │ +└───────────────────────┬─────────────────────────────────────────────────────┘ + ▼ VerricReport (claims carry status + evidenceIds) +┌── Studio review/draft → hover-to-source, ⚠ badges, readiness checklists ─────┐ +│ Export → /api/export-pdf | export-docx | (client) renderPlainTextReport │ +│ Honesty partitioning applied identically across all formats │ +└──────────────────────────────────────────────────────────────────────────────┘ +``` + +The whole system is one consistent loop: **decompose into citable claims → draft → strip bad citations & compute scores → independently verify → partition the unprovable out → render.** diff --git a/docs/03-INNOVATIONS-AND-COMPETITIVE-EDGE.md b/docs/03-INNOVATIONS-AND-COMPETITIVE-EDGE.md new file mode 100644 index 0000000..1f722e6 --- /dev/null +++ b/docs/03-INNOVATIONS-AND-COMPETITIVE-EDGE.md @@ -0,0 +1,170 @@ +# Verric — Innovations & Competitive Edge + +This document catalogs what is genuinely novel in Verric, why each piece matters in the real world, and where competing approaches fall short. For product context see [`01-VISION-AND-PRODUCT.md`](./01-VISION-AND-PRODUCT.md); for implementation detail see [`02-ARCHITECTURE-AND-ENGINE.md`](./02-ARCHITECTURE-AND-ENGINE.md). + +--- + +## 0. The framing: Verric sells *trust*, not *text* + +The entire AI-for-security space is crowded with tools that **generate**. Verric's category is different: it is a **trust layer for AI-generated technical documents** in a domain where one fabricated claim is a business-ending event. Every innovation below exists to serve a single thesis: + +> **Don't ask the user to trust the AI. Show the proof behind every line — and remove the lines you can't prove.** + +That reframing — from "generation quality" to "provable credibility" — is the foundational innovation. Everything else is the machinery that makes it real. + +--- + +## 1. Independent second-pass grounding verification + +**What it is.** After the model drafts the report, a *separate* LLM call (`verifyGrounding`) re-examines every factual claim against the specific evidence it cited and returns a verdict: **supported / partial / unsupported**. + +**How it works.** `collectClaims` gathers only observational claims (exec summary, finding description/impact/PoC). Each is sent as `{ claimText, citedEvidenceText[] }` to a temperature-0, JSON-mode call with a precise rubric. Verdicts mutate claim status in place: supported → `grounded`, partial → `needs_review` (with a reason), unsupported → `flagged` (pulled from the body). The call is try/catch-wrapped so it can never break generation. + +**Why it matters.** Almost every "AI cites its sources" feature is **self-citation** — the same model that wrote the sentence also asserts it's supported, which is circular and unreliable. Verric breaks the circularity with an **independent audit**. This is the difference between "the AI said it's fine" and "a second, independent check confirmed the evidence actually backs this exact sentence." + +**Real-world impact.** This is the mechanism that lets a firm put generated text in front of a paying client. It converts the unbounded risk of hallucination into a bounded, visible, reviewer-friendly signal. + +**Where competitors fall short.** Generic LLM chat does self-citation at best. Report platforms leave verification entirely to the human. No mainstream pentest-reporting tool runs an independent grounding audit and *acts on the verdict* by partitioning content. + +--- + +## 2. Hover-to-source provenance (claims are first-class, citable objects) + +**What it is.** Every factual sentence in the studio is a `ReportClaim` carrying `evidenceIds`. Hovering a claim lights up the exact source chunk(s) in the Evidence Inspector. + +**How it works.** Evidence is decomposed into atomic `EvidenceChunk`s with stable IDs (`ev-001`…). Claims reference those IDs; the UI's `selectClaim` drives highlight state. The same IDs are threaded into the PDF/DOCX evidence appendices. + +**Why it matters.** Provenance turns the report from an opaque wall of prose into an **auditable artifact**. When a client pushes back — "where did this come from?" — the answer is one hover, or one appendix lookup, away. + +**Real-world impact.** Massively reduces QA and client-defense time, and makes junior-authored reports reviewable by seniors at a glance. + +**Where competitors fall short.** Generated prose elsewhere is typically unattributed. Even where tools attach references, they rarely make the **sentence ↔ exact-evidence-line** link interactive and carry it all the way into the exported deliverable. + +--- + +## 3. Computed CVSS 3.1 — the vector is the single source of truth + +**What it is.** A pure-TypeScript CVSS 3.1 base-score engine (`cvssFromVector`). `validateReport` always **recomputes** the score and severity from the vector. + +**How it works.** Full metric weight tables (with scope-dependent PR), the official ISS/Impact/Exploitability formulas, and the spec's roundup-to-one-decimal — then `severityFromScore` derives the band. A malformed vector returns `null` and falls back gracefully rather than emitting a wrong number. + +**Why it matters.** "Score says 9.8 Critical, vector says `C:L/I:N/A:N`" is a classic, credibility-destroying inconsistency in both hand-written and naively-generated reports. By **deriving** score and severity from the vector in code, Verric makes that contradiction **structurally impossible**. + +**Real-world impact.** Clients and QA reviewers trust the numbers. No more silent CVSS arithmetic errors that undermine the whole report. + +**Where competitors fall short.** LLMs are notoriously unreliable at multi-step arithmetic; tools that let the model emit the score directly inherit that unreliability. Verric refuses to trust the model's number at all. + +--- + +## 4. The three-tier honesty gate + +**What it is.** A consistent partitioning that keeps unproven material out of the client-facing body: + +1. **Confirmed findings** → polished body. +2. **Unconfirmed observations** → "Items Requiring Validation." +3. **Unsupported claims** (flagged by grounding) → "Claims Pending Independent Verification." + +**How it works.** `isUnconfirmedFinding` classifies findings by readiness + language heuristics; the grounding verdicts classify individual claims; the same rules are applied across PDF, DOCX, and the studio. + +**Why it matters.** The dangerous failure mode of AI reporting isn't "the text reads badly" — it's "a plausible-but-unproven claim ships looking exactly like a proven one." Verric makes the **proven/unproven boundary explicit and structural**, not a matter of the reader's vigilance. + +**Real-world impact.** A reviewer instantly sees what's solid versus what needs another look, instead of having to audit every sentence for overstatement. + +**Where competitors fall short.** Generators produce a single undifferentiated block of text. The burden of separating proven from speculative falls entirely on the human. + +--- + +## 5. Structured evidence parsing → semantic, groundable chunks + +**What it is.** Raw tool output is parsed into structured facts before the model sees it. The shipped example is a real nmap `-sV` parser (`parseNmap`) that also emits semantic chunks. + +**How it works.** `buildEvidenceChunks` emits, on top of raw line chunks, one **fact-shaped** chunk per parsed port: `Nmap: 10.10.10.5 port 3306/tcp open mysql — MySQL 5.7.31`. The model grounds claims against a clean fact, not a noisy raw line; the same parse powers a Hosts & Services table in the UI. + +**Why it matters.** Grounding quality is bounded by evidence quality. Giving the model **pre-digested facts** with stable citation handles makes both drafting and verification sharper and reduces ambiguity in what a citation means. + +**Real-world impact.** Better, more defensible citations; a tester *sees* their scan understood correctly before any AI runs. + +**Where competitors fall short.** Dumping raw logs into a prompt yields fuzzy, line-noise citations. Verric's chunking is evidence engineering, not just text stuffing. + +--- + +## 6. Deterministic, hand-grounded fallback + +**What it is.** `createMockReport` builds a fully-grounded, realistic report **in code** from the actual uploaded chunks — no LLM required. + +**How it works.** It matches real evidence with an `ids()` helper, attaches it to encoded claims (unauth admin panel, MySQL exposure, version disclosure), and even demonstrates the honesty model by flagging an unproven CVE claim. It's the initial UI state, the `USE_MOCK_REPORT` path, the no-key path, **and** the catch-block when an OpenAI call fails. + +**Why it matters.** Two payoffs: (1) **the demo never breaks** — a dead network or missing key still yields a credible, grounded report; (2) it's a **reference implementation** of what "correctly grounded" looks like, which keeps the whole pipeline honest. + +**Real-world impact.** Resilience. Offline or degraded environments still produce something usable instead of an error screen — which matters in air-gapped or restricted client environments. + +**Where competitors fall short.** Most LLM tools hard-fail without connectivity/keys; few ship a deterministic, evidence-matched analogue of their AI output. + +--- + +## 7. Consulting-grade export fidelity + +**What it is.** PDF, DOCX, and TXT outputs that look like real consulting deliverables — cover page, exec summary, scope & methodology, risk-rating methodology, severity distribution, findings summary, detailed findings, evidence appendix with embedded screenshots, disclaimer. + +**How it works.** `@react-pdf/renderer` builds a multi-page A4 document with controlled typography, fixed footers, and monospace CVSS vectors; `docx` builds the Word equivalent with tables, shading, and decoded inline screenshots; both apply the same honesty partitioning. + +**Why it matters.** The deliverable **is** the product. A grounded report that exports as an ugly text dump won't be sent to a client. Verric's outputs are presentation-ready. + +**Real-world impact.** The tester's job ends at "review and sign off," not "reformat into our template." + +**Where competitors fall short.** Raw LLM output is markdown at best; achieving consulting-grade, multi-format fidelity with embedded evidence is real engineering most generators skip. + +--- + +## 8. Anti-hallucination prompt engineering as policy + +**What it is.** The drafting prompt encodes domain rules as hard policy: cite exact IDs, treat request/response/screenshot/scanner output as valid PoC (don't over-demand exploit code), never invent CVEs/credentials/outcomes, full canonical CVSS vectors with reference bands, and category-accurate OWASP/CWE references. + +**Why it matters.** This encodes **how an experienced consultant actually reasons** about evidence sufficiency and severity — not generic "write a security report" instructions. It's the difference between a tool built by people who've shipped these reports and a generic wrapper. + +**Where competitors fall short.** Thin prompt wrappers don't encode the nuanced rules (e.g. what counts as adequate PoC, or matching references to the actual vulnerability class) that keep findings credible. + +--- + +## 9. Competitive landscape (summary) + +| Capability | Generic LLM chat | Report platforms (PlexTrac/Dradis-class) | "Pentest GPT" assistants | **Verric** | +|---|---|---|---|---| +| Drafts a full report from raw evidence | ◑ (manual prompting) | ✗ (human writes) | ✗ (attack-phase focus) | ✅ | +| Per-claim provenance to exact evidence | ✗ | ◑ (manual refs) | ✗ | ✅ | +| **Independent** grounding verification | ✗ (self-citation) | ✗ | ✗ | ✅ | +| Computed CVSS (vector = source of truth) | ✗ | ◑ (calculators, manual) | ✗ | ✅ | +| Unproven content partitioned out | ✗ | ✗ | ✗ | ✅ | +| Structured evidence parsing → groundable chunks | ✗ | ◑ (importers) | ✗ | ✅ | +| Consulting-grade multi-format export | ✗ | ✅ | ✗ | ✅ | +| Deterministic offline fallback | ✗ | n/a | ✗ | ✅ | + +`✅ yes · ◑ partial/manual · ✗ no` (assessment by capability class, not a specific vendor benchmark.) + +--- + +## 10. The moat (why this is defensible) + +Any single feature here is copyable. The defensibility is in **three layers that are hard to assemble together credibly:** + +1. **An integrated trust pipeline.** Provenance, independent grounding, computed scoring, and honesty partitioning are threaded through one consistent data model from generation to every export format. Bolting one of these onto a generator is easy; making them cohere into a system a security professional *actually trusts* is the hard part. +2. **Encoded domain judgment.** The rules about evidence sufficiency, valid PoC, CVSS consistency, and reference accuracy reflect lived report-writing experience. That judgment is the product's "secret recipe," not the model. +3. **Category positioning.** Verric defines itself as a **trust layer**, not a generator. As models commoditize, "make AI provably honest in high-stakes documents" becomes more valuable, not less — and the grounding engine generalizes (SOC write-ups, security-annotated code docs) without changing its core. + +--- + +## 11. Why it matters beyond pentesting + +The grounding engine answers a general question: *"how do you let a generative model write a high-stakes technical document without shipping a fabrication?"* That question recurs in: + +- **SOC / incident response write-ups** — same need to ground every claim in log/telemetry evidence. +- **Compliance and audit artifacts** — where unprovable statements are a regulatory hazard. +- **Security-annotated code documentation** — living docs whose security flags must trace to real code evidence. + +Verric is the first concrete, working instance of that trust layer, aimed at the market that feels the pain most acutely today: penetration test reporting. + +--- + +## 12. The bottom line + +Verric's innovation is not that it writes faster. It's that it makes a generative model **prove its work, get independently audited, compute its numbers, and surrender anything it can't substantiate** — and then renders the result as a deliverable a consultant can sign their name to. In a domain where trust was the real bottleneck, that is the thing that actually unblocks adoption. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..b5a2f14 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,26 @@ +# Verric Documentation + +Deep documentation for Verric — the evidence-grounded pentest reporting engine. **Pentest reports you can prove.** + +| Doc | What's inside | +|---|---| +| [01 — Vision & Product](./01-VISION-AND-PRODUCT.md) | The problem, the thesis ("proof before polish"), who it's for, real-world workflows, the competitive landscape, the moat, business value, honest limitations, and the roadmap. | +| [02 — Architecture & Engine](./02-ARCHITECTURE-AND-ENGINE.md) | The full A→Z technical reference: stack, data model, the parse → chunk → draft → validate → ground → score pipeline, the CVSS engine, the grounding pass, the three export renderers, and the production deployment. | +| [03 — Innovations & Competitive Edge](./03-INNOVATIONS-AND-COMPETITIVE-EDGE.md) | Every genuine innovation — what it is, how it works in code, why it matters in the real world, and where competing approaches fall short — plus the defensibility/moat analysis. | + +## The 60-second version + +Reporting can eat up to ~60% of a penetration test engagement, and teams won't let generative AI near the deliverable because one hallucinated finding, wrong CVSS score, or invented impact ships a liability to a paying client. **The bottleneck was never speed — it was trust.** + +Verric solves trust with an integrated pipeline: + +1. **Ingest the chaos** — raw nmap, Burp, sqlmap, logs, screenshots, notes. No templates required. +2. **Decompose into citable claims** — every factual sentence carries the exact `evidenceIds` behind it. +3. **Draft a professional report** — structured findings, executive summary, remediation, **CVSS computed from the vector** so score/vector/severity can never disagree. +4. **Independently verify** — a *second* LLM pass audits each claim against its cited evidence (supported / partial / unsupported). +5. **Refuse to ship the unprovable** — confirmed findings go in the body; unconfirmed observations and unsupported claims are partitioned into clearly-labeled review sections. +6. **Export** — consulting-grade PDF / DOCX / TXT, with the honesty partitioning baked in. + +It doesn't ask you to trust the AI. It shows the proof behind every line — and removes the lines it can't prove. + +> Built by Team Stratosix · Submitted to HackArena 2.0 — Hyderabad Zonals.