# Supply chain (lockfile, SBOM, light SLSA)

Operators and reviewers use this page for dependency hygiene and release evidence. It implements light SBOM/SLSA practices for `CMP-08` in `SAAS-PRD.md`. It does **not** claim SLSA Level 3, a paid SOC 2 report, or an audited ISO certification.

## Lockfile discipline

- Package manager is **Bun only**. The committed lockfile is `bun.lock`.
- `package.json` pins `packageManager` / `engines.bun`. CI and deploy workflows install with `bun install --frozen-lockfile`.
- `.npmrc` sets `package-lock=false` so accidental `npm install` does not create a second lockfile.
- Foreign lockfiles (`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `npm-shrinkwrap.json`) are gitignored and rejected by `bun run check:lockfile`.

```bash
bun run check:lockfile
```

## Dependency update bots

Two configs ship so either bot can run:

| Config | Role |
| --- | --- |
| `renovate.json` | Preferred: Bun-aware grouping, OSV alerts, Monday lockfile maintenance (Asia/Kuala_Lumpur). Requires the Renovate GitHub App. |
| `.github/dependabot.yml` | Native fallback for `bun` and `github-actions` weekly PRs. |

Enable Renovate on the org when ready; leave Dependabot on as a safety net or turn it off for the ecosystems Renovate already covers to avoid duplicate PRs.

## SBOM (CycloneDX)

Workflow `.github/workflows/sbom.yml` runs on `main` push, published releases, and `workflow_dispatch` — **not** on every PR (keeps PR CI lean). It generates a CycloneDX 1.5 JSON SBOM via `@cyclonedx/cdxgen` (`-t js`, which reads `package.json` workspaces and `bun.lock`; cdxgen's `bun` type still emits an empty component list for Bun text lockfiles). The workflow uploads `edgecms-sbom-cdx` as an Actions artifact and, on published GitHub Releases, attaches `artifacts/sbom.cdx.json` to the release. Generation fails if the BOM has zero components.

Locally (needs network for `bunx`):

```bash
bun run sbom:generate
```

Fixture-only stub (no network; empty component list — tests and dry docs only):

```bash
bun run sbom:generate:stub
```

Generated files under `artifacts/sbom*` stay untracked.

## Light SLSA provenance

On `push` to `main`, `workflow_dispatch`, and `release`, the same workflow runs `actions/attest-build-provenance` against the SBOM file. That records GitHub Artifact Attestations (Sigstore) for the subject digest — a **light** provenance signal (builder identity + source ref), not a full SLSA Level 3 hardener set (no hermetic build, no verified two-party review gate in this workflow).

Verify an attestation after a main/release run with the GitHub CLI against the artifact digest, or from the Actions run's Attestations UI. Do not market this as “SLSA 3 certified.”

## Related checks

- Secret and dependency scanning remain part of the broader `CMP-08` vulnerability-management track (GitHub secret scanning / Dependabot alerts / Renovate OSV). Critical fixes target 7 days; high within 30 — process, not automated enforcement in this workflow.
- PR CI (`ci.yml`, single job) runs lockfile discipline with lint/typecheck/unit tests/build.
