Skip to main content

Projects

A project is the unit of source-tracked software the portal knows about. It owns scans, components, vulnerabilities, license findings, obligations, and a generated NOTICE file. Most workflows start by adding a project.

Audience

Engineers and team leads who scan their own services. Requires sign-in. The role on the project's team must be developer or higher to create / archive; team_admin to change visibility.

Anatomy of a project

FieldDescription
NameDisplay label (free text). Need not be unique — two projects in the same team may share a name; the slug is the unique key.
SlugURL-safe identifier ([a-z0-9-]+). Unique within a team — a duplicate slug is rejected with 409.
DescriptionOptional free-text summary surfaced on the project list and Overview tab.
Git URLGit URL the scan pipeline clones from. HTTPS supported. Private repos require credentials embedded in the URL — see Private repos.
Default branchThe branch the scan pipeline checks out (defaults to main). Editable from Project Settings after creation.
Visibilityteam (the only value accepted in this release — visible to members of the owning team). Set automatically on creation; mutable only via PATCH.
Owning teamThe team the project belongs to. Set automatically to your active team on creation.

Adding a project — UI

The Projects sidebar entry lands on the team-scoped project list — every project that belongs to your active team, with status badges, severity counts, an inline Scan action, and a compact per-project meta row showing n scans · m releases · last scan <relative time>:

/projects list — team-scoped table with name, last-scan status badge, severity counts, and an inline Scan action per row

The meta row sums:

  • scans — total scans this project has ever run (any status; archived runs included).
  • releases — count of release snapshots the project has accumulated (see Releases).
  • last scan — relative time since the last scan moved to a terminal status. until the first scan completes.

The list endpoint aggregates these three fields server-side in a single query, so the row is cheap to render even on portfolios of hundreds of projects.

  1. Sign in.

  2. Click Projects in the sidebar.

  3. Click New project in the top-right.

  4. Fill out the form:

    • Name (required)
    • Description (optional)
    • Git URL (required for source scans)
  5. Click Create.

    New project form — name, description, and Git URL fields

You land on the project's Overview tab. From here you can run the first scan — see Scans.

Project detail — Overview tab with risk gauge and quick actions

The default branch (main), visibility (team), and owning team (your active team) are set server-side and can be reviewed from Project Settings.

Detail-page tabs

The detail page exposes the following tabs, left-to-right:

TabWhat it shows
OverviewRisk axes (Security + License), the Build gate verdict, the Project info card (Git URL, default branch, owning team, created-at, last-scan time), and recent scans.
ReleasesSnapshots of the project at each terminal scan — the snapshot list, a "view snapshot" pin action, and per-release diff entry points. See The Releases tab.
ComponentsEvery component the scan discovered. See Components & licenses.
VulnerabilitiesOpen and triaged CVE findings. See Vulnerabilities.
LicensesThe same data viewed by SPDX identifier and tier.
ObligationsPer-component obligations + NOTICE-file generation. See Components & licenses → Obligations.
SBOMCycloneDX / SPDX exports, byte-stable. See SBOM.
ReportsGenerate-cards for NOTICE, SBOM, Vulnerability PDF, and VEX plus the project's unified download / export history. See The Reports tab.
SourceThe fetched first-party source tree from the latest succeeded scan, with file-level license findings highlighted. Sits between Reports and Remediation.
RemediationPer-component upgrade recommendations from the latest scan, including the opt-in npm remediation PR flow.
SettingsProject metadata, archive action, CI-integration helpers.
Tab order

The Source tab used to sit immediately after Licenses; it was moved to the right of Reports so the data-output cluster (SBOM / Reports / Source) is contiguous. Bookmarks and ?tab=source deep links continue to work — the slug is unchanged.

Adding a project — API

curl -sS -X POST https://trustedoss.example.com/v1/projects \
-H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"team_id": "8f0c1e2a-...your team UUID...",
"name": "checkout-service",
"slug": "checkout-service",
"description": "Storefront checkout service",
"git_url": "https://github.com/acme/checkout-service.git"
}' | jq .

The response includes the project's UUID — keep it; it is the value you wire into the GitHub Action's project-id input and the GitLab CI variable.

Required fields: team_id, name, and slug. Optional: description, git_url, default_branch, and visibility. The schema rejects unknown fields (extra="forbid"), so omitting team_id or slug returns 422 (missing: body.team_id).

Finding your team_id: in the UI the project-create form has a team selector, so you never type the UUID. Over the API any signed-in user reads their teams from GET /auth/me (the auth router is mounted at /auth, not /v1) — the response carries a memberships[] array, each entry with its team_id, team_name, and your role in that team. (GET /v1/admin/teams also lists teams but is super-admin only — a team_admin calling it gets 404.) In this release the team_id field is not derived from your session — it must be in the request body.

Visibility

  • team (default and only accepted value in this release) — only members of the owning team see the project, its scans, and its findings.

Visibility is set automatically on creation. PATCH currently rejects any value other than team. Audit log records the actor on every PATCH.

See Roadmap for organization (org-wide read) availability.

Archive

  • Archive — keeps the project, its history, scans, and findings, but hides it from default lists and disables new scans. Useful when a service is retired but you still need its compliance trail.

DELETE /v1/projects/{id} performs a soft-delete (archive). The portal does not currently expose a permanent-delete operation; audit-log entries persist regardless.

The Archive action lives on Project Settings → Archive and uses an inline confirm strip to prevent accidents.

Private repositories

Source scans clone the repository from inside the worker container. Authentication option supported in this release:

  • HTTPS + Personal Access Token — set the URL to https://<token>@github.com/acme/checkout-service.git. The token is stored as part of git_url and never returned by the API in plaintext form on read endpoints.
Private repos in this release

Today the only supported credential model is HTTPS + PAT embedded in the git URL (https://<token>@github.com/acme/payment-service.git). The PAT is persisted in the project row (the API never returns it in plaintext on read endpoints, and git_url is masked in audit logs).

Implications:

  • A leaked DB snapshot still leaks every embedded PAT. Use a short-lived PAT with read-only scope.
  • SSH keys and GitHub-App installations are on the roadmap for ; rotate aggressively in the meantime.

For SSH deploy keys, see Roadmap.

Risk score — two axes

The Overview tab now surfaces two risk axes on the project gauge instead of one composite number, so the two failure modes can be read independently:

  • Security risk — driven by the project's open vulnerability mix. The band (Critical / High / Medium / Low / Info) is set by the most severe open finding; within the band the score scales as n / (n + 4) (non-saturating, so the band itself is the primary signal — adding more findings cannot bump you up a band).
  • License risk — driven by the project's license-tier mix. Forbidden licenses dominate the band; Conditional rows raise the score within the band but never promote it to Critical on their own (the previous "any conditional component = Risk 100" behaviour was removed in W1).

The legacy single risk_score field is still exposed on the API as max(security_axis, license_axis) for back-compat with the build gate and CI integrations; the UI uses the two-axis breakdown.

Both axes refresh after every scan and after every CVE re-detection. Read them as relative indicators across your portfolio, not absolute SLAs — drilling into the project shows the per-axis breakdown.

Old "single risk gauge" screenshots

Screenshots taken before W1 show a single gauge labelled "Risk". The two-axis card replaces it. The numbers are not strictly comparable between the old single score and either of the two new axes — re-baseline against your portfolio after the upgrade.

Build gate verdict (Overview tab)

The Overview tab shows a Build gate card next to the risk gauge. It surfaces the same build-blocking verdict the CI integration computes — so you can read the gate result in the portal without opening a CI log. The card evaluates the project's latest successful scan.

The build gate (also called the policy gate) is the CI-blocking mechanism that exits non-zero when a build carries critical CVEs or forbidden-tier licenses. The concept and how to wire it into a pipeline live in GitHub Actions → the build gate and Glossary → Build gates; this card is the read-only, in-UI view of the same verdict.

The card shows:

ElementMeaning
Pass / Fail badgePass (green, shield-check) when the latest successful scan has no critical CVEs and no forbidden licenses; Fail (red, shield-x) otherwise.
ReasonOn Fail, a one-line explanation of what tripped the gate.
Critical CVEsCount of open critical-severity findings on the evaluated scan. Open = status not in not_affected, fixed, false_positive.
Forbidden licensesCount of distinct components carrying at least one forbidden-tier license.
EPSS ≥ {threshold}Shown only when an operator has enabled the EPSS gate (GATE_EPSS_THRESHOLD set on the portal). Count of open findings whose EPSS score meets or exceeds the threshold. Hidden when the EPSS gate is disabled (the default). See Gate the build on EPSS.
No scan yet

A project that has never had a successful scan shows a neutral No scan yet state instead of a green pass — there is nothing to evaluate. Run a scan (see Scans) and the card fills in.

CVE — Common Vulnerabilities and Exposures; EPSS — Exploit Prediction Scoring System. See the Glossary for both.

The card is read-only — it reflects the verdict but does not change policy. The thresholds (severity floor, EPSS) are operator- and CI-side settings; see GitHub Actions and GATE_EPSS_THRESHOLD.

Project info (Overview tab)

The Overview tab has a Project info card next to the risk gauges. It collapses the project's identifying metadata into one read-only block, so you do not have to open Settings for a quick lookup:

FieldSourceNotes
Git URLProject git_url.Click-to-copy. The URL is masked when a personal-access token is embedded (the token segment is rendered as ***); the raw value never appears on read endpoints.
Default branchProject default_branch.Editable from Settings.
Owning teamProject team.Links to the team's /admin/teams/{id} admin view when the viewer is super_admin.
CreatedProject created_at.Absolute timestamp on hover, relative time on the face.
Last scanProject last_scan_at (the same value the project list aggregates). until the first scan reaches a terminal status.

The card is the same data the project-list meta row exposes, surfaced once at the top of the detail page so the reader does not have to bounce back to the list to remember the project's repo URL.

The Releases tab

Every time a scan reaches a terminal succeeded status the portal records a release snapshot — an immutable point-in-time view of the project (component list, license tier mix, vulnerability findings, scan id) tagged with the scan's completion timestamp. The Releases tab on a project lists those snapshots newest-first:

ColumnWhat it shows
SnapshotThe scan completion time (yyyy-mm-dd HH:MM) + relative time.
Scan kindsource or container.
Severity countsCritical / High / Medium / Low at snapshot time.
License mixAllowed / Conditional / Forbidden bars at snapshot time.
ActionsView components (jumps to the Components tab pinned to that scan) and View snapshot (pins ?scan=<id> and reloads the Overview with the snapshot's data).

Click a release row directly to navigate to the Components tab with the snapshot pinned. The pin propagates as a ?scan=<id> URL parameter so the deep link survives reload and can be shared with a teammate — every tab on the project (Components, Vulnerabilities, Licenses, …) reads from the pinned snapshot until you clear the pin in the breadcrumb. Removing the pin restores the latest succeeded scan as the data anchor everywhere.

The companion Compare screen (linked from the Releases-tab toolbar) takes two snapshot ids and shows the added / removed components and severities between them — the canonical diff view for "what changed between release X and release Y".

The Reports tab

The Reports tab is a single landing page that unifies the project's downloadable artifacts:

  • Four generate cards for NOTICE, SBOM, Vulnerability PDF, and VEX. Each card is a deep link — clicking the card's action button switches to the relevant domain tab (Obligations / SBOM / Vulnerabilities / Vulnerabilities) where the actual format chooser and download buttons live. The currently pinned ?scan= snapshot is preserved across the jump.
  • An export history table on the right, with columns When (relative + absolute timestamp), Who (the actor's email — for anonymized rows kept for audit), Type (one of NOTICE / SBOM / Vulnerability PDF / VEX), Format (the exact format string — cyclonedx-json, spdx-tv, openvex, etc.), Scan (first eight characters of the scan id), and Size (humanized; when the renderer did not record a size).
  • A toolbar Type multi-select filter and Prev / Next pagination, both mirrored to the URL as ?rpt_type=<type> / ?rpt_page=<n> so a filtered view is reload-safe and link-shareable.

Authorisation is the same posture as the SBOM and PDF exports — any team member with at least developer can read history; non-members receive 404 (existence-hide). The history table is append-only: there is no edit, delete, or replay action. To re-download an artifact, click the relevant generate card and re-export it from the domain tab.

The Reports tab does not duplicate the domain-tab download UX

Generate cards always deep-link to the domain tab (Obligations, SBOM, Vulnerabilities) rather than spawning a generation dialog inside the Reports tab. The intent is to keep one canonical UX per format and avoid drift between two download surfaces. The added value of the tab is the history view across all formats in one place.

Verify it worked

After creating a project:

  1. The project appears in Projects with status Idle (no scans yet).
  1. The Overview tab shows zero components and zero vulnerabilities.

    -- components / vulnerabilities are scan-scoped, so a project
    -- without a scan necessarily shows zero of both
    SELECT count(*) FROM projects p
    WHERE p.name = 'docs-uat-new-project'
    AND NOT EXISTS (SELECT 1 FROM scans s WHERE s.project_id = p.id);
  1. The audit log (/admin/audit, super-admin only) records target_table=projects&action=create with your user_id.

    SELECT count(*) FROM audit_logs
    WHERE target_table = 'projects'
    AND action = 'create'
    AND actor_user_id IS NOT NULL
    AND created_at > now() - interval '1 hour';

Troubleshooting

"Repository URL is invalid"

The wizard validates the URL must start with http:// or https:// (HTTPS strongly preferred). git@… and ssh://… URLs are not accepted by the form in this release; use the HTTPS clone URL. The portal does not verify reachability — that happens at scan time. If the URL is rejected at form submission, double-check for typos.

"Project slug already in use"

The slug (not the name) is unique per team — the 409 fires when another project in the same team already uses that slug. Names may repeat. Pick a different slug, e.g. checkout-service-legacy.

Forbidden when creating a project

Your role on the owning team is below developer. Ask a team admin to invite you with the right role — see Users & teams.

Roadmap

Items the manual previously promised that are not in this release; tracked for later releases.

  • Project tags for portfolio grouping — planned.
  • organization (org-wide) visibility — planned.
  • SSH deploy-key generation from Project Settings — planned.
  • Permanent project delete with typed-name confirmation — under design; soft-delete (archive) is currently the only option.
  • SSH (git@…, ssh://…) URL acceptance in the create wizard — planned.

See also