feat: adopt CycloneDX v1.6 as SpeckBOM output format

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.
This commit is contained in:
Content Agent 2026-04-28 16:51:24 -07:00
parent bba505a7a3
commit 4a7d9d967a

View file

@ -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 <email>` | `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 <email>` | `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).*
*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).*