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:
parent
bba505a7a3
commit
4a7d9d967a
1 changed files with 170 additions and 46 deletions
|
|
@ -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).*
|
||||
Loading…
Add table
Add a link
Reference in a new issue