Expand description
The read-only documents security list / security status return over a
model-facing tool surface.
Ungated, like guidance and lint_grant, and for a related reason: what
a read owes its reader is not a property of which backends were compiled in.
It is also the one place either document is built — the CLI’s security status shares its coverage matrix and staleness rows from here, so
possibly_stale and ready are one computation rather than three. Read the
module for the two hazards it exists to remove: an empty listing that reads as
a clean one, and a status blob whose two halves have different scopes.
The read-only security list / security status documents the
model-facing tool surfaces return.
roteiro security list and roteiro security status are the two security
subcommands that read and never write, so they are the two that may be
exposed to a model at all — the other three (ingest, run, prefetch) are
permanent refusals, and rto_render::mcp’s module documentation carries the
disposition table with each reason. What this module adds is the two things a
CLI does not need and a tool surface cannot do without.
§1. An empty listing must not read as a clean one
roteiro security list --json is 36 bytes on a repository no analyzer has
ever run against: {"layers": [], "findings": 0}. “Nothing has been
analyzed” and “an analyzer ran and found nothing” are opposite facts, and
findings: 0 reads as the second while meaning the first. A model that
reports “no security findings” from that document is confidently wrong, and it
is the single most likely misuse of these tools.
The data does distinguish them — a clean run leaves a live layer whose
findings is empty, and no run leaves no layer — so this is a defect in the
document, not in the store. Coverage fixes it the way
rto_spec::tool_check’s Gate fixes the same hazard for check: a
discriminator that is always present, and the payload omitted entirely in
the case that has no answer. A consumer reaching for findings in a
Coverage::NoAnalyzerOnRecord document finds no report at all, rather
than finding nothing-wrong.
§2. security status is two halves with two different scopes
The CLI’s status output reads the machine-global asset cache
(crate::asset_root, crate::status) and the current repository’s
findings layers, and prints them as one screen. On a CLI that is invisible and
harmless: one process, one repository, one machine.
Over a tool surface it is neither. A caller selects a project (ADR-0008), so the layer half follows the selected project and the asset half does not — those digests describe the machine the server runs on, whichever project was asked about. A model handed one flat blob has no way to tell which half is which, and “this repository’s analyzers are not provisioned” is a claim the asset half cannot support.
So the split is in the output, not only in this comment:
ToolSecurityStatus has exactly two named sections, each carrying an
explicit scope field, and each scope’s identifying value lives inside its
own section — the asset root under machine, the project name under
repository. Neither half can be quoted without its scope travelling with it.
§3. A readiness claim names what it has actually checked
roteiro security status used to label one analyzer ready on the strength of
its pinned assets being provisioned. Running it needs a second thing — the
analyzer’s own program on PATH — and that is the one Roteiro deliberately
never installs (ADR-0014). So on a host with the rules provisioned and
semgrep absent, the old report read semgrep ready and the run then failed
with analyzer binary not found on PATH. Both statements were true about
different things and only one of them used the word ready (issue #464).
docs/REVIEW_CHECKLIST.md has the rule this is a corollary of — a refusal
names the way forward — applied to a report rather than a refusal: a
readiness claim names what it has actually checked. And it is the same shape
as §1, one field over: a caller that cannot run command -v — which is every
caller on a tool surface — will read ready as this will run.
Readiness is therefore three states rather than a bool, because the
remedy differs: assets-not-provisioned is fixed by prefetch, which
Roteiro performs; binary-not-found is fixed by an install, which it refuses
to perform; ready is both. Both underlying facts are reported alongside it,
so a host missing both is fully readable in one call rather than in two.
@rto:0012 @rto:0018
Structs§
- Analyzer
Coverage - What one shipped analyzer covers — the coverage matrix, read off the code rather than off a document, so the two cannot drift apart unnoticed.
- Cross
Reference - One advisory in the cross-reference (ADR-0018 v1.1), as a serialisable view.
- Cross
Reference Report - One analyzer’s report inside a
CrossReference. - Layer
Staleness - The staleness of the advisory data behind one live findings layer.
- Machine
Scope - The machine-global half of a status document.
- Repository
Scope - The per-repository half of a status document.
- Security
List Report - The listing itself, present only when an analyzer result is on record.
- Tool
Findings Layer - One live layer: its run evidence, and a bounded page of its findings.
- Tool
Security List - The tool-surface
security listresult. - Tool
Security Status - The tool-surface
security statusresult: two scopes, never one blob.
Enums§
- Coverage
- Whether any analyzer result is on record, as a value rather than an absence.
- Readiness
- Whether one analyzer can actually be run on this host, as one word.
Constants§
- TOOL_
SECURITY_ LIST_ SCHEMA - Schema tag for the tool-surface
security listdocument. - TOOL_
SECURITY_ STATUS_ SCHEMA - Schema tag for the tool-surface
security statusdocument.
Functions§
- coverage_
matrix - The coverage matrix for
analyzer(or every shipped analyzer), with each one’s readiness resolved against the asset cache atrootand this process’sPATH. - coverage_
matrix_ with coverage_matrixwith thePATHprobe supplied by the caller.- layer_
staleness - The advisory-staleness rows for
layers, aged againstnow(an RFC 3339 timestamp, ascrate::rfc3339_utcrenders one). - security_
list - Build the tool-surface
security listdocument from a project’s live layers. - security_
status - Build the tool-surface
security statusdocument.