first commit
This commit is contained in:
83
docs/security-stack/security/slsa/src/sbom/sbom.md
Normal file
83
docs/security-stack/security/slsa/src/sbom/sbom.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# sbom
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Generates CycloneDX 1.5 compatible Software Bill of Materials documents for
|
||||
packages in Suaveplan. An SBOM lists every component a package
|
||||
depends on, keyed by `purl`, enabling downstream vulnerability scanners,
|
||||
license audits, and provenance correlation. Alongside generation, this
|
||||
module exports canonical serialisation, SHA-256 digesting, and `purl`
|
||||
construction so other packages (notably the publish pipeline) can
|
||||
reproduce the same output bytes.
|
||||
|
||||
## Features
|
||||
|
||||
- CycloneDX 1.5 schema adherence, validated by the sibling Zod schema.
|
||||
- Scoped-package `purl` construction (`pkg:npm/%40scope/name@ver`).
|
||||
- Workspace/catalog placeholder resolution (`workspace:*` → `*`,
|
||||
`catalog:key` → `catalog-key`).
|
||||
- Deterministic sort-key serialisation via `canonicalize`.
|
||||
- Injectable `clock` and `serial` factories for deterministic tests.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { generateSbom } from "@suaveplan/slsa";
|
||||
|
||||
const sbom = generateSbom({
|
||||
packageName: "@suaveplan/utils",
|
||||
packageVersion: "1.2.3",
|
||||
dependencies: { lodash: "4.17.21" },
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { generateSbom, hashSbom, serializeSbom } from "@suaveplan/slsa";
|
||||
|
||||
const sbom = generateSbom(
|
||||
{
|
||||
packageName: "@suaveplan/app",
|
||||
packageVersion: "2.0.0",
|
||||
packageLicense: "MIT",
|
||||
componentType: "application",
|
||||
dependencies: {
|
||||
"@suaveplan/crypto": "workspace:*",
|
||||
vitest: "catalog:testing",
|
||||
},
|
||||
},
|
||||
{
|
||||
clock: () => 0,
|
||||
serial: () => "urn:uuid:deadbeef-dead-beef-dead-beefdeadbeef",
|
||||
}
|
||||
);
|
||||
|
||||
console.log(hashSbom(sbom)); // stable across runs
|
||||
await fs.writeFile("sbom.json", serializeSbom(sbom));
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `generateSbom(input, opts?): Sbom` — constructs the SBOM. Throws
|
||||
`InvalidSbomError` when `packageName`, `packageVersion`, or `dependencies`
|
||||
is missing.
|
||||
- `GenerateSbomOptions { clock?, serial? }` — deterministic seam.
|
||||
- `serializeSbom(sbom): string` — canonical JSON encoding.
|
||||
- `hashSbom(sbom): string` — SHA-256 hex digest of the canonical encoding.
|
||||
- `buildPurl(name, version): string` — constructs a `purl` for either a
|
||||
scoped or unscoped npm package.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`crypto.randomUUID` is the default serial source; the fallback construction
|
||||
using `Math.random` is retained only to keep the module universally
|
||||
importable — runtimes that land in the fallback should be considered a
|
||||
configuration bug and should inject `serial` explicitly. `resolveVersion`
|
||||
maps catalog references to a stable `catalog-<key>` form rather than the
|
||||
resolved pin because catalog resolution happens at publish time, not at
|
||||
SBOM generation time; the downstream publisher can post-process the
|
||||
document if stricter pins are required.
|
||||
Reference in New Issue
Block a user