feat: bring facts generation up to date with the shipping pipeline - #7
feat: bring facts generation up to date with the shipping pipeline#7Jeppe Fredsgaard Blaabjerg (jfblaa) wants to merge 5 commits into
Conversation
Reconciles the shared pipeline with socket-cli's current generation, so a consumer can swap its vendored emitters for this package without its own tests or snapshots moving. All four of socket-cli's shared-pipeline suites are ported verbatim and pass with no assertion edits. Squashed from 23 commits: intermediate states carried tracker references, and this repository is public, so they must not reach its history. The logical chunks were: - sidecar: keyed by absolute facts-file path, with entries carried through verbatim from the facts SBOM plus resolved paths, and no cross-reactor dedup - exclude paths: one compiler, and each emitter only compiles the patterns it is handed; three per-language glob implementations deleted - dotnet: honours excludePaths, so a wholly excluded project emits no records - workspaces: the enumeration emitter family moves in, both lifecycle participants ship in the one shaded jar, and both emitter families share one parameterized invocation path - pipeline: a coordinate that is both a resolved node and a first-party project reports the project's output roots, not its published jar - sbt: the caller can own the global base, which withFiles artifact paths point into and which was previously deleted before the caller could read them - invocation: this package passes its own build-tool properties AFTER the caller's options, because every tool resolves a repeated property last-one-wins and a caller option could otherwise unload the emitter - gates: the repo check now type-checks src/ and test/, which the fleet check config covers neither of; a missing built emitter asset is built on demand instead of silently skipping conformance tests - conformance: a dotnet fixture holds that resolver to resolve-once, diffed against MSBuild's own property evaluation rather than a golden file - docs: private-repo references removed, and the trust boundary states the consumer's vetting obligation directly
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 4c77702. Configure here.
| acc: SidecarAccumulator, | ||
| facts: SocketFactsSbom, | ||
| artifactPaths: ResolvedArtifactPaths, | ||
| factsFile: string, |
There was a problem hiding this comment.
Fuzz sidecar missing facts key
Medium Severity
accumulateSidecar now requires a factsFile key for the new path-scoped sidecar, but the records fuzz target still calls it with three arguments. At runtime that stores under undefined, so serializeSidecar emits a bucket keyed by "undefined". The fuzz then validates that wrong shape and no longer guards the absolute .socket.facts.json key contract this PR introduced. The new sources-are-type-checked gate only includes test/**/*.mts, so this .ts fuzz file is never type-checked either.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 4c77702. Configure here.
There was a problem hiding this comment.
Fixed in 976de4f — both halves were real.
The call. accumulateSidecar now gets a factsFile, and the fuzz asserts the payload has exactly that one key. The second part matters because the validator accepts any string key, so the fuzz was passing on a payload keyed literally "undefined" and guarding nothing about the contract this PR introduces. accumulateSidecar always sets exactly one key, so the assertion is safe for arbitrary input.
The gate. I tried widening it to test/**/*.ts and backed it out: the fuzz framework there is an optional devDependency that is not installed, and the .ts extension lands in CommonJS resolution while the tree is .mts/ESM — so including it turned the gate red on a fresh clone for unrelated reasons. It stays .mts-only, with the gap recorded in the check script rather than left implicit.
Verified by running the fuzz body logic through vitest on empty, garbage and real records input, since the fuzz runner cannot run locally.


This package was seeded from socket-cli's manifest emitters and has not tracked it since, so the two describe the same bytes differently in both directions. The bar for this work is that socket-cli can swap its vendored emitters for this package without its own tests or snapshots moving.
Direction of truth: socket-cli for the shared pipeline, this package for the dotnet emitter,
config-glob.mts, andconfigsByProject.Evidence the swap is a no-op
All four of socket-cli's shared-pipeline suites are ported verbatim under
test/repo/unit/parity/and pass with zero assertion edits — only import paths changed. An assertion that has to be edited to pass is a divergence, not a test fix.sidecar.test.mtsexclude-paths-glob.test.mtsresolution-report-render.test.mts+assemble.test.mts35 test files / 283 tests, zero skips.
preflight --testsclean.check --allreports no failures the default branch does not already report.Two defects found and fixed
The sbt global base was deleted before the caller could use it. sbt provisions the Scala toolchain under
<global base>/boot, andwithFilesartifact paths point into it. The invocation always wrapped in a self-deleting temp dir, so an sbt run withwithFilesreturned paths under a directory it had already removed. The caller can now own that directory.This package passed its own build-tool properties before the caller's options. Every tool resolves a repeated property last-one-wins — measured on Maven
-D, Gradle-Pand the JVM's-D, and read from the dotnet tool's own argument parser. A caller option could therefore unload the emitter and produce an empty SBOM at exit 0. Properties now go last, which also covers alias spellings a collision check cannot enumerate: Maven accepts--defineas a synonym for-D.Sidecar wire format
Now keyed by the absolute
.socket.facts.jsonpath, with entries carried through verbatim from the facts SBOM plus resolved paths. The key is the scope, which is what per-subproject reachability reads, and there is no cross-reactor dedup.groupnamespaceextqualifiers.extclassifierqualifiers.classifierecosystemtype(required)ResolvedComponent[]Exclude paths, and dotnet support for them
One compiler; each emitter only compiles the patterns it is handed. Three per-language implementations are gone — NIO
PathMatcherconstruction,/**variant expansion and azeroDepthVariantsBFS in each of Groovy, Scala and Java — for a net 70 fewer lines.The dotnet tool gains
--exclude-paths, so a wholly excluded project emits no records, matching the JVM emitters. Covered end to end against a real dotnet build, including that a non-matching pattern drops nothing — which is what proves the pattern is doing the work rather than an unrelated load failure.Workspace enumeration
The workspaces emitter family moves in, and both lifecycle participants ship in the one shaded jar. A test asserts that against the packaged bytes and the sisu index, because a class present but unindexed is silently inert — and Maven with no participant emits an empty SBOM, which reads downstream as "no dependencies" rather than as a failure.
Both emitter families now share one parameterized invocation path, so their property sets and argument order cannot drift apart.
Conformance and gate changes
src/andtest/, which the fleet check config covers neither of. It found two real type errors on its first run.Not in this PR
Release preparation.
Consumer-side vetting of
binandoptsstays with the consumer, unchanged by this PR — seedocs/agents.md/repo/trust-boundary.md.Note
High Risk
Breaking sidecar wire format and build-invocation ordering affect scan completeness and reachability handoff; requires coordinated consumer release and careful rollout.
Overview
Brings this package’s facts-generation pipeline in line with the shipping socket-cli emitters so a drop-in swap should not move downstream tests. The largest change is the resolved-paths sidecar: it is no longer a flat
ResolvedComponent[]but a record keyed by absolute.socket.facts.jsonpaths, with SBOM-shapedprojects/componentsentries plus optionaltargets/sources, updated validators, and serialization that scopes reachability per facts file without cross-reactor dedup.Exclude paths are centralized in
exclude-paths-glob.mts(shared with config globs viaglob-syntax.mts); JVM emitters and the dotnet tool now receive pre-compiled regex sources instead of duplicating NIO glob logic. Dotnet gains--exclude-pathsand skips wholly excluded projects like the JVM tools.Adds a workspace enumeration path (Gradle/Maven/sbt init scripts/plugins plus Maven
socket-workspacesparticipant in the same jar) exposed asenumerateWorkspaces, sharinginvoke-build-tool.mtswith full facts runs. Invocation fixes pass caller build-tool options before this package’s properties (so Maven--definecannot unload the extension) and allow a caller-owned sbttmpDirsowithFilespaths underbootsurvive the call. Artifact-path assembly prefers a module’s build output over its published jar when both exist.Conformance and gates expand with socket-cli parity unit tests, dotnet dynamic-version and exclude-paths compat suites, workspace enumeration e2e,
sources-are-type-checkedforsrc//test/, and on-demand emitter builds in compat tooling. Docs andCLAUDE.mddescribe the new contract and consumer trust obligations; fleet/gitignore and permission tweaks are ancillary.Reviewed by Cursor Bugbot for commit 4c77702. Configure here.