Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ jobs:
REDIS_URL: redis://localhost:6379/0
steps:
- uses: actions/checkout@v4
with:
# Full history: `showLastUpdateTime` reads each page's git log —
# a shallow clone would stamp every page with the deploy date.
fetch-depth: 0

# --- Regenerate the OpenAPI spec from the live backend BEFORE the docs
# build, so the published Redoc reference always reflects the current
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,29 @@ jobs:
gh release create "$TAG" --draft --title "$TAG" --generate-notes
fi

# An SCA product ships its own SBOM (Dependency-Track convention):
# generate a CycloneDX document over the release's checked-out source
# tree and attach it to the (draft) Release. Runs on re-runs too — the
# create step above leaves an existing Release untouched, and --clobber
# makes the asset upload idempotent.
- name: Generate source SBOM (CycloneDX)
uses: anchore/sbom-action@v0
with:
path: .
format: cyclonedx-json
output-file: trusca-${{ steps.resolve.outputs.version }}.cdx.json
upload-artifact: false
upload-release-assets: false

- name: Attach SBOM to the Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.resolve.outputs.tag }}
VERSION: ${{ steps.resolve.outputs.version }}
run: |
set -euo pipefail
gh release upload "$TAG" "trusca-${VERSION}.cdx.json" --clobber

# ===========================================================================
# release-gate — prove the PUBLISHED images before revealing the Release
# (Phase I / P3-12, steps I2 + I3). Pulls the three multi-arch images at the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ Every source scan signs its CycloneDX SBOM with [cosign](https://docs.sigstore.d
Two readers:

- **Verifiers** (sections 1–4) — anyone who consumes a TRUSCA SBOM and wants to prove it is intact and was signed by a known deployment. Assumes a shell and the ability to install a CLI binary.
- **Operators** (section 5) — the person who deploys the portal and owns the signing key. Assumes Linux + Docker Compose proficiency and familiarity with [environment variables](./env-variables.md).
- **Operators** (section 5) — the person who deploys the portal and owns the signing key. Assumes Linux + Docker Compose proficiency and familiarity with [environment variables](../reference/env-variables.md).
:::

## Prerequisites

For verification:

1. A TRUSCA account with at least the **Developer** [role](./glossary.md#rbac-roles) on the project's team (the signature endpoints reuse the same access control as the SBOM export — an outsider sees `404`).
1. A TRUSCA account with at least the **Developer** [role](../reference/glossary.md#rbac-roles) on the project's team (the signature endpoints reuse the same access control as the SBOM export — an outsider sees `404`).
2. The project has at least one **succeeded** scan, and signing was configured on the deployment that ran it (see [section 5](#5-operator-key-setup)). A scan that was never signed has no signature artifacts.
3. [cosign](https://docs.sigstore.dev/cosign/installation/) installed on the machine that verifies (see [section 2](#2-install-cosign)).

## 1. Why sign an SBOM?

An [SBOM](./glossary.md#sca-core) tells a consumer *what is inside* a release. A **signature** answers two further questions the SBOM alone cannot:
An [SBOM](../reference/glossary.md#sca-core) tells a consumer *what is inside* a release. A **signature** answers two further questions the SBOM alone cannot:

- **Integrity** — were the SBOM bytes altered after the deployment produced them? A signature over the exact bytes detects any tampering.
- **Provenance** — *how* was the SBOM produced, and by whom? The [in-toto](https://in-toto.io/) / [SLSA](https://slsa.dev/) provenance attestation records the build platform identity and version.
Expand Down Expand Up @@ -263,7 +263,7 @@ The attestation stamps a builder identity into the provenance. Set these so a ve
| `SLSA_BUILDER_ID` | a vendor-neutral URI | URI naming this build platform in the provenance `builder.id` |
| `TRUSTEDOSS_VERSION` | bundled portal version | stamped into `builder.version` and the SBOM-generation context |

See [Environment variables → cosign signing](./env-variables.md) for the full key list and runtime semantics.
See [Environment variables → cosign signing](../reference/env-variables.md) for the full key list and runtime semantics.

## Troubleshooting

Expand Down Expand Up @@ -297,7 +297,7 @@ The artifact or bundle exceeds the deployment's configured download size cap. Th
## See also

- [SBOM](../user-guide/sbom.md) — export the SBOM the signature is over
- [Glossary](./glossary.md) — SBOM, SCA, VEX, and RBAC role definitions
- [Environment variables](./env-variables.md) — the `COSIGN_*` and `SLSA_*` keys
- [Glossary](../reference/glossary.md) — SBOM, SCA, VEX, and RBAC role definitions
- [Environment variables](../reference/env-variables.md) — the `COSIGN_*` and `SLSA_*` keys
- [API reference (Redoc)](pathname:///reference/api) — the generated endpoint contract
- [Report an issue](https://github.com/trustedoss/trusca/issues/new/choose) — if verification fails unexpectedly
4 changes: 3 additions & 1 deletion docs-site/docs/contributor-guide/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ The workflow runs four stages in order, each depending on the previous one:
version tags (`X.Y.Z` immutable, `X.Y` movable — never `:latest`).
3. **`release`** — creates the GitHub Release as a **draft**. Notes come from
`docs-site/docs/release-notes/X.Y.Z.md` when present, otherwise from GitHub's
auto-generated notes.
auto-generated notes. The job also generates a CycloneDX SBOM of the
release's own source tree (syft) and attaches it as a Release asset
(`trusca-X.Y.Z.cdx.json`) — an SCA product ships its own SBOM.
4. **`release-gate`** — pulls the freshly published `X.Y.Z` images, boots the
**production** `docker-compose.yml` (with the small
[`docker-compose.smoke.yml`](https://github.com/trustedoss/trusca/blob/main/docker-compose.smoke.yml)
Expand Down
9 changes: 9 additions & 0 deletions docs-site/docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ your own code. Still on the demo stack:
**Vulnerabilities** tab shows the open findings — switch it to the
**By upgrade** view for the exact version bumps that would clear them.

:::note First boot downloads the vulnerability DB
On a fresh stack the worker downloads the Trivy vulnerability database in the
background (1–3 minutes with internet egress). A scan that finishes before the
download does shows its **components but zero vulnerabilities** — that is the
DB still arriving, not a clean bill of health. No re-scan is needed: the
automatic re-match fills the findings in once the DB lands. See
[Vulnerability data](./admin-guide/vulnerability-data.md).
:::

A private repository needs a credential first — see
[Private repositories](./user-guide/projects.md#private-repositories). The full
scan reference (container scans, SBOM upload, cancelling, troubleshooting) is
Expand Down
4 changes: 2 additions & 2 deletions docs-site/docs/reference/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Move the finding to an excluded VEX state (`Not affected`, `False positive`, `Su

### Can I generate or import a VEX document? {#vex-export}

Yes — VEX can be exported and re-imported. See [Vulnerabilities](../user-guide/vulnerabilities.md).
Yes — VEX can be exported and re-imported. See [VEX documents](../user-guide/vex.md).

## SBOM and reports {#sbom-reports}

Expand All @@ -126,7 +126,7 @@ CycloneDX (JSON/XML) and SPDX (JSON/Tag-Value), with optional policy-annotated a

### Can I verify an SBOM was signed by TRUSCA? {#sbom-verify}

Yes — default SBOM exports are signed with cosign and can be verified offline. Note that export profiles are unsigned. See [SBOM signature verification](./sbom-signature-verification.md).
Yes — default SBOM exports are signed with cosign and can be verified offline. Note that export profiles are unsigned. See [SBOM signature verification](../ci-integration/sbom-signature-verification.md).

## Administration and operations {#admin-ops}

Expand Down
4 changes: 2 additions & 2 deletions docs-site/docs/reference/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ column.
scan's CycloneDX SBOM with cosign (`cosign sign-blob`) so a consumer
can verify it with `cosign verify-blob`. Key-based signing is the
self-hosted default; keyless (OIDC) is opt-in. See
[Verify SBOM signatures](./sbom-signature-verification.md) and
[Verify SBOM signatures](../ci-integration/sbom-signature-verification.md) and
[docs.sigstore.dev/cosign](https://docs.sigstore.dev/cosign/overview/).
- **Sigstore / Fulcio / Rekor.** The keyless-signing ecosystem cosign
draws on: **Fulcio** issues a short-lived signing certificate bound to
Expand All @@ -138,7 +138,7 @@ column.
[in-toto](https://in-toto.io/) Statement carrying
[SLSA](https://slsa.dev/) provenance (builder identity + build
context) alongside the SBOM signature. See
[Verify SBOM signatures](./sbom-signature-verification.md#inspect-the-provenance-attestation).
[Verify SBOM signatures](../ci-integration/sbom-signature-verification.md#inspect-the-provenance-attestation).

## License classification

Expand Down
11 changes: 6 additions & 5 deletions docs-site/docs/user-guide/components-and-licenses.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ the **UI label** column is what appears in tables and badges.
| `unknown` | **Unknown** | Surfaced for review; no automatic block. Always needs human review. | License could not be parsed; SPDX ID not matched by the classifier — see [below](#why-so-many-unknown). |

:::warning Classification source
The legal-tier classification (`forbidden` / `conditional` / `permissive` / `unknown`) is driven by a built-in SPDX-to-tier catalog. Per-organization rule customization is on the roadmap. Until then, super-admins can override individual entries in-place and restart the worker — an operator-only path.
The legal-tier classification (`forbidden` / `conditional` / `permissive` / `unknown`) is driven by a built-in SPDX-to-tier catalog. Until per-organization rule customization lands (see [Roadmap](#roadmap)), super-admins can override individual entries in-place and restart the worker — an operator-only path.
:::

### Why so many `unknown`? {#why-so-many-unknown}

:::info
Classification uses exact-match SPDX IDs. Suffix-less variants (`LGPL-3.0` instead of `LGPL-3.0-or-later`) fall through to `unknown`. If a component shows `unknown` despite a well-known SPDX ID, the source likely emitted a deprecated alias. Fuzzy SPDX normalization is on the roadmap.
Classification uses exact-match SPDX IDs. Suffix-less variants (`LGPL-3.0` instead of `LGPL-3.0-or-later`) fall through to `unknown`. If a component shows `unknown` despite a well-known SPDX ID, the source likely emitted a deprecated alias — see [Roadmap](#roadmap) for the planned fuzzy normalization.
:::

A separate, common cause is a manifest that names dependencies without their
Expand Down Expand Up @@ -333,8 +333,8 @@ kinds yet:
- **Trademark restrictions** (Apache-2.0 §6, BSD-4-clause).
- **Field-of-use restrictions** (BUSL-1.1).

For these, see the underlying license text via the component drawer; a
richer obligation taxonomy is on the roadmap.
For these, see the underlying license text via the component drawer
(see [Roadmap](#roadmap)).
:::

## Korean license content {#korean-license-content}
Expand Down Expand Up @@ -387,7 +387,7 @@ The license could not be parsed, or the SPDX ID was not in the classifier's exac

### Classification looks wrong

Classification is driven by the built-in SPDX-to-tier catalog (see [Classification source](#license-classification) above). For a one-off override today, a super-admin can patch the catalog and restart the worker; the per-organization customization path is on the roadmap. If the catalog entry is correct but a detected license disagrees with the declared one, review both findings in the component drawer (see [Declared vs. detected](#declared-vs-detected)).
Classification is driven by the built-in SPDX-to-tier catalog (see [Classification source](#license-classification) above). For a one-off override today, a super-admin can patch the catalog and restart the worker; per-organization customization is tracked on the [Roadmap](#roadmap). If the catalog entry is correct but a detected license disagrees with the declared one, review both findings in the component drawer (see [Declared vs. detected](#declared-vs-detected)).

### Lockfile not detected

Expand All @@ -403,6 +403,7 @@ Items the manual previously promised that are not in this release; tracked for l
- Manual **Override concluded license** action in the drawer (`team_admin`) — planned.
- Fuzzy SPDX normalization for suffix-less variants (`LGPL-3.0` → `LGPL-3.0-or-later`) — planned.
- Per-organization license-classification rule customization — planned; today classification uses the built-in catalog.
- Richer obligation taxonomy (network-use disclosure, patent-grant termination, trademark restrictions, field-of-use) — planned; today these are read from the license text via the drawer.

## See also

Expand Down
7 changes: 4 additions & 3 deletions docs-site/docs/user-guide/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Open `/integrations` and scroll to the **API keys** section. The list shows ever

2. Fill in the form:
- **Name** — free-text reminder of what the key is for (e.g. `github-action-checkout-service`).
- **Scope** — `org`, `team`, or `project`. Lower scopes are stricter; pick the smallest that covers the calls you need to make. The form has plain UUID inputs for `team_id` (required when scope=`team`) and `project_id` (required when scope=`project`); copy the IDs from the corresponding admin pages. A picker UI is on the roadmap.
- **Scope** — `org`, `team`, or `project`. Lower scopes are stricter; pick the smallest that covers the calls you need to make. The form has plain UUID inputs for `team_id` (required when scope=`team`) and `project_id` (required when scope=`project`); copy the IDs from the corresponding admin pages.

Who can issue each scope:

Expand All @@ -44,7 +44,7 @@ Open `/integrations` and scroll to the **API keys** section. The list shows ever
3. Click **Create**.

:::caution Keys do not expire in this release
The key-creation form does not yet collect an expiry. Every key issued in this release is valid until you explicitly **Revoke** it. Treat the key like any other long-lived secret — store it in your CI's secret manager, never in source control. An expiry preset is on the roadmap (see below).
The key-creation form does not yet collect an expiry. Every key issued in this release is valid until you explicitly **Revoke** it. Treat the key like any other long-lived secret — store it in your CI's secret manager, never in source control.
:::

The portal opens a **one-time reveal modal** with the full key:
Expand Down Expand Up @@ -126,7 +126,7 @@ URL to register at GitLab: `https://<your-host>/v1/webhooks/gitlab`.
<!-- docs-uat: id=integrations-github-webhook-202 kind=manual tier=manual -->
- After registering the webhook in GitHub, push a commit and check the **Webhook deliveries** view in GitHub — successful deliveries return HTTP 200.
<!-- docs-uat: id=integrations-audit-events kind=manual tier=manual -->
- A super-admin can confirm `target_table=api_keys&action=create` and `target_table=webhook_deliveries&action=create` events on `/admin/audit`. Team-scoped audit-log access is on the roadmap (see below).
- A super-admin can confirm `target_table=api_keys&action=create` and `target_table=webhook_deliveries&action=create` events on `/admin/audit`. Today the audit log is super-admin only — see [Roadmap](#roadmap).

## Troubleshooting

Expand All @@ -141,6 +141,7 @@ URL to register at GitLab: `https://<your-host>/v1/webhooks/gitlab`.
Items the manual previously promised that are not in this release; tracked for later releases.

- API-key expiry presets (30 / 90 / 180 / 365 days, custom) — planned; today every issued key is non-expiring until revoked.
- A team / project picker on the key-creation form — planned; today the form takes plain UUID inputs.
- **Project Settings → CI/CD** subtab with **Rotate webhook secret** action — planned; today the per-project `webhook_secret` is bootstrapped server-side.
- Team-scoped audit log at `/audit` for `team_admin` users — planned; today the audit log is super-admin only at `/admin/audit`.

Expand Down
4 changes: 2 additions & 2 deletions docs-site/docs/user-guide/sbom.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ is named distinctly (`sbom-<project>-<profile>.<ext>`) so it is never mistaken
for the canonical export.

:::caution Profile exports are not signed
The cosign [signature](../reference/sbom-signature-verification.md) covers only
The cosign [signature](../ci-integration/sbom-signature-verification.md) covers only
the **default** SBOM — the exact bytes produced at scan time. A policy profile
is generated on demand and
therefore has **no signature**; `cosign verify-blob` against a profiled export
Expand Down Expand Up @@ -332,7 +332,7 @@ Items the manual previously promised that are not in this release; tracked for l

## See also

- [Verify SBOM signatures (cosign)](../reference/sbom-signature-verification.md) — prove the SBOM is intact and signed by this deployment
- [Verify SBOM signatures (cosign)](../ci-integration/sbom-signature-verification.md) — prove the SBOM is intact and signed by this deployment
- [Components & licenses](./components-and-licenses.md)
- [Vulnerabilities](./vulnerabilities.md)
- [API overview](../reference/api-overview.md)
Loading
Loading