From 4a7d9d967ab238214d3ceddff151d300a315bbd0 Mon Sep 17 00:00:00 2001 From: Content Agent Date: Tue, 28 Apr 2026 16:51:24 -0700 Subject: [PATCH] feat: adopt CycloneDX v1.6 as SpeckBOM output format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom JSON-LD compilation manifest with valid CycloneDX v1.6 documents using bomType: specBOM and speckl: property namespace. Key changes: - §4.5: Compilation manifest now outputs CycloneDX v1.6 JSON - Added 'Why CycloneDX' section comparing CycloneDX vs SPDX for this use case - Full CycloneDX JSON example for DrugDosageCalculator - Added CycloneDX field mapping table (SpeckDL primitive → CycloneDX location) - Added path to standardization (community proposal → OWASP recognition) - Appendix B restructured into three sections: B.1 Provenance Graph (JSON-LD / PROV-O) — intent layer B.2 SpeckBOM (CycloneDX v1.6) — composition layer B.3 Two-Layer Architecture — how they complement each other This extends an existing OWASP/ECMA-424 standard rather than defining a bespoke format, ensuring compatibility with Dependency-Track and the full CycloneDX tooling ecosystem. --- speckdl/SPEC.v2-dp-primitives.md | 216 ++++++++++++++++++++++++------- 1 file changed, 170 insertions(+), 46 deletions(-) diff --git a/speckdl/SPEC.v2-dp-primitives.md b/speckdl/SPEC.v2-dp-primitives.md index 12db788..8f417b1 100644 --- a/speckdl/SPEC.v2-dp-primitives.md +++ b/speckdl/SPEC.v2-dp-primitives.md @@ -1,7 +1,7 @@ # SpeckDL Language Specification v0.2-DP > The specification-first language for auditable software. -> **This version adds Dark Provenance primitives (`provenance`, `review`, `derives`, `satisfies`, `author`, `source`) and SpeckBOM (`bom` + import pinning).** +> **This version adds Dark Provenance primitives (`provenance`, `review`, `derives`, `satisfies`, `author`, `source`), SpeckBOM (`bom` + import pinning), and CycloneDX v1.6 as the SpeckBOM output format.** > Part of the [Speckl](https://os.scoble.me/forgejo/sscoble/speckl) project. MIT License. --- @@ -431,55 +431,115 @@ The provenance graph is serialized as JSON-LD and stored alongside the compiled } ``` -### 4.5 Compilation Manifest (SpeckBOM Output) +### 4.5 Compilation Manifest (SpeckBOM Output — CycloneDX) -At compile time, the compiler produces a **compilation manifest** — the SpeckBOM's runtime component. This complements the declarative `bom` block in the source with verified, observed data: +At compile time, the compiler produces a **SpeckBOM** — a valid [CycloneDX](https://cyclonedx.org/) v1.6 document with `bomType: specBOM` and `speckl:` property extensions. This extends an existing OWASP/ECMA-424 standard rather than defining a bespoke format, ensuring compatibility with the full CycloneDX tooling ecosystem (Dependency-Track, OWASP integration, etc.). + +#### Why CycloneDX + +CycloneDX is the natural base for SpeckBOM because: + +| Concern | CycloneDX Feature | SpeckBOM Mapping | +|---|---|---| +| Component inventory | `components[]` | Imported Specks as components | +| Dependency graph | `dependencies[]` | Import/derives/satisfies edges | +| Toolchain provenance | `metadata.tools[]` | Compiler, solver, runtime | +| Content integrity | `hashes[]` on components | Source and artifact hashes | +| Attestations | CycloneDX Attestations (CDXA) | Review status (`manual`/`auto`/`hybrid`) | +| Citations | `annotations[]` | Author, source, provenance metadata | +| Cross-BOM linking | BOM-Link | Chaining SpeckBOMs across spec imports | +| Extensibility | `properties[]` with namespace | `speckl:` properties for domain-specific fields | + +Neither CycloneDX nor SPDX currently defines a **specification-level BOM type**. SpeckBOM (`specBOM`) fills this gap: it captures *what specification a system satisfies*, *what verification evidence exists*, and *what intent drove each decision* — concerns that software-level BOMs don't address. + +#### Output Format + +The compiler emits a single CycloneDX JSON document per Speck: ```json { - "@context": { - "prov": "http://www.w3.org/ns/prov#", - "speckl": "https://os.scoble.me/speckl/ns#", - "spdx": "https://spdx.org/rdf/terms" + "$schema": "https://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6", + "bomType": "specBOM", + "serialNumber": "urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6", + + "metadata": { + "timestamp": "2026-04-28T16:00:00Z", + "component": { + "type": "application", + "name": "DrugDosageCalculator", + "version": "1.0.0", + "purl": "pkg:speckl/DrugDosageCalculator@1.0.0", + "hashes": [ + { "alg": "SHA-256", "content": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" } + ], + "licenses": [{ "expression": "MIT" }], + "properties": [ + { "name": "speckl:reproducible", "value": "true" }, + { "name": "speckl:verificationResult", "value": "SAT" } + ] + }, + "tools": [ + { "name": "speckl-compile", "version": "0.2.0" }, + { "name": "z3", "version": "4.12.5" }, + { "name": "wasm-runtime", "version": "1.0.0" } + ] }, - "@id": "speck:DrugDosageCalculator/bom", - "@type": "speckl:SpeckBOM", - "speckl:spec": { - "@id": "speck:DrugDosageCalculator", - "speckl:hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "speckl:license": "MIT" - }, - "speckl:dependencies": [ + + "components": [ { - "@id": "speck:RetryHandler", - "speckl:alias": "retry", - "speckl:version": "1.2.0", - "speckl:hash": "sha256:a1b2c3...", - "speckl:integrity": "verified" + "type": "library", + "name": "RetryHandler", + "version": "1.2.0", + "purl": "pkg:speckl/RetryHandler@1.2.0", + "hashes": [ + { "alg": "SHA-256", "content": "a1b2c3..." } + ], + "properties": [ + { "name": "speckl:importAlias", "value": "retry" }, + { "name": "speckl:integrity", "value": "verified" }, + { "name": "speckl:derivesFrom", "value": "pkg:speckl/FaultHandler@2.0.0" }, + { "name": "speckl:satisfies", "value": "REQ-ASYNC-001" } + ] } ], - "speckl:toolchain": { - "speckl:compiler": { "speckl:name": "speckl-compile", "speckl:version": "0.2.0" }, - "speckl:solver": { "speckl:name": "z3", "speckl:version": "4.12.5" }, - "speckl:runtime": { "speckl:name": "wasm-runtime", "speckl:version": "1.0.0" } - }, - "speckl:artifacts": [ + + "dependencies": [ { - "@type": "speckl:Z3AssertionSet", - "speckl:hash": "sha256:abc...", - "speckl:verificationResult": "SAT" - }, - { - "@type": "speckl:DST", - "speckl:hash": "sha256:def..." - }, - { - "@type": "speckl:WASMModule", - "speckl:hash": "sha256:789..." + "ref": "pkg:speckl/DrugDosageCalculator@1.0.0", + "dependsOn": ["pkg:speckl/RetryHandler@1.2.0"] } ], - "speckl:compilationTimestamp": "2026-04-28T16:00:00Z", - "speckl:reproducible": true + + "annotations": [ + { + "bomRef": "provenance-regulation", + "subjects": ["pkg:speckl/DrugDosageCalculator@1.0.0"], + "text": "FDA 21 CFR 820.30", + "properties": [ + { "name": "speckl:provenanceType", "value": "regulation" } + ] + }, + { + "bomRef": "provenance-author", + "subjects": ["pkg:speckl/DrugDosageCalculator@1.0.0"], + "text": "Dr. Sarah Chen", + "properties": [ + { "name": "speckl:provenanceType", "value": "author" }, + { "name": "speckl:authorEmail", "value": "s.chen@meddevice.example" } + ] + }, + { + "bomRef": "review-requirement", + "subjects": ["pkg:speckl/DrugDosageCalculator@1.0.0"], + "text": "Manual review required before deployment", + "properties": [ + { "name": "speckl:reviewType", "value": "manual" }, + { "name": "speckl:reviewStatus", "value": "pending" } + ] + } + ] } ``` @@ -496,6 +556,35 @@ This manifest is the **audit-ready output**. An auditor can: 2. Verify all dependency hashes match their imports 3. Verify toolchain versions match the declared ones 4. Re-run compilation and verify artifact hashes match +5. Load the SpeckBOM into any CycloneDX-compatible tool (Dependency-Track, OWASP ecosystem) for dependency analysis, vulnerability tracking, and compliance reporting + +#### CycloneDX Field Mapping + +| SpeckDL Primitive | CycloneDX Location | Field | +|---|---|---| +| `bom { compiler }`, `bom { solver }`, `bom { runtime }` | `metadata.tools[]` | Standard tool entries | +| `bom { license }` | `metadata.component.licenses[]` | SPDX expression | +| `bom { hash }` | `metadata.component.hashes[]` | SHA-256 | +| `import "X" as Y hash H version V` | `components[]` | Component entry with purl, hashes, properties | +| `derives from X` | `component.properties[]` | `speckl:derivesFrom` | +| `satisfies X clause Y` | `component.properties[]` | `speckl:satisfies` | +| `author: Name ` | `annotations[]` | `speckl:provenanceType: author` | +| `source: kind ref X` | `annotations[]` | `speckl:provenanceType: source` | +| `provenance { regulation: X }` | `annotations[]` | `speckl:provenanceType: regulation` | +| `review: manual` | `annotations[]` | `speckl:reviewType: manual` | +| Compilation artifacts (Z3, DST, WASM) | `components[]` (nested) | Type + hash | +| Verification results (SAT/UNSAT) | `metadata.component.properties[]` | `speckl:verificationResult` | +| Reproducibility status | `metadata.component.properties[]` | `speckl:reproducible` | + +#### Path to Standardization + +SpeckBOM currently extends CycloneDX with a `specBOM` bomType and `speckl:` property namespace. The path to formal adoption: + +1. **Now**: Speckl emits valid CycloneDX v1.6 with `speckl:` extensions — works with all existing tooling +2. **Near-term**: Submit a community proposal to CycloneDX for `specBOM` as a recognized BOM type (alongside SBOM, HBOM, MBOM, OBOM, AI-BOM, CBOM) +3. **Long-term**: If adopted, Speckl becomes the reference implementation for specification-level BOMs in an OWASP standard + +This is the same path SPDX used for AI-BOM — extend the standard rather than fork it. --- @@ -824,6 +913,10 @@ The reference compiler (`speckl-compile`) is a Node.js/TypeScript application th ## Appendix B: Dark Provenance JSON-LD Reference (NEW) +### B.1 Provenance Graph — JSON-LD / PROV-O + +The provenance graph (§4.4) is serialized as JSON-LD using PROV-O vocabulary. This is the **intent provenance** layer — who, why, and what drove a specification. + | SpeckDL Primitive | JSON-LD Output | PROV-O Mapping | |---|---|---| | `provenance { regulation: X }` | Node with `prov:wasInformedBy` → Regulation | `prov:Entity` → `prov:Activity` | @@ -837,13 +930,44 @@ The reference compiler (`speckl-compile`) is a Node.js/TypeScript application th | `review: manual` | `speckl:ManualReview` requirement node | Extension | | `review: auto` | No additional nodes (default path) | N/A | | `review: hybrid` | `speckl:HybridReview` with sampling params | Extension | -| `bom { compiler: X version Y }` | `speckl:SpeckBOM` with toolchain entries | SPDX-compatible | -| `bom { solver: X version Y }` | Toolchain entry in SpeckBOM | SPDX-compatible | -| `bom { runtime: X version Y }` | Toolchain entry in SpeckBOM | SPDX-compatible | -| `bom { license: X }` | `spdx:licenseDeclared` | SPDX | -| `bom { hash: X }` | `speckl:contentHash` (verified at compile time) | Extension | -| `import ... hash: X version: Y` | Dependency entry in SpeckBOM | SPDX-compatible | + +### B.2 SpeckBOM — CycloneDX v1.6 + +The compilation manifest (§4.5) is serialized as CycloneDX v1.6 JSON with `bomType: specBOM` and `speckl:` property extensions. This is the **composition BOM** layer — what a spec depends on, what tools built it, and what it produced. + +| SpeckDL Primitive | CycloneDX Location | Field | +|---|---|---| +| `bom { compiler }`, `bom { solver }`, `bom { runtime }` | `metadata.tools[]` | Standard tool entries | +| `bom { license }` | `metadata.component.licenses[]` | SPDX expression | +| `bom { hash }` | `metadata.component.hashes[]` | SHA-256 | +| `import "X" as Y hash H version V` | `components[]` | Component entry with purl, hashes, properties | +| `derives from X` | `component.properties[]` | `speckl:derivesFrom` | +| `satisfies X clause Y` | `component.properties[]` | `speckl:satisfies` | +| `author: Name ` | `annotations[]` | `speckl:provenanceType: author` | +| `source: kind ref X` | `annotations[]` | `speckl:provenanceType: source` | +| `provenance { regulation: X }` | `annotations[]` | `speckl:provenanceType: regulation` | +| `review: manual` | `annotations[]` | `speckl:reviewType: manual` | +| `review: auto` | No additional annotation | N/A | +| `review: hybrid` | `annotations[]` | `speckl:reviewType: hybrid` | +| Compilation artifacts (Z3, DST, WASM) | `components[]` (nested) | Type + hash | +| Verification results (SAT/UNSAT) | `metadata.component.properties[]` | `speckl:verificationResult` | +| Reproducibility status | `metadata.component.properties[]` | `speckl:reproducible` | + +### B.3 Two-Layer Architecture + +Speckl produces **two complementary outputs**: + +| Layer | Format | Concern | Standard | +|---|---|---|---| +| **Intent provenance** | JSON-LD / PROV-O | Who, why, what drove this specification | W3C PROV-O | +| **Composition BOM** | CycloneDX v1.6 JSON | What this spec depends on, builds with, produces | OWASP CycloneDX (ECMA-424) | + +These layers are orthogonal: +- The provenance graph answers *"Why does this constraint exist?"* (regulatory, design decision, conversation) +- The SpeckBOM answers *"What is this spec made of, and can I reproduce it?"* (dependencies, toolchain, artifacts) + +Together they form the complete audit trail: **intent** (PROV-O) + **composition** (CycloneDX) = **full accountability**. --- -*This is a v0.2-DP specification. Dark Provenance and SpeckBOM primitives are optional but recommended for safety-critical and regulated systems. Feedback welcome via the [Speckl repository](https://os.scoble.me/forgejo/sscoble/speckl).* \ No newline at end of file +*This is a v0.2-DP specification. Dark Provenance and SpeckBOM primitives are optional but recommended for safety-critical and regulated systems. The SpeckBOM compilation output extends CycloneDX v1.6 (OWASP/ECMA-424). Feedback welcome via the [Speckl repository](https://os.scoble.me/forgejo/sscoble/speckl).* \ No newline at end of file