Repository navigation
Lane A end to end: anvil scan, the daemon, and the first-run contract fixes - #18
Merged
Merged
Conversation
…icy, repo collector Wiring anvil scan end to end surfaced mismatches no unit test could see, and each is fixed where it lives: - Record: anvil/target.provisioning is absent exactly when no target was declared. Both legal values describe a runtime target, so every core-only audit had to state a provisioning path that never happened, and record emission's own validation envelope did. - Record: Validate counted only a sealed half toward anvil/state, while the sealer advances the state on any terminal half. It refused the sealer's own output for an audit whose SAST half failed; it now uses the sealer's rule. - Record: Assemble, the record assembler the contract names and nothing implemented, builds and validates a SAST-only audit from the sealer's snapshot. Its index maps are empty objects, and emission's cveIds an empty array, because the wire schema rejects null for both. - Store: Open applies ConnectionPragmas on every connection (foreign keys were otherwise off) and migrates; WriteScan records scan_run, audit_record with the zstd payload, and the findings, marking each new, persisting, regressed or fixed by fingerprint. A finding is fixed only by a cleanly sealed, complete scan of the detectors it came from. - Policy: Load and DecodeYAML read .anvil/policy.yml in production; the only decoder was a test helper. It refuses oversized files, deep nesting, and anchors, aliases, tags and block scalars. - Repo collector: Database reports the Trivy database's build time, the as_of of every Trivy-decided finding. - internal/distro: the one release vocabulary (debian-12, alpine-3.19, rhel-9) shared by ingestion, the host scan and the cache-backed source.
…end to end cmd/anvil replaces the bootstrap placeholder with a thin command over the tested packages, and internal/scan is the production caller the Lane A ledger reported missing: trigger policy, scan controller, collection, comparison, emission, seal, assembly, masking, the store and SARIF out. The identity seams the conformance harness found are closed in their owners: ingestion writes distro ranges in the comparator's scheme with the release in the purl's distro qualifier; scan.HostRecords builds each host purl from os-release; scan.CacheSource consults only the host release's ranges, so a Debian 11 advisory never decides a Debian 12 package; and repository findings, which Trivy has already decided, go to emission directly under the owner's accelerator decision of 2026-10-03: off unless the operator's configuration enables the Trivy database, tier-2 attribution on every finding when it does. - anvil scan --repo / --host: exit 0 clean, 1 findings, 2 usage, 3 refused, 4 missing tool, 5 error. A host scan reads the collector's inventory and never collects itself. - anvil daemon keeps feeds fresh through delta.Syncer and runs dispatched scans from a spool, each through the trigger policy; scheduled full scans are anvil-full-scan@.timer one-shots. - anvil feeds import loads an offline snapshot through the same licence gate, decoders and cache writes as live ingestion. testdata/lanea-fixture is one, with two host inventories and a repository for the regression marks. - The conformance harness calls the production code instead of its stand-ins and proves 10 of 12 links where Trivy and its database exist. - CI's new anvil end to end job runs test/e2e/fixture.sh on a clean checkout and validates every record against the wire schema.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 4's vertical slice (plan nodes
clianddaemon):anvilstops printing "bootstrap placeholder" and runs Lane A end to end.What runs
anvil scan --repo PATHandanvil scan --host --inventory FILE|-: trigger policy → scan controller → collection → comparator → record emission → SAST seal → record assembly → masking → store (WAL,BEGIN IMMEDIATE) → SARIF out.anvil daemonkeeps feeds fresh throughdelta.Syncerand runs dispatched scans from a spool, each through the trigger policy. Scheduled full scans areanvil-full-scan@.timerone-shots.anvil feeds import DIRloads an offline snapshot through the same licence gate, decoders and cache writes as live ingestion.anvil findingsreads the store back.anvil scan --hostnever collects an inventory itself. It reads what the collector writes under its unit (deploy/systemd/README.mdexplains the handoff and its open item).Mismatches the first run found, fixed in their owning packages
policy.Load/DecodeYAMLpromote the test decoder, hardened for files from the repository under scan.record.Assemblebuilds and validates a SAST-only audit from the sealer's snapshot.anvil/target.provisioningwas required with no truthful value for an audit that declared no target. It is now absent exactly then; emission's own envelope had been writing a false value.Validateand the sealer disagreed about a failed half.Validatenow counts terminal halves, as the sealer does.cveIds; the Go validator could not see it. Both fixed, and CI now validates every record against the schema.internal/distro), host purls come from os-release, and the cache-backed source is release-scoped, so a Debian 11 advisory never decides a Debian 12 package. Repository findings Trivy decided go to emission directly.The owner's accelerator decision (2026-10-03)
The Trivy database is off by default. Repository SCA runs only when the operator's configuration enables it, never by a flag, and every finding it produces carries tier-2 attribution (
LicenseRef-Anvil-TrivyDB-Tier2). With it off,anvil scan --repoexits 3.Evidence
sh test/e2e/fixture.shpasses on Debian 13: two host scans (3 new; then 1 new, 2 persisting, 1 fixed), a refused collector-less host scan, a real Trivy repository scan (7 lodash findings, all tier-2), and all three records valid againstschemas/anvil-record-v1.schema.json.gofmt,go vet,go test -count=1 ./...(with and without Trivy on PATH),go test -race -count=1 ./...and the eval suite are green.