Skip to content

Commit 63b41e7

Browse files
tcconnallytcconnallyclaude
authored
docs(sbom): separate distributed runtime from build-time toolchain (#688)
SBOM.md previously published the full `pip freeze` of the dev virtualenv (~140 packages incl. anthropic, openai, langchain, grpcio, poetry, twine, mypy) as if it were the product's SBOM. None of those ship: the distributed package declares `dependencies = ["pyyaml>=6.0.1"]`, and the container image installs only PyYAML. Presenting the dev freeze as the SBOM overstates the attack surface and misrepresents the software to anyone reading it as a compliance artifact. - Lead with the RUNTIME (distributed) set: CPython + PyYAML, plus optional extras. - Add machine-readable CycloneDX 1.5 `sbom.cdx.json` (purls, SHA-256, dependency graph) — closes the NTIA gaps the old file marked "Not Provided". - Retain the dev/CI freeze, clearly labeled as NOT distributed, for transparency. Co-authored-by: tcconnally <hermes@perseus.observer> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 42fbfc1 commit 63b41e7

2 files changed

Lines changed: 144 additions & 27 deletions

File tree

SBOM.md

Lines changed: 79 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,84 @@
11
# Software Bill of Materials (SBOM) for Perseus
22

3-
This SBOM document lists all direct and transitive dependencies of the Perseus project, as required for federal procurement compliance.
4-
5-
## NTIA Minimum Elements Checklist
6-
7-
| Element | Status | Notes |
8-
| :----------------------- | :---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
9-
| **Data Fields** | | |
10-
| - Supplier Name | Provided | Perseus-Computing-LLC |
11-
| - Component Name | Provided | Each Python package listed below. |
12-
| - Component Version | Provided | Version numbers are specified for each package. |
13-
| - SPDX ID (or equivalent)| Not Provided| Not directly applicable for Python packages in requirements.txt. Package names serve as identifiers. |
14-
| - Hash of Component | Not Provided| While `pip` can generate hashes, they are not included in this SBOM by default. Can be generated on request. |
15-
| - Relationship | Provided | All listed components are direct dependencies of Perseus. |
16-
| - Author Timestamp | Provided | This document's creation date. |
17-
| **Automation Support** | | |
18-
| - Format | Human-readable| Markdown format. Can be converted to machine-readable formats (e.g., SPDX, CycloneDX) if needed. |
19-
| **Practices and Processes** | | |
20-
| - Frequency | On Request | Generated as part of the compliance process. Updated as dependencies change. |
21-
| - Depth | Transitive | `pip freeze` captures all installed packages, which includes transitive dependencies. |
22-
| - Distribution | Included | This document is included in the repository. |
23-
| - Access | Public | This document is publicly available in the Perseus repository. |
24-
25-
## Python Dependencies
26-
27-
The following Python packages are used in the Perseus project. This list is generated using `pip freeze` from the project's virtual environment, capturing both direct and transitive dependencies.
28-
29-
**Note:** License information for each package is not automatically extracted by `pip freeze`. This would require additional tools (e.g., `pip-licenses` or `license-scanner`). For compliance, refer to the individual package repositories or distribution metadata for exact license terms.
3+
Perseus is distributed as a **single self-contained Python file** (`perseus.py`).
4+
This document describes its dependencies for federal procurement compliance.
5+
6+
> **Read this first — scope.** Two very different dependency sets exist and were
7+
> previously conflated in this file:
8+
>
9+
> 1. **Runtime (distributed)** — what actually ships and executes on a user's
10+
> machine or in the container image. This is a *tiny* set.
11+
> 2. **Build / development (NOT distributed)** — the toolchain used to test,
12+
> lint, type-check, and package Perseus (pytest, mypy, poetry, twine, …).
13+
> None of these are present in the shipped artifact.
14+
>
15+
> Attack-surface and vulnerability analysis should be scoped to the **runtime**
16+
> set. The build/dev freeze is retained at the end of this document for
17+
> transparency, clearly labeled.
18+
19+
A machine-readable CycloneDX 1.5 SBOM of the runtime set is provided alongside
20+
this document: [`sbom.cdx.json`](sbom.cdx.json).
21+
22+
---
23+
24+
## 1. Runtime dependencies (distributed)
25+
26+
The distributed package `perseus-ctx` declares exactly one third-party runtime
27+
dependency. `perseus.py` is otherwise built entirely on the Python standard
28+
library (its single hard third-party import is `yaml`).
29+
30+
| Component | Version | License | Role |
31+
| :-------- | :------ | :------ | :--- |
32+
| CPython | >= 3.10 (image ships 3.12) | Python-2.0 (PSF) | Interpreter |
33+
| PyYAML | >= 6.0.1 (tested 6.0.3) | MIT | YAML parsing/emitting — the only hard third-party runtime dependency |
34+
35+
Source of truth: `pyproject.toml``dependencies = ["pyyaml>=6.0.1"]`.
36+
37+
### Optional extras (installed only on explicit opt-in)
38+
39+
| Extra | Adds | When needed |
40+
| :------- | :---------- | :---------- |
41+
| `[mcp]` | `mcp` | Only if using the external `mcp` package integration path. |
42+
| `[dev]` | `pytest`, `coverage`, `hypothesis` | Development/testing only — never distributed. |
43+
44+
### Container / Iron Bank image
45+
46+
The hardened container image ships **only** CPython 3.12 + PyYAML on an approved
47+
minimal base — it does **not** install the build/dev freeze below (it installs
48+
`requirements-runtime.txt`, which pins PyYAML alone). See `ironbank/` for the
49+
hardened Dockerfile, hardening manifest, and a pinned, hash-validated
50+
image-specific SBOM.
51+
52+
---
53+
54+
## 2. NTIA Minimum Elements Checklist
55+
56+
| Element | Status | Notes |
57+
| :------ | :----- | :---- |
58+
| Supplier Name | Provided | Perseus Computing LLC |
59+
| Component Name | Provided | See runtime table above; machine-readable in `sbom.cdx.json`. |
60+
| Component Version | Provided | Pinned in `sbom.cdx.json`. |
61+
| Unique Identifier | Provided | Package URLs (purl) in `sbom.cdx.json`. |
62+
| Hash of Component | Provided | SHA-256 of the pinned PyYAML wheel in `sbom.cdx.json` and in `ironbank/hardening_manifest.yaml`. |
63+
| Relationship | Provided | Dependency graph in `sbom.cdx.json` (`dependencies`). |
64+
| Author / Timestamp | Provided | In `sbom.cdx.json` metadata. |
65+
| Format | Machine-readable | CycloneDX 1.5 JSON (`sbom.cdx.json`) + this human-readable summary. |
66+
| Depth | Complete for runtime | Runtime set is flat (PyYAML has no further hard runtime deps). |
67+
| Distribution | Included | Committed in the repository. |
68+
| Access | Public | Publicly available in the Perseus repository. |
69+
| Frequency | On dependency change | Regenerated when `pyproject.toml` runtime deps change. |
70+
71+
---
72+
73+
## 3. Build / development environment (NOT distributed)
74+
75+
> ⚠️ **The packages below are the development, testing, and packaging toolchain.
76+
> They are NOT part of any shipped Perseus artifact** (not in `perseus.py`, not
77+
> in the pip package's runtime deps, not in the container image). They are listed
78+
> only for transparency into the build environment. Do **not** treat this list as
79+
> the product's attack surface — use §1 for that.
80+
81+
This is a `pip freeze` of the full development virtual environment:
3082

3183
```
3284
annotated-doc==0.0.4

sbom.cdx.json

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"bomFormat": "CycloneDX",
3+
"specVersion": "1.5",
4+
"version": 1,
5+
"metadata": {
6+
"timestamp": "2026-07-06T00:00:00Z",
7+
"authors": [{ "name": "Perseus Computing LLC", "email": "perseus@perseus.observer" }],
8+
"component": {
9+
"type": "application",
10+
"bom-ref": "perseus-ctx@1.0.17",
11+
"name": "perseus-ctx",
12+
"version": "1.0.17",
13+
"description": "Perseus — single-file, on-prem live context engine for AI agents.",
14+
"licenses": [{ "license": { "id": "MIT" } }],
15+
"purl": "pkg:pypi/perseus-ctx@1.0.17",
16+
"externalReferences": [
17+
{ "type": "website", "url": "https://perseus.observer" },
18+
{ "type": "vcs", "url": "https://github.com/Perseus-Computing-LLC/perseus" }
19+
]
20+
},
21+
"properties": [
22+
{
23+
"name": "perseus:sbom:scope",
24+
"value": "RUNTIME (distributed) dependencies only. The development/CI/packaging toolchain (pytest, mypy, poetry, twine, etc.) is documented separately in SBOM.md and is NOT part of any shipped artifact."
25+
}
26+
]
27+
},
28+
"components": [
29+
{
30+
"type": "application",
31+
"bom-ref": "python",
32+
"name": "python",
33+
"version": ">=3.10",
34+
"description": "CPython interpreter. The distributed container image ships 3.12.",
35+
"licenses": [{ "license": { "id": "Python-2.0" } }],
36+
"purl": "pkg:generic/python@3.12"
37+
},
38+
{
39+
"type": "library",
40+
"bom-ref": "pyyaml",
41+
"name": "PyYAML",
42+
"version": ">=6.0.1",
43+
"description": "YAML parser/emitter. The single hard third-party runtime dependency (pyproject.toml: pyyaml>=6.0.1). Reference/tested pin: 6.0.3.",
44+
"licenses": [{ "license": { "id": "MIT" } }],
45+
"purl": "pkg:pypi/pyyaml@6.0.3",
46+
"hashes": [
47+
{
48+
"alg": "SHA-256",
49+
"content": "ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"
50+
}
51+
],
52+
"properties": [
53+
{
54+
"name": "perseus:sbom:hash-note",
55+
"value": "SHA-256 is for the reference pin pyyaml 6.0.3 cp312 manylinux x86_64 wheel; the aarch64 wheel is 9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28."
56+
}
57+
]
58+
}
59+
],
60+
"dependencies": [
61+
{ "ref": "perseus-ctx@1.0.17", "dependsOn": ["python", "pyyaml"] },
62+
{ "ref": "pyyaml", "dependsOn": [] },
63+
{ "ref": "python", "dependsOn": [] }
64+
]
65+
}

0 commit comments

Comments
 (0)