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.

Overview

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.

Veylqorix system architecture: entry points, integration layer, core engine, and results surfaces

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

Veylqorix scan lifecycle: code change to normalized findings to gate decision to verified fix

Scan lifecycle — normalize before judging, gate failures are first-class, verify don't trust.

Monorepo layout

Package / pathRole
packages/coreEngine: detection, scanners, policy, gate, reports, path safety, git + hook helpers, policy validation. Independent of every front-end.
crates/veylqorix-enginePure-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/engineThe 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/pluginScanner 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/cliThe veylqorix command-line interface.
packages/mcp-serverMCP server exposing the engine to AI coding agents.
packages/apiDependency-free REST API that runs real scans for the dashboard.
packages/skillsPortable AI-agent skill plus per-client MCP configs.
apps/webLanding 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.
Surface 01

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.

commandsveylqorix
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
exit codesveylqorix
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

OptionEffect
--root / --path FILEAudit a specific root (alias of the positional root argument).
--stagedScope the secret scan to Git-staged files (used by the pre-commit hook).
--jsonMachine-readable JSON on stdout.
--format markdown|json|sarifReport format.
--report-out FILEWrite the Markdown report to a file.
--sarif-out FILEWrite a SARIF 2.1.0 report to a file.
--offlineSkip network-dependent scanners (no advisory DB pull).
--no-testsSkip test/build quality checks.
--scanners a,bRestrict which scanners run.
--block-on a,bSeverities that block the gate.
--strictStricter exit-code mapping (strictExitCode) — same decision, tighter codes.
--policy FILELoad a custom policy JSON file.
hooks --yes / --pre-push / --forceActually 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.

Surface 02

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.

ToolPurpose
scan_repositoryFull audit: dependency, secret, license, and quality scans plus the gate decision.
scan_dependenciesDependency audit only (npm audit / pip-audit).
scan_secretsSecret detection only; matched values are redacted in the response.
run_security_checksQuality checks only (type, lint, tests).
get_findingsFetch findings for a completed scan, optionally filtered by ids.
validate_fixRe-check a file set after a fix to confirm a finding no longer reproduces.
.mcp.jsonveylqorix
{
  "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 set VEYLQORIX_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=1 skips the advisory DB, so the gate can report INCOMPLETE rather than PASS.
Surface 03

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 varEffect
VEYLQORIX_API_TOKENBearer auth; protected/remote mode — required for any non-loopback bind.
VEYLQORIX_API_HOSTBind address. Non-loopback without a token refuses to start.
VEYLQORIX_CORS_ORIGINSComma-separated exact-origin allowlist; no wildcard, no credentialed wildcard.
VEYLQORIX_MAX_CONCURRENT_SCANSDefault 2; over the limit -> 429 with retryAfterSec, and the rejected scan is never recorded.
VEYLQORIX_BODY_LIMIT_BYTESDefault 1 MiB; larger bodies -> 413.
VEYLQORIX_MAX_FIELD_LENGTHDefault 4096; longer fields -> 400.
VEYLQORIX_STORE_PATHDurable JSON store (default ./.veylqorix-store.json); in-flight scans recover as INTERRUPTED on restart.
EndpointWhat it does
GET /api/healthLiveness probe — open even in protected mode (no token).
POST /api/repositoriesRegister a repository (403 outside allowed roots). Requires the bearer token in protected mode.
GET /api/repositoriesList registered repositories.
POST /api/scanStart 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/:idFull scan result when complete: gate, coverage, exit code, findings, scanner summaries.
GET /api/scan/:id/findingsFindings only.
GET /api/scan/:id/reportReport inline (?format=markdown|json|sarif).
GET /api/scansList scans, newest first; ?repoId filter. (0.1.1)
GET /api/scans/:idFull detail for one scan. (0.1.1)
GET /api/reports/:scanIdDownloadable report attachment — 202 while running, 404 unknown scan, 400 unknown format. (0.1.1)
GET /api/repo/:id/latest | /historyMost recent completed scan, or the full history.
Surface 04

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.

Surface 05

GitHub security gate

Veylqorix GitHub pull-request security gate flow from PR to enforced check

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.

Honest limitations

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

SymptomWhyFix
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 CVEOffline mode, a transitive dependency, or a stale advisory-DB pull.Remove --offline, run a full pnpm install, re-scan.
Secret not detectedThe 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 dataThe 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.
Community

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.
docs/faq.md — the short version