Dependencies and team facts¶
Two jobs answer questions about the whole project, not about a single translation unit. One job reports what the project depends on. The other reports what the repository attaches people’s names to. Both jobs produce results, and not console decoration. They travel to the terminal, over the server protocol and into a saved result. They take the same road as the symbol table and the findings.
Neither produces a score. The SBOM says what the manifests say; the
authorship job says what git says. Every consumer prints the
caveats next to the numbers, and this page states them too.
SBOM¶
Running it¶
visao --sbom --sbom-root ~/proj -- ~/proj/main.c
visao --sbom-output sbom.json --sbom-root ~/proj -- ~/proj/main.c
--sbomCollect the dependencies and carry them in the result. The console prints a Packages section.
--sbom-output <file>Also write the document. This flag implies
--sbom. The file and the result section hold the same facts in two shapes.--sbom-root <dir>Where to look. The default is the directory of the first analysed input. That default fits a run over a project tree. Name the directory yourself when you analyse one file outside the tree.
--sbom-format <cyclonedx|spdx>Document format. Default
cyclonedx(CycloneDX 1.5).
The walk skips .git, target, node_modules, vendor,
dist, build, out, .cache, __pycache__, .venv
and venv, and every dot-directory. A vendored copy of another
tree belongs to that tree, so the walk leaves it out.
What is discovered¶
Ecosystem |
Files read |
|---|---|
Cargo (Rust) |
|
npm (Node.js) |
|
PyPI (Python) |
|
Go modules |
|
vcpkg (C/C++) |
|
Conan (C/C++) |
|
Maven (Java) |
|
Boss (Delphi) |
|
Versions: resolved or merely asked for¶
A manifest states a constraint. A lock file states a version. The analyser reads both, collapses entries on (ecosystem, name), and keeps the two facts apart:
versionThe resolved version when a lock file exists. Without a lock file it is the text the manifest spelled, which can be a range.
declaredThe manifest’s constraint, when it differs.
resolvedTrue when
versioncame from a lock file.
• serde@1.0.219 (cargo)
↳ manifest asks for: 1.0.100 (version above is what the lock file resolves to)
• express@^4.18.0 (npm)
↳ a constraint, not a resolved version — no lock file was found
go.mod pins by construction, so its versions are exact without a
lock file. requirements.txt and pyproject.toml fill the version
only for == / ===; a >= leaves it empty.
Nothing contacts a registry. The analyser reads only the files in the tree. It never asks the ecosystem to resolve a range.
Licenses¶
Each package carries the license its manifest declared. An empty field means the manifest declared no license.
A policy file turns that into findings:
visao --sbom --sbom-license-policy policy.txt --sbom-root ~/proj -- ~/proj/main.c
# policy.txt — one verb per line, '#' comments
allow MIT
allow Apache-2.0
deny AGPL-3.0
With any allow line the policy is a whitelist: a package passes
only if one of its SPDX atoms is allowed. With deny lines alone it
is a blacklist. OR expressions pass on their most permissive atom.
Violations surface as sbom/license/violation findings.
Vulnerabilities¶
visao --sbom --sbom-vuln-db ~/osv -- ~/proj/main.c
The argument is an OSV record file or a directory of them (one JSON
object per file). Matches surface as sbom/vulnerability findings
and attach to their package in the result section.
The match is exact when the version is resolved. For an unresolved
version the analyser uses the floor of the constraint, which is the
lowest version the build can install. The flag resolved = false
travels with the package, so a consumer reports that answer as an
approximation. A wildcard takes the advisory’s own “no version
information” branch, which stays on the safe side.
Comparing two snapshots¶
visao --sbom-output current.json --sbom-diff previous.json \
--sbom-diff-output delta.json --sbom-root ~/proj -- ~/proj/main.c
The diff reports added, removed and version-bumped packages as
sbom/diff/added, sbom/diff/removed and sbom/diff/bumped.
Gating a pipeline¶
SBOM findings are ordinary findings, so everything in
CI/CD integration applies. This includes --report-format sarif
and --baseline:
visao --sbom --sbom-vuln-db ~/osv --sbom-license-policy policy.txt \
--fail-on high --report-format sarif --report-output visao.sarif \
-- build/compile_commands.json
Coding standards¶
visao --standard misra-c-2012 -- src/*.c
A standard does two things. First, the rules that exist only because
the standard requires them start firing. These rules cover banned
library functions, braces around every control-statement body, and a
default on every switch. Second, each finding that answers to one
of its rules carries the rule identifier, in the console, in SARIF and
over the protocol.
The run ends with a compliance summary. It states how many rules the standard has, how many this build checks, and how many stay unchecked. It names the unchecked rules.
▎ Compliance (174)
• MISRA C:2012
↳ rules in the standard: 174
↳ checked by this build: 67
↳ checked rules with findings: 19
↳ Rule 21.3 (Required) — 2 finding(s): Use of the memory-allocation functions
↳ not checked by this build: 107
↳ Dir 1.1 (Required), Dir 3.1 (Required), …
The summary speaks for the rules this build checks. Compliance rests on the standard’s document and the project’s deviation records. This summary is evidence for that argument.
--standard-rules <file> takes a different rule set: an amended
edition, or a project’s own selection. Write one rule per line as
<rule>[,<category>]. The summary counts the rules from that file
that this build knows, and it counts the rest apart.
MISRA findings are ordinary findings, so --report-format sarif,
--baseline and --fail-on work on them as on everything else.
Team facts¶
Commit facts alone¶
visao --history main..HEAD
Prints the same facts and exits. It needs no analysis and no files.
How to read the numbers¶
Commit and line counts measure volume, not value, and reward the wrong things when used as a target.
The assistant co-author line is a declaration by the author. Its absence is not evidence of anything.
“Region worked again later” overlaps line ranges as each commit recorded them. Lines drift, so read it as a region, not as a proof.
“A later fix-shaped commit” is a word match on the subject. Iteration and repair look the same from here.
Visao derives no score from these numbers.
Reviewing a change¶
visao --since main -- src/*.c # only lines the change touched
visao --since main --since-whole-file -- src/*.c
--since compares the revision against the working tree, so it
includes uncommitted work. A changed file usually carries older
findings from outside this change. Use --since-whole-file to see
them too, because a change can break a line it never touched.
Over the server¶
Both are job kinds, requested at start and answered in their own
section of the result:
asp-cli connect tcp://127.0.0.1:5555 \
ws:add file /proj/main.c \
an:options sbom_root=/proj sbom_vuln_db=/proj/osv \
start defects sbom authorship wait result
sbom also runs on its own (start sbom). Its work happens when
the job instance is built, and not in an analysis pass. authorship
attributes findings to an analysis, and it reports commit facts
without one.
Options are set on the workspace before start, as key=value
pairs:
Key |
Meaning |
|---|---|
|
directory to scan |
|
OSV file or directory |
|
policy file |
|
|
|
write the document (server-side path) |
|
previous SBOM to compare against |
|
where to write the diff |
|
git range for the authorship job |
|
attribute findings without |
|
analyse a change against a revision |
The paths are on the machine of the analyser. The result sections
carry the answer for that reason: sbom_data and
authorship_data arrive in the response. A client that reads no
file on the server still gets the whole answer.
Facts about the data¶
A range stays a range, because nothing contacts a registry. Without a lock file the version stays a constraint, and the output says so.
Transitive dependencies appear only insofar as a lock file lists them; a manifest alone gives direct dependencies.
Vulnerability matching is only as current as the OSV data you point it at; nothing is downloaded.
git blameattribution is a starting point for a conversation, not an assignment of responsibility.