Summary
Extract @opencodehub/scanners (the 22-tool SAST wrapper package) out of OCH's core. It produces SARIF but contributes nothing to code retrieval or understanding — the graph/pack/retrieval surface consumes SARIF through a separate, cheap layer (@opencodehub/sarif + ingest-sarif) that has zero dependency on the wrappers. Moving codehub scan to a bring-your-own-SARIF model sheds ~5.3K LOC and 17 external tool binaries (plus their CVE/version churn) with zero loss of retrieval capability.
Why (grounded in origin/main)
Production and consumption of findings are already decoupled:
packages/pack/src/findings.ts builds the findings BOM slice from store.listFindings() — i.e. findings already in the graph, not from running scanners. It imports @opencodehub/sarif (types), never @opencodehub/scanners.
packages/cli/src/commands/ingest-sarif.ts (codehub ingest-sarif <file>) accepts any SARIF v2.1.0 log → @opencodehub/analysis → graph FindingNodes. Its only OCH imports are @opencodehub/sarif, @opencodehub/analysis, @opencodehub/core-types.
- None of
storage, ingestion, pack, search, or analysis import @opencodehub/scanners. Verified:
grep -rn "@opencodehub/scanners" packages/{storage,ingestion,pack,search,analysis} --include='*.ts' | grep -v '.test.ts'
# → (no matches)
So SARIF production (the wrappers) is orthogonal to SARIF consumption (graph + pack + retrieval). If a repo runs its own SAST and emits SARIF, codehub ingest-sarif already folds it into the graph and the findings BOM works unchanged. The wrappers are the redundant middle.
What the wrappers cost
packages/scanners: 5,303 LOC — 3,513 prod (1,637 in 22 wrappers · 718 in 6 SARIF converters · 1,158 in runner/catalog/exec/file-context) + 1,790 test. All orthogonal to retrieval.
- 17 external binaries to keep alive across OS/arch:
semgrep, bandit, betterleaks, grype, trivy, osv-scanner, checkov, hadolint, ruff, ty, radon, vulture, clamav, spectral, tflint, pip-audit (+ biome, docker-compose).
- A meaningful share of the nightly Dependabot / CVE / version churn is these tools, not OCH itself.
Consumers to migrate (3 source + 1 test)
| File |
Uses |
Action |
packages/cli/src/commands/scan.ts |
runScanners, ~8 *_SPEC, types |
Reduce to BYO-SARIF shim or remove |
packages/mcp/src/tools/scan.ts (registered in server.ts:171) |
runScanners, createDefaultWrappers, specs |
Remove the scan MCP tool or repoint to ingest |
packages/cli/src/commands/doctor.ts (+ doctor.test.ts) |
BANDIT_SPEC for env checks |
Inline the one spec constant or drop the check |
Plan
Phase 1 — Decouple (no deletion yet)
Phase 2 — Deprecate the runner
Phase 3 — Remove
Non-goals
- Not removing findings from the pack BOM — that stays, sourced from graph ingestion.
- Not touching
@opencodehub/sarif — it's the cheap core-format layer and is kept.
- Not touching the standalone CI security jobs (
semgrep.yml, grype, osv, betterleaks) — those are upstream Actions, independent of the wrappers.
Net
Shed ~5.3K LOC + 17 tool dependencies + their CVE churn, lose zero retrieval/understanding capability. Findings-in-graph survives on ingestion alone.
Filed by Bonk nightly maintenance follow-up. Architecture grounded against origin/main.
Summary
Extract
@opencodehub/scanners(the 22-tool SAST wrapper package) out of OCH's core. It produces SARIF but contributes nothing to code retrieval or understanding — the graph/pack/retrieval surface consumes SARIF through a separate, cheap layer (@opencodehub/sarif+ingest-sarif) that has zero dependency on the wrappers. Movingcodehub scanto a bring-your-own-SARIF model sheds ~5.3K LOC and 17 external tool binaries (plus their CVE/version churn) with zero loss of retrieval capability.Why (grounded in
origin/main)Production and consumption of findings are already decoupled:
packages/pack/src/findings.tsbuilds the findings BOM slice fromstore.listFindings()— i.e. findings already in the graph, not from running scanners. It imports@opencodehub/sarif(types), never@opencodehub/scanners.packages/cli/src/commands/ingest-sarif.ts(codehub ingest-sarif <file>) accepts any SARIF v2.1.0 log →@opencodehub/analysis→ graphFindingNodes. Its only OCH imports are@opencodehub/sarif,@opencodehub/analysis,@opencodehub/core-types.storage,ingestion,pack,search, oranalysisimport@opencodehub/scanners. Verified:So SARIF production (the wrappers) is orthogonal to SARIF consumption (graph + pack + retrieval). If a repo runs its own SAST and emits SARIF,
codehub ingest-sarifalready folds it into the graph and the findings BOM works unchanged. The wrappers are the redundant middle.What the wrappers cost
packages/scanners: 5,303 LOC — 3,513 prod (1,637 in 22 wrappers · 718 in 6 SARIF converters · 1,158 in runner/catalog/exec/file-context) + 1,790 test. All orthogonal to retrieval.semgrep, bandit, betterleaks, grype, trivy, osv-scanner, checkov, hadolint, ruff, ty, radon, vulture, clamav, spectral, tflint, pip-audit(+biome,docker-compose).Consumers to migrate (3 source + 1 test)
packages/cli/src/commands/scan.tsrunScanners, ~8*_SPEC, typespackages/mcp/src/tools/scan.ts(registered inserver.ts:171)runScanners,createDefaultWrappers, specsscanMCP tool or repoint to ingestpackages/cli/src/commands/doctor.ts(+doctor.test.ts)BANDIT_SPECfor env checksPlan
Phase 1 — Decouple (no deletion yet)
codehub ingest-sarifhandles every SARIF shape the wrappers emit today (baseline-diff, suppression,applyBaselineState). These already live in@opencodehub/sarif, so this should be a no-op verification..github/workflows/och-self-scan.yml, currently runscodehub scan .) to consume the SARIF from the existing upstreamsemgrep.ymljob →codehub ingest-sarif. This dogfoods the BYO path.release.ymlsignsoch-scan.sarifinto the attested bundle (sha256'd into provenance). Options: (a) drop it from the release contract, or (b) source it from the upstream semgrep job. Needs a deliberate call — the re-derivable SARIF/license/owners BOM is OCH's differentiator, and this is the only place scan output touches it.Phase 2 — Deprecate the runner
codehub scan→ deprecation-warning shim pointing toingest-sarif(keeps the command name working for one release with a clear migration message).scanMCP tool registration, or repoint it to ingest existing SARIF.doctor.ts— inlineBANDIT_SPECor drop the env check.Phase 3 — Remove
packages/scanners.mise.toml/ CI.Non-goals
@opencodehub/sarif— it's the cheap core-format layer and is kept.semgrep.yml,grype,osv,betterleaks) — those are upstream Actions, independent of the wrappers.Net
Shed ~5.3K LOC + 17 tool dependencies + their CVE churn, lose zero retrieval/understanding capability. Findings-in-graph survives on ingestion alone.
Filed by Bonk nightly maintenance follow-up. Architecture grounded against
origin/main.