Tour
Inside Veylqorix
Everything the platform does, surface by surface. One core engine, six entry points, and a gate that refuses to green-wash — here is how each piece fits.
The architecture in words
The system separates four layers: entry points (who runs a scan — terminal, agent, CI, browser), the integration layer (how they reach the engine — CLI, MCP, REST), the core engine (which scanner runs, when, and how results are normalized and gated), and the results & enforcement surfaces (reports, dashboards, and CI status checks). The core engine itself now has a byte-compatible Rust implementation ( crates/veylqorix-engine), reached through a TypeScript adapter that degrades honestly when the binary is missing.

System architecture — the diagram depicts the target design; the shipped implementation keeps the same engine/adapter separation in a pnpm TypeScript monorepo.

Scan lifecycle — normalize before judging, gate failures are first-class, verify don't trust.
Monorepo layout
| Package / path | Role |
|---|---|
| packages/core | Engine: detection, scanners, policy, gate, reports, path safety, git + hook helpers, policy validation. Independent of every front-end. |
| crates/veylqorix-engine | Pure-Rust security engine: offline secret scanner, cargo audit, policy resolution, and gate — byte-compatible with packages/core, reached through a TypeScript adapter over a JSON-over-stdio protocol. On main. |
| packages/core/src/engine | The TypeScript adapter: spawns the engine binary, degrades to the byte-compatible TypeScript scanner + policy with an honest note when it is missing. On main. |
| packages/plugin | Scanner extension SDK: teams define custom scanners and quality checks (definePlugin / runPluginAudit); their evidence flows into runAudit and the same gate — no silent passes. Not published to npm yet. |
| apps/cli | The veylqorix command-line interface. |
| packages/mcp-server | MCP server exposing the engine to AI coding agents. |
| packages/api | Dependency-free REST API that runs real scans for the dashboard. |
| packages/skills | Portable AI-agent skill plus per-client MCP configs. |
| apps/web | Landing page + security dashboard (real API data, labeled demo fallback). |
| Veylqorix_Diagrams/ | Five rendered PNG diagrams of the target design, plus the palette README. |
| docs/ | Per-surface documentation: CLI, MCP, API, dashboard, GitHub Actions, engine, FAQ, troubleshooting. |
| tests/ | Unit tests + integration fixtures (fake data only, never real credentials), plus engine-adapter tests that spawn the real Rust binary. |
CLI — veylqorix
The CLI is a thin adapter over the core engine: every result comes from a real scanner run, and a scanner that cannot run is reported as SKIPPED or ERROR, never as a clean pass. It is not published to npm yet — run it from the monorepo build.
veylqorix scan [root] full audit + quality gate veylqorix check [root] quality checks only — no scanners run; always INCOMPLETE (exit 2) veylqorix report [root] Markdown report veylqorix config validate FILE validate a policy veylqorix hooks install|uninstall safe Git hooks
0 PASS gate passed 1 FAIL blocking findings 2 INCOMPLETE coverage degraded — never green 64 usage error 65 bad root / missing policy 70 unexpected error
Options
| Option | Effect |
|---|---|
| --root / --path FILE | Audit a specific root (alias of the positional root argument). |
| --staged | Scope the secret scan to Git-staged files (used by the pre-commit hook). |
| --json | Machine-readable JSON on stdout. |
| --format markdown|json|sarif | Report format. |
| --report-out FILE | Write the Markdown report to a file. |
| --sarif-out FILE | Write a SARIF 2.1.0 report to a file. |
| --offline | Skip network-dependent scanners (no advisory DB pull). |
| --no-tests | Skip test/build quality checks. |
| --scanners a,b | Restrict which scanners run. |
| --block-on a,b | Severities that block the gate. |
| --strict | Stricter exit-code mapping (strictExitCode) — same decision, tighter codes. |
| --policy FILE | Load a custom policy JSON file. |
| hooks --yes / --pre-push / --force | Actually write hooks; add pre-push; back up a foreign hook before replacing. |
The hook installer is safe on purpose
- It never touches
git config. - It backs up any non-Veylqorix hook before replacing it.
- It is a dry run unless you pass
--yes. - Local override:
VEYLQORIX_OVERRIDE=1.
Hooks are a local convenience, not a security boundary. The authoritative enforcement point is the GitHub Actions gate plus branch protection.
MCP — six tools for coding agents
The MCP server exposes the engine to Claude Code, Codex, Cursor, and any MCP client. Inputs are Zod-validated; every response is structured, evidence-based, and redacted. The server only reads and scans — it has no write path.
| Tool | Purpose |
|---|---|
| scan_repository | Full audit: dependency, secret, license, and quality scans plus the gate decision. |
| scan_dependencies | Dependency audit only (npm audit / pip-audit). |
| scan_secrets | Secret detection only; matched values are redacted in the response. |
| run_security_checks | Quality checks only (type, lint, tests). |
| get_findings | Fetch findings for a completed scan, optionally filtered by ids. |
| validate_fix | Re-check a file set after a fix to confirm a finding no longer reproduces. |
{
"mcpServers": {
"veylqorix": {
"command": "node",
"args": ["/abs/path/packages/mcp-server/dist/bin.js"],
"env": {
"VEYLQORIX_ROOTS": "/abs/path/your/project",
"VEYLQORIX_TIMEOUT_MS": "120000"
}
}
}
}Safety properties
- Path confinement — roots are canonicalized;
..traversal and symlink escapes are rejected. Always setVEYLQORIX_ROOTS. - Redaction — secret values are redacted in every tool response, same as CLI and API.
- No write path — the server cannot commit, push, or modify the repository.
- Offline honesty —
VEYLQORIX_OFFLINE=1skips the advisory DB, so the gate can report INCOMPLETE rather than PASS.
REST API — real scans over HTTP
A dependency-free REST API on port 4173 that registers repositories, runs real scans, and serves reports as JSON, Markdown, or SARIF. Every error is structured JSON; paths are validated against VEYLQORIX_ALLOWED_ROOTS when set; secrets are redacted in every response.
The API is loopback-only by default: it binds to 127.0.0.1. Set a non-loopback VEYLQORIX_API_HOST without VEYLQORIX_API_TOKEN and the server refuses to start. In protected/remote mode (a token set), every /api route except GET /api/health requires Authorization: Bearer <token> — a missing or malformed header is a 401, a wrong token a 403. CORS is an exact-origin allowlist from VEYLQORIX_CORS_ORIGINS; no wildcard, never credentialed. State (repositories and scans) is durable in a JSON store; on restart, in-flight RUNNING scans recover as INTERRUPTED — never completed, never lost, single-process.
| Env var | Effect |
|---|---|
| VEYLQORIX_API_TOKEN | Bearer auth; protected/remote mode — required for any non-loopback bind. |
| VEYLQORIX_API_HOST | Bind address. Non-loopback without a token refuses to start. |
| VEYLQORIX_CORS_ORIGINS | Comma-separated exact-origin allowlist; no wildcard, no credentialed wildcard. |
| VEYLQORIX_MAX_CONCURRENT_SCANS | Default 2; over the limit -> 429 with retryAfterSec, and the rejected scan is never recorded. |
| VEYLQORIX_BODY_LIMIT_BYTES | Default 1 MiB; larger bodies -> 413. |
| VEYLQORIX_MAX_FIELD_LENGTH | Default 4096; longer fields -> 400. |
| VEYLQORIX_STORE_PATH | Durable JSON store (default ./.veylqorix-store.json); in-flight scans recover as INTERRUPTED on restart. |
| Endpoint | What it does |
|---|---|
| GET /api/health | Liveness probe — open even in protected mode (no token). |
| POST /api/repositories | Register a repository (403 outside allowed roots). Requires the bearer token in protected mode. |
| GET /api/repositories | List registered repositories. |
| POST /api/scan | Start a scan by repoId or path; returns 202 with a RUNNING scan. 429 (with retryAfterSec) when the concurrency limit is reached — a rejected scan is never recorded. |
| GET /api/scan/:id | Full scan result when complete: gate, coverage, exit code, findings, scanner summaries. |
| GET /api/scan/:id/findings | Findings only. |
| GET /api/scan/:id/report | Report inline (?format=markdown|json|sarif). |
| GET /api/scans | List scans, newest first; ?repoId filter. (0.1.1) |
| GET /api/scans/:id | Full detail for one scan. (0.1.1) |
| GET /api/reports/:scanId | Downloadable report attachment — 202 while running, 404 unknown scan, 400 unknown format. (0.1.1) |
| GET /api/repo/:id/latest | /history | Most recent completed scan, or the full history. |
Dashboard — labeled, never faked
What it shows
- Gate result: PASS / FAIL / INCOMPLETE, with blocking reasons and coverage.
- Normalized findings sorted by severity, with redacted secret values.
- Per-scanner status, so you can see which checks actually ran.
- Scan history for the selected repository.
LIVE vs DEMO MODE
When the API is reachable, the dashboard shows real scan data (LIVE, green). When it is not, it renders clearly-labeled sample data under a DEMO MODE banner (amber). It never presents a demo as a live result.
pnpm --filter @veylqorix/web dev — dashboard on :3000, API on :4173
The API is loopback-only (127.0.0.1) by default, so a local pair needs no token — allow the dashboard's origin in VEYLQORIX_CORS_ORIGINS so the browser fetch succeeds. Exposing it on a non-loopback host requires VEYLQORIX_API_TOKEN; then the dashboard must also send the bearer token.
GitHub security gate

The reusable veylqorix-gate workflow: check out the PR, run a real scan, emit SARIF to code scanning, upload artifacts.
How it works
- Reusable workflow_call — independent of local hooks.
- All actions pinned to commit SHAs; least-privilege permissions.
- Monorepo branch: sets up the Rust toolchain and builds the release engine, so the CLI's adapter can find it (a missing binary is a skipped scanner result, never a failure).
- SARIF output feeds GitHub code scanning; JSON + stderr upload as artifacts.
- On blocking findings or incomplete coverage, it exits non-zero.
advisory → enforced: 4 steps
The enforcement note
The workflow does not block merges by itself. It becomes authoritative when the repository requires its status check via branch protection or a ruleset. Until then it is advisory: findings are produced, the check fails — but a merge can still be forced. That is documented in the workflow file itself.
What the gate will not say
Veylqorix reports what its scanners found. It does not certify the absence of vulnerabilities or secrets. Five things it is honest about, always:
01
Degraded coverage is surfaced, not hidden
Offline mode, a missing pip-audit binary, or a missing lockfile makes a scanner SKIPPED or ERROR — and the gate INCOMPLETE (exit 2), never a pass.
02
Regex secrets have false positives and negatives
The built-in offline rule set complements tools like Gitleaks; it does not replace them. Optional delegation to Gitleaks (preferGitleaks) lives in the Rust engine; unknown formats are not covered.
03
License scanning is manifest-level
It checks declared licenses and copyleft risk in manifests — it is not a transitive license audit.
04
A clean quality check is not a certification
Passing lint, type checks, and tests is evidence — not proof that the code is secure.
05
The gate and hooks are advisory until enforced
Local hooks are bypassable (git commit --no-verify, VEYLQORIX_OVERRIDE=1), and the Actions gate blocks only when a branch-protection rule requires its status check. Until then, a merge can still be forced.
Troubleshooting quick answers
| Symptom | Why | Fix |
|---|---|---|
| Gate reports INCOMPLETE (exit 2) | A scanner errored or was skipped — degraded coverage is never green. | Restore the missing binary / network / lockfile, re-run without --offline. |
| No dependency findings despite a published CVE | Offline mode, a transitive dependency, or a stale advisory-DB pull. | Remove --offline, run a full pnpm install, re-scan. |
| Secret not detected | The built-in offline rule set does not cover every format. | Enable preferGitleaks for higher fidelity in the Rust engine; report the format gap. |
| Dashboard shows demo data | The API is unreachable, so it falls back to labeled sample data. | Start the loopback API on :4173 (127.0.0.1, no token needed; add the dashboard origin to VEYLQORIX_CORS_ORIGINS) — the banner flips to LIVE. |
| hooks install says “not a Git repository” | The installer requires .git/ and will not create a repo. | Run it from inside a Git work tree. |
Ground rules for contributors
Contributing
- No fabricated results — every finding must come from a real scanner run.
- Never weaken the gate to make a test pass.
- Redact secrets everywhere, in code, fixtures, and output.
- No new dependencies without justification.
pnpm build · pnpm typecheck · pnpm lint · pnpm test, plus cargo fmt · clippy · test for the Rust engine — the release checklist runs all of it.
The codebase, as it is
- MIT licensed — see LICENSE.
- Code of Conduct: Contributor Covenant v2.0.
- Accessibility commitment with known limitations, documented in ACCESSIBILITY.md.
- Threat model and disclosure policy in SECURITY.md.
- Test fixtures contain only fake, well-known placeholder values.
Veylqorix surfaces incomplete audits instead of green-washing them. The gate is advisory until you enforce it, and it says so in the workflow file.