v1.6.2 — Open-source-readiness: license inventory + policy + GPL-3.0 remediation
SPARC v1.6.2
The open-source-readiness release. Closes out license inventory, policy, dispositions, and the GPL-3.0 runtime concern so SPARC can ship as an Apache-2.0 public repository with a clean compliance story.
This release does not add new application features — it's the infrastructure of supply-chain transparency: SBOM-driven license inventory, machine-readable policy, per-component dispositions, the actual license texts, and the gate that fails CI on un-dispositioned license violations. Plus one CI quality-of-life fix (aggregator hardening) and the removal of the only GPL-3.0 runtime dependency.
Highlights
📋 SBOM License Inventory + Policy (#472 → PR #474)
Consolidates the three CycloneDX SBOMs (Ruby gems via cdxgen, Trivy filesystem, Trivy container) into a single canonical license inventory artifact published on every Security Scanning CI run:
license-inventory.json— machine-readable (operators / sparc-iac / audit pipelines)license-inventory.md— human-readable with grouped action-item tables (warn / unmapped / block) for compliance reviewdocs/compliance/license-policy.yml— declarative allowlist / warn_list / blocklist as policy-as-codedocs/compliance/license-dispositions.yml— per-component disposition tracker following the existingsparc-findings.yml(CVE) pattern. Supportsaccepted/replace/waiver/remediated.- Trivy
--scanners licenseenabled on both fs and container scans (closes a 0% / 21% license coverage gap).
NIST control coverage updated: RA-3(1), CA-2, CM-8, SR-3, SA-15, SA-22.
🛠️ Inventory polish + LICENSES/ population (#475 → PR #477)
Cleaned up the inventory's signal-to-noise ratio and committed canonical SPDX license text:
- License-alias normalization map in
build_license_inventory.rb— canonicalizes upstream variants (Apache 2.0→Apache-2.0,GPL-3.0→GPL-3.0-only,OpenLDAP-2.8→OLDAP-2.8, etc.) before policy lookup. - Cross-SBOM purl-level dedup — when the same gem appears in both
sbom-ruby(with license) andtrivy-container(without), collapse to the row that has the license, preserve provenance via joined source labels. sparc-combined-sbom.cdx.json— single canonical CycloneDX SBOM with purl-deduplicated components (530 unique from 885 raw).LICENSES/populated — 26 license text files: 24 fetched from the SPDXlicense-list-datacorpus + 2 hand-curated for non-SPDX entries (Brakeman, BSD-3-clause-Cambridge expression). Newlib/tasks/licenses.rake(bin/rails licenses:fetch) regeneratesLICENSES/README.mdwith component-count maps.
🧾 Baseline dispositions for the open-source story (#475 → PR #478)
Recorded 65 per-component dispositions covering the GPL family found in the inventory:
- 64
accepted—brakemanandbundler-audit(CI/dev-only Ruby gems) + 62 Debian Bookworm base-image system packages (dynamically-linked OS dependencies, not derivative works of SPARC application code). - 1
replace—spreadsheet 1.3.4flagged as a runtime GPL-3.0-only dependency. Remediated in this release; see below.
Audit result: AGPL: 0, OFL/Artistic/EPL/CDDL: 0 — no licensing surprises hiding in the dependency tree.
🚮 Removed spreadsheet / roo-xls (the GPL-3.0 fix, #479 → PR #480)
spreadsheet 1.3.4 (GPL-3.0-only) was loaded at runtime via SspExcelParserService / SarExcelParserService — strong copyleft incompatible with Apache-2.0 redistribution. Eliminated by dropping roo-xls from the Gemfile, which removes both gems transitively:
Gemfile.lockno longer containsspreadsheet 1.3.4orroo-xls 2.0.0roo(MIT,.xlsx) +caxlsx(MIT, export) retained — capability preserved for API consumers- Legacy
.xls(Excel 97-2003 binary) support dropped as the trade-off
🧹 Excel UI scrub (#479)
Removed every user-facing reference to Excel ingest or export across views, about pages, and docs. Underlying services / routes / controllers / API stay live — the capability lives in the codebase and API; the UI just stops advertising it. Files affected:
app/views/sar_documents/{index,show,new,select_ssp,enrich}.html.erb
app/views/ssp_documents/{index,show,new,editor}.html.erb
app/views/about/{index,quickstart,api_docs}.html.erb
app/views/shared/_oscal_export_dropdown.html.erb
CLAUDE.md
docs/{API.md,SPARC_Video_Script.md,puma-dev.md}
Notable removal: the "Convert Excel to JSON" upload card + handleExcelUpload() / convertExcelToJSON() / showConversionStatus() JS in ssp_documents/editor.html.erb.
Historical creation_method == "excel" rows now display as "Import" in the UI (data preserved, label scrubbed).
🚦 License enforce gate flipped on (#479)
docs/compliance/license-policy.yml::enforce is now true. CI fails on:
- Any component matching
blocklist(BUSL / SSPL / Elastic / Commons Clause / etc.) - Any component matching
warn_listwithout a recorded disposition inlicense-dispositions.yml
Operators resolve new findings by adding dispositions, not by weakening policy.
🔧 Aggregator hardening (#473 → PR #476)
Required Checks Passed (the branch-protection aggregator) now:
- Fires on
editedpull_requestevents (so body edits re-triggeringTest plan checklistalso re-run the aggregator — closes the gap that required manualgh run rerunon PRs #462, #467, #469, #471). - Skips short-circuiting on a stale failure when an in-flight rerun for the same check name exists. Logs
"ignoring stale failures (in-flight rerun pending) for: …"and keeps polling.
Validated end-to-end on this release: every PR in #1.6.2 passed the aggregator on first run without manual intervention.
Upgrade Notes
- No env-var changes required. Existing deployments continue to work.
- No database migrations.
bin/rails db:prepareis a no-op. .xls(Excel 97-2003 binary) uploads will now fail. Use.xlsx, or — preferably — OSCAL JSON/YAML/XML.- License compliance documentation expanded.
NOTICE,LICENSES/,docs/compliance/THIRD_PARTY_NOTICES.md,docs/compliance/license-policy.yml,docs/compliance/license-dispositions.ymlare now part of the audit-package surface. license_inventoryis now a required CI artifact alongside the existing SBOM + HDF outputs insparc-compliance-latest.
Backlog Carried Forward
- 120 unmapped components in the inventory (5 Ruby gems where cdxgen missed the license, 4 Debian system libs Trivy didn't enrich, 26 Python deps in
tests/api/uv.lock, 80 Go modules from the vendoredhdfbinary, 5 meta entries) — to be triaged in a separate follow-up issue with a 5-category disposition plan.
Verification
- Full test suite: 2202 examples, 0 failures, 2 pending (HdfRunner real-binary; environmental).
license_inventoryCI artifact: 0 block-severity items, 0 un-dispositioned warns.Required Checks Passedpassed on first run for every PR in this release (#476, #477, #478, #480) — validates the aggregator fix.- AGPL components in the inventory: 0.
Release Contents
| Issue | PR | Description |
|---|---|---|
| #472 | #474 | SBOM license inventory + policy + dispositions schema |
| #473 | #476 | Aggregator hardening (in-flight reruns, edited trigger) |
| #475 | #477 | Inventory polish + alias map + dedup + LICENSES/ population |
| #475 | #478 | Baseline GPL dispositions (65 entries) |
| #479 | #480 | Drop roo-xls; Excel UI scrub; enforce flip; v1.6.2 bump |