|
| 1 | +License Policy Gate |
| 2 | +=================== |
| 3 | + |
| 4 | +``build_sbom`` records each component's license *name*, but nothing ever judged |
| 5 | +it — a copyleft or otherwise-disallowed license could ship unnoticed. This adds |
| 6 | +the policy gate: normalize the SBOM's license strings to SPDX ids, evaluate them |
| 7 | +against an allowlist / denylist (with a built-in strong-copyleft set), and emit |
| 8 | +violations that bridge into the existing SARIF exporter — the license-compliance |
| 9 | +lane beside the OSV vulnerability lane. |
| 10 | + |
| 11 | +Pure standard library (``re``); fully offline; imports no ``PySide6``. |
| 12 | + |
| 13 | +Headless API |
| 14 | +------------ |
| 15 | + |
| 16 | +.. code-block:: python |
| 17 | +
|
| 18 | + from je_auto_control import ( |
| 19 | + build_sbom, evaluate_sbom, evaluate_license, |
| 20 | + license_findings_to_sarif, write_sarif, DEFAULT_COPYLEFT) |
| 21 | +
|
| 22 | + sbom = build_sbom("je_auto_control") |
| 23 | +
|
| 24 | + # Allowlist mode: anything outside the list is a violation. |
| 25 | + violations = evaluate_sbom(sbom["components"], |
| 26 | + allow=["MIT", "Apache-2.0", "BSD-3-Clause"]) |
| 27 | +
|
| 28 | + # Or denylist mode using the built-in strong-copyleft set. |
| 29 | + violations = evaluate_sbom(sbom["components"], deny=DEFAULT_COPYLEFT) |
| 30 | +
|
| 31 | + write_sarif(license_findings_to_sarif(violations), "licenses.sarif", |
| 32 | + tool_name="AutoControl-License") |
| 33 | +
|
| 34 | +``normalize_spdx`` maps loose names (``"MIT License"`` → ``MIT``, ``"Apache |
| 35 | +2.0"`` → ``Apache-2.0``) to SPDX ids. ``evaluate_license`` returns ``allowed`` / |
| 36 | +``denied`` / ``unknown``: ``deny`` takes precedence; an empty ``allow`` means |
| 37 | +"not constrained"; a missing license is ``unknown``. SPDX **expressions** are |
| 38 | +understood — ``"MIT OR GPL-3.0-only"`` is a *choice* (allowed if any operand is |
| 39 | +allowed), while ``"MIT AND GPL-3.0-only"`` requires every operand. Each |
| 40 | +violation is ``{name, version, license, status}``; ``denied`` maps to a SARIF |
| 41 | +``error`` and ``unknown`` to a ``warning``. |
| 42 | + |
| 43 | +Executor command |
| 44 | +---------------- |
| 45 | + |
| 46 | +``AC_check_licenses`` takes ``components`` (a component list, a full SBOM dict, |
| 47 | +or a JSON string) and optional ``allow`` / ``deny`` lists; it returns |
| 48 | +``{violations, count}``. The same operation is exposed as the MCP tool |
| 49 | +``ac_check_licenses`` and as a Script Builder command under **Security**. |
0 commit comments