// SBOM (Software Bill of Materials) export. // // Generates CycloneDX or SPDX reports from the Coven's Tomb. Used by the // legal department to audit the fleet and by Portable Tool Bin consumers // who need to redistribute static binaries with proper attribution. package legal import ( "encoding/json" "encoding/xml" "fmt" ) // Component is one entry in the SBOM. type Component struct { Name string `json:"name" xml:"name"` Version string `json:"version" xml:"version"` License string `json:"license" xml:"license"` Hash string `json:"hash" xml:"hash"` Purl string `json:"purl" xml:"purl"` } // Sbom is the report itself. type Sbom struct { Components []Component `json:"components" xml:"component"` } // ExportCycloneDX produces a CycloneDX v1.4 JSON document for a set of // Essences. `tree` is the dependency tree returned by the Tomb. func ExportCycloneDX(tree []Component) ([]byte, error) { s := Sbom{Components: tree} return json.MarshalIndent(s, "", " ") } // ExportSPDX produces an SPDX 2.3 XML document for the same data. func ExportSPDX(tree []Component) ([]byte, error) { type spdxDoc struct { XMLName struct{} `xml:"SpdxDocument"` License string `xml:"License,attr"` Comp []Component `xml:"component"` } return xml.MarshalIndent(spdxDoc{Comp: tree}, "", " ") } // AttributionBundle collects every LICENSE / COPYING file referenced by // the given components. The Portable Tool Bin attaches this as // CREDITS.md / LICENSE_BUNDLE.txt to every downloaded static ELF so the // legal "notice" requirement of MIT/BSD/GPL is satisfied out-of-the-box. func AttributionBundle(tree []Component) string { var out string out = "# Attribution Bundle\n\nGenerated by the Sorcery-Go Legal Sentinel.\n\n" for _, c := range tree { out += fmt.Sprintf("## %s %s\n", c.Name, c.Version) out += fmt.Sprintf("- License: %s\n", c.License) out += fmt.Sprintf("- Hash: %s\n\n", c.Hash) } return out }