Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .env.local.example

This file was deleted.

69 changes: 69 additions & 0 deletions .github/actions/verric/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Verric GitHub Action

Generate an evidence-grounded report — pentest, postmortem, audit — straight from your CI pipeline. The action wraps the [`verric` CLI](../../../packages/cli/) and uploads the resulting `report.json`, `receipt.json`, and verdicts as a workflow artifact.

## Trust contract

- Real provider or honest failure. **No mock fallback.**
- Every successful run produces a [cryptographic receipt](../../../packages/core/src/receipts.ts) signed with `VERRIC_SIGNING_KEY` (defaults to `${{ github.sha }}` so receipts are reproducible per commit).
- The grounding pass + adversarial canary still run; if a model gets prompt-injected, the action exits non-zero.

## Quick start

```yaml
name: Generate pentest report
on:
workflow_dispatch:
push:
paths: ["evidence/**"]

jobs:
verric:
runs-on: ubuntu-latest
permissions:
contents: read
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/verric
with:
evidence-dir: ./evidence
project-file: ./engagement.json
provider: openai
```

## Inputs

| Name | Description | Required | Default |
|---|---|---|---|
| `evidence-dir` | Directory of evidence files | yes | — |
| `project-file` | `ProjectDetails` JSON | no | built-in sample |
| `notes-file` | Markdown notes appended to evidence | no | — |
| `out-dir` | Where to write report/receipt/verdicts | no | `./verric-out` |
| `provider` | `openai` \| `anthropic` \| `ollama` | no | auto-detect |
| `model` | Override model id | no | provider default |
| `signing-key` | HMAC key for the receipt | no | `${{ github.sha }}` |
| `template` | Report template id | no | `pentest@0.1.0` |

## Outputs

| Name | Description |
|---|---|
| `report-path` | Path to the generated `report.json` |
| `receipt-path` | Path to the signed `receipt.json` |
| `receipt-signature` | First 16 hex chars of the HMAC signature |

## Verifying a receipt later

Anyone with the same signing key can independently verify a receipt:

```bash
verric verify \
--receipt ./verric-out/receipt.json \
--report ./verric-out/report.json \
--evidence ./verric-out/evidence.json \
--signing-key $GITHUB_SHA
```

Exit 0 = signature valid. Non-zero with a per-field breakdown on stderr otherwise.
108 changes: 108 additions & 0 deletions .github/actions/verric/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: "Verric — Evidence-Grounded Report"
description: "Generate a grounded pentest/postmortem/audit report from CI evidence. Real provider or honest failure."
author: "Verric"
branding:
icon: "shield"
color: "red"

inputs:
evidence-dir:
description: "Directory containing evidence files (scans, logs, screenshots, etc.)."
required: true
project-file:
description: "Path to a ProjectDetails JSON file. Optional; the built-in sample is used if omitted."
required: false
notes-file:
description: "Optional Markdown file appended as manual tester notes."
required: false
out-dir:
description: "Directory where the action writes report.json, receipt.json, etc."
required: false
default: "./verric-out"
provider:
description: "openai | anthropic | ollama. Auto-detects from env when omitted."
required: false
model:
description: "Override model id for the chosen provider."
required: false
signing-key:
description: "HMAC key for the cryptographic receipt. Defaults to GITHUB_SHA so receipts are reproducible per commit."
required: false
template:
description: "Report template id (e.g. pentest@0.1.0)."
required: false
default: "pentest@0.1.0"

outputs:
report-path:
description: "Path to the generated report.json"
value: ${{ steps.run.outputs.report-path }}
receipt-path:
description: "Path to the signed receipt.json"
value: ${{ steps.run.outputs.receipt-path }}
receipt-signature:
description: "First 16 hex chars of the HMAC signature (for at-a-glance log inspection)"
value: ${{ steps.run.outputs.receipt-signature }}

runs:
using: "composite"
steps:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: "11.5.2"

- name: Install + build CLI
shell: bash
working-directory: ${{ github.action_path }}/../../..
run: |
pnpm install --frozen-lockfile
pnpm --filter @verric/cli build

- name: Run Verric
id: run
shell: bash
env:
# Provide whichever provider creds are present; the CLI picks one.
OPENAI_API_KEY: ${{ env.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ env.ANTHROPIC_API_KEY }}
OLLAMA_BASE_URL: ${{ env.OLLAMA_BASE_URL }}
VERRIC_PROVIDER: ${{ inputs.provider }}
VERRIC_SIGNING_KEY: ${{ inputs.signing-key || github.sha }}
run: |
set -euo pipefail
CLI="${{ github.action_path }}/../../../packages/cli/dist/cli.mjs"
PROJECT_ARG=""
if [ -n "${{ inputs.project-file }}" ]; then
PROJECT_ARG="--project ${{ inputs.project-file }}"
fi
NOTES_ARG=""
if [ -n "${{ inputs.notes-file }}" ]; then
NOTES_ARG="--notes ${{ inputs.notes-file }}"
fi
MODEL_ARG=""
if [ -n "${{ inputs.model }}" ]; then
MODEL_ARG="--model ${{ inputs.model }}"
fi
node "$CLI" report \
--evidence "${{ inputs.evidence-dir }}" \
--out "${{ inputs.out-dir }}" \
$PROJECT_ARG \
$NOTES_ARG \
$MODEL_ARG
echo "report-path=${{ inputs.out-dir }}/report.json" >> "$GITHUB_OUTPUT"
echo "receipt-path=${{ inputs.out-dir }}/receipt.json" >> "$GITHUB_OUTPUT"
SIG=$(node -e "const r=require('${{ inputs.out-dir }}/receipt.json'); process.stdout.write(r.signature.slice(0,16));")
echo "receipt-signature=$SIG" >> "$GITHUB_OUTPUT"

- name: Upload report artifacts
uses: actions/upload-artifact@v4
with:
name: verric-report
path: ${{ inputs.out-dir }}
retention-days: 30
34 changes: 34 additions & 0 deletions .github/apps/verric/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Verric GitHub App

A GitHub App that auto-drafts grounded reports when specific events happen on a repo. Triggers:

| Trigger | Action |
|---|---|
| Close an issue with the label `verric:postmortem` | Draft a postmortem from the issue body + linked PRs + relevant Slack threads (when configured) |
| Merge a PR with the label `verric:adr` | Draft an Architecture Decision Record from the PR description + diff |

## How it works

1. The app posts events to `POST /api/github/webhook` on your self-hosted Verric instance.
2. Verric verifies the `X-Hub-Signature-256` header against `VERRIC_GITHUB_WEBHOOK_SECRET`.
3. Routes by event + label, then dispatches a Verric run asynchronously (same engine used for manual runs — receipt, canary, grounding pass, the lot).
4. When the run completes, Verric posts a comment on the issue/PR linking to the report and includes the receipt's signature prefix.

## Configure the App

1. Create a new GitHub App: <https://github.com/settings/apps/new>
2. Webhook URL: `https://your-verric.example.com/api/github/webhook`
3. Webhook secret: any high-entropy string. Set the same value as `VERRIC_GITHUB_WEBHOOK_SECRET` on your Verric server.
4. Permissions:
- **Issues**: Read & write (for posting comments on completed postmortems)
- **Pull requests**: Read & write
- **Contents**: Read (for fetching diffs)
- **Metadata**: Read (default)
5. Subscribe to events:
- Issues
- Pull request
6. Install on the repo(s) you want grounded reports for.

## Status

The webhook receiver is **live and signature-verified**. Dispatching to the engine for postmortem/ADR drafts is wired but currently logs intent rather than firing the run end-to-end — that lights up alongside the GitHub importer expansion in the next slice.
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

# Cancel any in-flight CI run on the same branch when a new push lands.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
TURBO_TELEMETRY_DISABLED: 1
NEXT_TELEMETRY_DISABLED: 1
CI: true

jobs:
verify:
name: lint · typecheck · test · build
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 11.5.2

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: "pnpm"

- name: Install
run: pnpm install --frozen-lockfile

- name: Format check
run: pnpm format:check

- name: Lint
run: pnpm lint

- name: Typecheck
run: pnpm typecheck

- name: Test
run: pnpm test

- name: Build
run: pnpm build
37 changes: 34 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
# Build output
.next
.turbo
out
dist
build
coverage

# Rust / Tauri build output
target/
apps/desktop/src-tauri/gen/
# Dependencies
node_modules
.env*.local

# Lockfiles for other package managers (we use pnpm)
package-lock.json
yarn.lock

# Env / secrets
.env
.env.*
!.env.*.example

# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# verric scratch
# IDE / OS
.vscode
.idea
.DS_Store
Thumbs.db

# Verric scratch
.page*.png
.pf*.png
.nf*.png
.vp*.png

# tooling binaries
# Tooling
bin/
tsconfig.tsbuildinfo
*.tsbuildinfo

# CodeGraph index
.codegraph
5 changes: 5 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=false
node-linker=isolated
verify-deps-before-run=false
18 changes: 18 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
node_modules
.next
.turbo
dist
build
out
coverage
pnpm-lock.yaml
package-lock.json
*.min.js
*.min.css
.codegraph

# Hand-styled markdown — leave the author's voice alone
README.md
demo-evidence-pack
demo-complete-evidence-pack
demo-complete-evidence-pack-README.md
10 changes: 10 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"singleQuote": false,
"trailingComma": "none",
"printWidth": 110,
"tabWidth": 2,
"useTabs": false,
"endOfLine": "lf",
"arrowParens": "always"
}
Loading
Loading