Skip to content

Commit 9ae2ef5

Browse files
committed
Add portfolio management docs
Signed-off-by: nscuro <nscuro@protonmail.com>
1 parent c2e715c commit 9ae2ef5

17 files changed

Lines changed: 677 additions & 3 deletions

context/diataxis-contract.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ correctly and safely.
7171
- Step-by-step beginner introductions (→ Tutorials).
7272
- Exhaustive parameter listings (→ Reference).
7373
- Design rationale or architectural background (→ Concepts).
74+
- REST endpoints or configuration property keys when the procedure is UI-driven (→ Surface language).
7475

7576
---
7677

@@ -105,6 +106,7 @@ product.
105106
- Step-by-step instructions (→ Tutorials or Guides).
106107
- Parameter or API field listings (→ Reference).
107108
- Actionable procedures ("do X, then Y") (→ Guides).
109+
- Java field names, REST endpoint paths, or runtime config keys (→ Surface language).
108110

109111
---
110112

@@ -186,3 +188,34 @@ Rules:
186188
Use relative links between documentation pages. Prefer linking to a specific
187189
section (`concepts/vulnerability-analysis.md#data-sources`) over linking to an
188190
entire page when the relevant information is in a subsection.
191+
192+
---
193+
194+
## Surface language
195+
196+
Each Diataxis type has a default surface vocabulary. Match it to the audience
197+
that consults the page.
198+
199+
- **Concepts**: UI labels and domain terms. Do not use Java field names
200+
(`isLatest`, `accessTeams`, `inactiveSince`), REST endpoint paths, or
201+
runtime configuration property keys. Refer to features the way they appear
202+
in the application. Permission codes and CycloneDX classifier names that
203+
surface verbatim in the product (BOMs, dropdowns, badges) are fine.
204+
- **Guides**: describe procedures via the UI by default. The user's path is
205+
the form, the dropdown, the toggle. Inline REST endpoints, request bodies,
206+
or configuration property keys only when the page is itself a technical
207+
procedure where the API or config file is the user's entry point (for
208+
example, "Upload a BOM via REST API", "Configure with environment
209+
variables"). Otherwise, link to the relevant Reference subsection and keep
210+
prose UI-first.
211+
- **Reference**: structured tables of UI-visible labels, dropdown values,
212+
classifier names, and other product-surface vocabulary belong here. The
213+
dedicated REST API and configuration-property references (the OpenAPI
214+
specs, the `application.properties` table) are the home for low-level
215+
identifiers. Other Reference subsections should also stay UI-first.
216+
- **Tutorials**: same default as Guides. The student is using the UI unless
217+
the tutorial is explicitly an API tutorial.
218+
219+
When a feature has both a UI label and a technical identifier, prefer the UI
220+
label and link out to Reference for the identifier. The reverse breaks for
221+
users who never see the API or the config file.

docs/concepts/.pages

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
title: Concepts
22
nav:
33
- index.md
4+
- About projects: projects.md
5+
- About tags: tags.md
46
- About access control: access-control.md
57
- About vulnerability data sources: about-vulnerability-data-sources.md
68
- About notifications: notifications.md

docs/concepts/access-control.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,5 @@ and holders of `PORTFOLIO_ACCESS_CONTROL_BYPASS` until one is assigned.
175175

176176
* [Permissions reference](../reference/permissions.md) for the full permissions table
177177
and default teams.
178+
* [About projects](projects.md) for how Dependency-Track models
179+
projects, hierarchies, and collection projects.

docs/concepts/changes-in-v5.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ shipped as a beta feature in v4 with known gaps and noticeable overhead on
111111
larger portfolios. v5 closes those gaps and reworks the implementation so
112112
the cost stays bounded as the project count grows.
113113

114+
### Retention policies for projects and metrics
115+
116+
v5 expires inactive project versions and time-series metrics on
117+
configurable schedules. v4 left both to grow unbounded, so operators
118+
carried stale portfolio data and ever-growing metric tables. See
119+
[Configuring project retention](../guides/administration/configuring-project-retention.md)
120+
and [time-series metrics retention](time-series-metrics.md#daily-partitions-and-bounded-retention).
121+
114122
### Centralized secrets
115123

116124
Credentials for integrations live in one place instead of spreading across

docs/concepts/component-policies.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ dependency graph, or operate on SPDX license expressions directly.
5959
## Where a policy applies
6060

6161
By default, a policy applies to every project in the portfolio. Narrow it to specific projects, to
62-
descendants of those projects, or to projects carrying specific tags. Scoping is flat: a policy
62+
descendants of those projects, or to projects carrying specific
63+
[tags](tags.md). Scoping is flat: a policy
6364
either applies to a project or does not. See
6465
[Component policies › Assignment](../reference/policies/component-policies.md#assignment) for the
6566
exact rules.

docs/concepts/projects.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# About projects
2+
3+
A **project** is the unit of tracking in Dependency-Track. Everything else, from components
4+
to findings to policy violations to metrics, hangs off projects. The **portfolio** is the
5+
set of all projects in an instance, and how you model it shapes what reports, alerts, and
6+
aggregations are useful later.
7+
8+
This page explains what a project is, how projects relate to each other, and the deliberate
9+
limits of the model.
10+
11+
## What a project is
12+
13+
Each project has:
14+
15+
- A name and an optional version that together identify it.
16+
- A classifier naming the kind of thing the project represents (an app, a library, a
17+
container image, a firmware image, and so on, matching CycloneDX). See the
18+
[classifier list](../reference/projects.md#classifiers).
19+
- Optional ecosystem identifiers: a Package URL, a CPE, or a SWID tag.
20+
- Descriptive metadata such as a group, a description, authors, a supplier, a manufacturer,
21+
and external references.
22+
- Tags (categorical labels) and project properties (typed key-value metadata).
23+
- An optional parent, forming a hierarchy.
24+
- An access list controlling which teams can see it.
25+
- Lifecycle state: an active flag, the timestamp of the last BOM import, the timestamp of
26+
the last vulnerability analysis, and the current risk score.
27+
28+
<!-- TODO(screenshot): docs/assets/images/concepts/projects/project-detail-header.png - Project detail header for a regular project at /projects/{uuid}/overview. Show: the version dropdown (closed), the "LATEST VERSION" badge, tag chips, description, and the severity pie charts to anchor the "what defines a project" discussion. -->
29+
30+
## What Dependency-Track does *not* assume
31+
32+
A few modelling decisions are deliberately left to the user. Knowing them up front avoids
33+
arguments later:
34+
35+
- **Dependency-Track does not prescribe what a project is.** A project can map to a single
36+
library, a deployable service, an environment of a service, or an entire product line.
37+
Pick the granularity that matches how you triage and report.
38+
- **Versions are opaque strings.** Dependency-Track does not parse, compare, or sort them.
39+
Semver-like ordering is not assumed. The "latest version" pointer is a manually maintained
40+
flag (see [Versions](#versions)), not a computed one.
41+
- **Projects cannot depend on projects.** Component-level dependencies live inside a BOM. The
42+
only relationship Dependency-Track tracks between projects is the parent-child hierarchy
43+
below, and that hierarchy is organizational, not a dependency graph. If service A consumes
44+
service B, that fact is not expressible as a project relation.
45+
- **A name and version together identify a project globally.** That pair is unique across
46+
the entire instance, independent of where the project sits in the hierarchy. The same
47+
name and version cannot exist under two different parents.
48+
49+
## Active and inactive projects
50+
51+
A project is **active** by default. Marking it inactive records the time and changes its
52+
behavior:
53+
54+
- It disappears from active portfolio views unless the viewer opts in to show inactive
55+
projects.
56+
- It cannot serve as a parent.
57+
- It becomes eligible for retention-driven deletion (see [Retention](#retention)). Active
58+
projects never are.
59+
60+
A project with active children cannot become inactive. Mark the children first, or accept
61+
that the parent stays around for as long as something underneath stays live.
62+
63+
## Hierarchies
64+
65+
A project can have one parent and any number of children. Hierarchies are organizational:
66+
they let you group by product, environment, team, or any other axis that fits how you work.
67+
68+
Two things flow through the hierarchy:
69+
70+
- **Access control.** A team that can see a parent can also see the parent's descendants.
71+
See [Access control](#access-control) below.
72+
- **Aggregated metrics on collection projects.** A [collection project](#collection-projects) reads
73+
metrics from its children to produce its own. Regular parents do not. The risk score on a
74+
regular parent reflects only that parent's own components, not its children.
75+
76+
Constraints worth remembering:
77+
78+
- A project cannot be its own ancestor. Dependency-Track rejects cycles.
79+
- The hierarchy does not affect identity. A name and version pair remains globally unique,
80+
so the same combination cannot appear under two different parents.
81+
82+
(Inactive projects cannot serve as a parent either. See [Active and inactive projects](#active-and-inactive-projects).)
83+
84+
<!-- TODO(screenshot): docs/assets/images/concepts/projects/projects-tree-view.png - Projects landing at /projects with "Show flat view" toggled OFF, the tree expanded one level, and at least one collection-project parent visible. Show: the portfolio as a hierarchy and the calculator icon that distinguishes a collection project from a regular parent. -->
85+
86+
## Collection projects
87+
88+
A **collection project** is a parent whose only role is to combine metrics from its
89+
children. It holds no components or services of its own. Instead, it surfaces the metrics
90+
of its children using one of three modes:
91+
92+
| Mode | Behavior |
93+
|:---------------------------|:--------------------------------------------------------------------|
94+
| Roll up every direct child | Combines metrics from every direct child. |
95+
| Roll up by tag | Combines metrics from direct children carrying a chosen tag. |
96+
| Roll up the latest version | Combines metrics from direct children marked as the latest version. |
97+
98+
Collection projects are useful for product or portfolio aggregations that span versions,
99+
services, or environments without forcing every child to share a tag scheme. They differ
100+
from regular parents in three important ways:
101+
102+
- They have no classifier. The classifier field disappears once a project becomes a
103+
collection project.
104+
- They cannot have components, services, or a dependency graph. The detail page hides those
105+
tabs and shows a *Collection Projects* tab listing children instead.
106+
- They do not accept BOM uploads.
107+
108+
For when to reach for which mode and how to set them up, see
109+
[Organizing projects into hierarchies](../guides/user/organizing-projects.md).
110+
111+
<!-- TODO(screenshot): docs/assets/images/concepts/projects/collection-project-header.png - Project detail header for a collection project, hovering the calculator icon so the tooltip showing the configured logic is visible. Show: how a collection project surfaces in the UI and that the regular Components / Services / Dependency Graph tabs are absent (Collection Projects tab is present instead). -->
112+
113+
## Versions
114+
115+
Two or more projects can share a name. Together they represent the version history of one
116+
logical thing. A *latest version* flag marks one of them as current. At most one version
117+
per name carries the flag.
118+
119+
The latest-version flag drives:
120+
121+
- The latest-version collection mode.
122+
- The badge URLs that resolve a project by name without specifying a version.
123+
- The *LATEST VERSION* badge in the project header.
124+
125+
Because Dependency-Track does not parse version strings, nothing here is automatic. You
126+
set the flag manually when promoting a release. Cloning a project produces a new sibling
127+
with chosen inclusions (components, services, tags, properties, audit history, access list,
128+
policy violations) and is the typical path for starting a new version. See
129+
[Managing project versions](../guides/user/managing-project-versions.md).
130+
131+
## Tags and properties
132+
133+
A project carries two kinds of metadata. A **tag** is a categorical label that many
134+
projects can share. Policies, alerts, the tag-filtered collection mode, and the project
135+
list filter all read tags. For the wider model see [About tags](tags.md). A **project
136+
property** is a typed key-value pair (group, name, value, type, optional description)
137+
scoped to one project. The policy engine, alerting, and collection logic do not consult
138+
properties. Use a tag for a label that may apply to many projects, and a property for
139+
per-project structured data you want to read back later.
140+
141+
## Retention
142+
143+
By default, inactive projects stick around indefinitely. When the operator turns on
144+
retention, a scheduled maintenance task deletes inactive projects according to one of two
145+
policies:
146+
147+
- **By age**: delete inactive projects older than a configured cutoff.
148+
- **By version count**: keep the most recent N inactive versions per name, and delete the
149+
rest.
150+
151+
Active projects are never touched. See
152+
[Configuring project retention](../guides/administration/configuring-project-retention.md).
153+
154+
## Access control
155+
156+
Each project has an access list. A team can see a project when:
157+
158+
- The team appears on that project's access list, **or** on the access list of the
159+
project's ancestors. Granting a team access to a parent also grants access to every
160+
descendant.
161+
- The team holds the `PORTFOLIO_ACCESS_CONTROL_BYPASS` permission, which overrides the
162+
access list entirely.
163+
164+
Use this when designing a hierarchy: shared access concerns sit at parents, and the
165+
children inherit them automatically. To revoke inherited access, remove the team from
166+
the ancestor that granted it. A descendant cannot opt out on its own.
167+
168+
For the wider model (users, teams, and which permissions gate which actions), see
169+
[About access control](access-control.md) and the
170+
[Permissions reference](../reference/permissions.md).

docs/concepts/tags.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# About tags
2+
3+
A **tag** is a short, shared label. You can attach the same tag to
4+
[projects](projects.md), [component](component-policies.md) and
5+
[vulnerability](vulnerability-policies.md) policies, vulnerabilities, and
6+
[alerts](notifications.md), and the rest of the system reads tags to scope behavior.
7+
Tags are deliberately lightweight: a name and nothing else.
8+
9+
## What a tag is
10+
11+
A tag is just a name. Names are unique across the instance, so two attachments of the
12+
same name refer to the same tag. A tag has no value, no type, no namespace, no
13+
description. If you need richer metadata bound to a project, use
14+
[project properties](projects.md#tags-and-properties) instead.
15+
16+
Tags are many-to-many with the things they label. A project can carry many tags, and a
17+
tag can label many projects. Removing a tag from one project does not affect any other.
18+
19+
## What tags do
20+
21+
Tags are a scoping primitive. Different parts of the system look at the same tag set:
22+
23+
- **Project filtering.** The project list can filter by tag.
24+
- **Policy assignment.** A component or vulnerability policy can target only projects
25+
carrying specific tags. See [About component policies](component-policies.md) and
26+
[About vulnerability policies](vulnerability-policies.md).
27+
- **Collection projects.** The tag-based collection mode aggregates only the children
28+
carrying the configured tag. See
29+
[About projects › Collection projects](projects.md#collection-projects).
30+
- **Alerts.** An [alert](notifications.md) can fire only for projects carrying specific tags.
31+
- **Vulnerability tagging.** You can attach tags to vulnerabilities for triage and
32+
reporting.
33+
34+
## Tags versus project properties
35+
36+
Both attach metadata to a project, but they answer different questions:
37+
38+
- Reach for a **tag** when the value is a label that may apply to many projects, and you
39+
expect the policy engine, alerting, or the tag-filtered collection mode to read it.
40+
- Reach for a **project property** when the value is per-project structured data (a
41+
typed key with a value) that you want to read back later, but no built-in feature
42+
consumes it.
43+
44+
Properties carry types and group names, while tags do not. If you find yourself encoding two
45+
pieces of information into one tag (`team:platform`, `env=prod`), that is a signal to
46+
reach for a property, or for two separate tags, instead.
47+
48+
## Lifecycle
49+
50+
Tags come into being implicitly on first use. Attaching a name that does not exist
51+
creates the tag. Detaching the last attachment leaves an orphan tag, which the
52+
maintenance task cleans up on its next run. Tags carry no per-tag access control. Any
53+
user who can edit a project can also tag it.

docs/concepts/vulnerability-policies.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ rather than replace them. The important differences are:
2222

2323
* **VEX analyses are static.** A VEX statement records a decision for a specific finding at a specific
2424
moment. Vulnerability policies are rules. A single policy can match many findings now and in
25-
the future, based on conditions such as component version ranges, project tags, or dependency graph
26-
relationships.
25+
the future, based on conditions such as component version ranges,
26+
[project tags](tags.md), or dependency graph relationships.
2727
* **VEX cannot express constraints.** A policy condition can say "apply this decision only while the
2828
affected component sits behind a specific transitive dependency" or "only for projects tagged
2929
`3rd-party`". VEX cannot do this.

docs/guides/administration/.pages

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ nav:
1414
- configuring-oidc.md
1515
- managing-notification-templates.md
1616
- debugging-notifications.md
17+
- configuring-project-retention.md
1718
- backing-up.md
1819
- upgrading-instances.md
1920
- migrating-from-v4.md

0 commit comments

Comments
 (0)