Expand description
The analyzer execution seam: one contract, interchangeable backends.
Running an external analyzer (cargo-audit, semgrep, successors) can happen
in CI, on a developer’s machine, or — later — locally inside a sandbox. This
crate exists so those stop being competing architectures: every backend
implements one AnalyzerRunner trait, takes one AnalysisRequest, and
returns one AnalysisResponse of normalized findings plus run evidence. A
caller never learns which backend produced a result, so adding the sandboxed
and subprocess backends later changes no call site.
Today there is exactly one implementation, IngestRunner, which consumes a
normalized report produced elsewhere. It is the zero-install default, not a
fallback: it needs no container runtime and adds no isolation surface, and
what it produces is byte-for-byte the shape a sandboxed run will produce.
§What this crate does not do
It does not decide how results are stored. Persistence lives in rto-graph,
which files findings in their own tables — never nodes/edges, never a
provenance class, never in the exported graph artifact (ADR-0012). Nothing
here can move the published GraphArtifact by a byte, and that is checked by
test rather than assumed.
No analyzer is implemented here, and no sandbox dependency is pulled in; the backends arrive behind their own features (ADR-0014).
@rto:0014 @rto:0012
§Example
use rto_exec::{AnalysisRequest, AnalyzerRunner, Consent, IngestRunner, Worktree};
use rto_graph::SourceIdentity;
let report = br#"{
"schema": "roteiro.findings/v1",
"analyzer": "cargo-audit",
"analyzer_version": "0.21.0",
"started_at": "2026-08-15T09:00:00Z",
"ended_at": "2026-08-15T09:00:04Z",
"exit_status": 1,
"findings": [{
"identity": ["RUSTSEC-2024-0001", "openssl", "0.10.5", "lock123"],
"rule": "RUSTSEC-2024-0001",
"severity": "high",
"title": "openssl is vulnerable",
"message": "upgrade to 0.10.66"
}]
}"#;
let request = AnalysisRequest {
analyzer: "cargo-audit".to_owned(),
worktree: Worktree::read_only("/repo".as_ref()).expect("worktree"),
network: rto_graph::NetworkPolicy::Deny,
consent: Consent::Granted,
source: SourceIdentity::default(),
};
let response = IngestRunner::new(report.to_vec()).run(&request).expect("ingest");
assert_eq!(response.findings.len(), 1);
assert_eq!(response.run.isolation, rto_graph::Isolation::Ingested);Re-exports§
pub use adapter::ADAPTERS;pub use adapter::Adapter;pub use adapter::AssetPaths;pub use adapter::Invocation;pub use adapter::NO_SNIPPET;pub use adapter::NativeContext;pub use adapter::UNKNOWN_VERSION;pub use adapter::adapter_for;pub use adapter::known_analyzers;pub use adapter::snippet_hash;pub use adapter::snippet_hash_at;pub use crossref::Correspondence;pub use crossref::Report;pub use crossref::cross_reference;pub use snippet::NoSnippets;pub use snippet::SnippetSource;pub use snippet::WorktreeSnippets;
Modules§
- adapter
- Per-analyzer adapters: native analyzer output in, a
NormalizedReportout. - crossref
- Cross-referencing dependency findings across analyzers.
- snippet
- The source text a finding points at, read from the analyzed worktree.
Structs§
- Analysis
Request - What a caller asks a backend to do.
- Analysis
Response - What a backend returns: normalized findings plus the evidence for the run that produced them.
- Ingest
Runner - Consumes a normalized report and yields the same values any other backend would.
- Normalized
Report - A normalized analyzer report — the interchange format
roteiro security ingestconsumes and every analyzer adapter emits. - Report
Finding - One finding as it appears in a normalized report.
- Worktree
- The worktree an analyzer is pointed at.
Enums§
Constants§
- MAX_
REPORT_ FINDINGS - The most findings accepted from one report.
- REPORT_
SCHEMA - Schema tag every normalized report must carry. Bump on a breaking change to
the report format, exactly as
rto_graph::ARTIFACT_SCHEMAdoes for the graph artifact.
Traits§
- Analyzer
Runner - One analyzer backend.
Functions§
- age_
in_ days - Whole days between two RFC 3339 UTC timestamps,
Noneif either will not parse. - check_
reported_ path - Reject a reported path that is absolute or climbs out of the worktree.
- check_
request - The preflight every backend shares: explicit consent, denied egress, a read-only worktree, and a well-formed analyzer id.
- normalize_
native - Turn one analyzer’s native output into a normalized report, using that analyzer’s adapter.
- rfc3339_
from_ unix - Format
secsseconds since the Unix epoch as RFC 3339 UTC. - rfc3339_
utc - Format a
SystemTimeas RFC 3339 UTC with second granularity (2026-08-15T09:00:04Z). - sha256_
hex - Lowercase hex SHA-256 of
bytes. - unix_
from_ rfc3339 - Parse
YYYY-MM-DDor a full RFC 3339 UTC timestamp to seconds since the epoch. Deliberately strict and small: it accepts whatrfc3339_from_unixemits and the date-only form advisory databases publish, and refuses anything else rather than guessing an offset. - worktree_
id - Derive a stable, opaque id for the checkout at
path.