Core
Tags: Projects, Workspaces & Labels
Three independent dimensions a service can belong to at once.
A service is not filed into one folder. It carries membership in three independent dimensions at the same time — projects, workspaces and labels — each stored in its own join table (service_projects, service_workspaces, service_labels). Nothing moves when you reorganise; you only add or remove a tag.
The three dimensions
- Workspace — the tenancy boundary. Members, roles, invitations and RBAC hang off it. A service can be shared across several workspaces.
- Project — a purpose grouping (Acme Web, Internal tooling). Projects also own shared environment variables, and a service inherits the union of every project it is linked to.
- Label — a free-form coloured tag (production, staging, team-x) for slicing across the other two.
Filtering
The top bar has one chip group per dimension. Selections OR within a group and AND across groups: picking projects A and B plus the label production returns services in (A or B) that are also tagged production. The selection is persisted per browser under ninedeploy.tagScope, so a reload keeps your view.
REST
# Every dimension is a comma-separated id list; omit one to leave it unfiltered.
GET /v1/services?tagProjectIds=3,7&tagLabelIds=2
# Manage the flat lists
GET|POST /v1/projects PATCH|DELETE /v1/projects/:id
GET|POST /v1/labels PATCH|DELETE /v1/labels/:id
# Replace one service's whole membership in a single round-trip
PUT /v1/services/:id/tags
{ "projectIds": [3], "workspaceIds": [1], "labelIds": [2, 5] }In the panel
- Organize → Workspaces — tenants, members, roles and invitations (including invites to addresses with no account yet).
- Organize → Projects — create, rename and delete projects; the row shows service and database counts.
- Organize → Labels — full CRUD with an eight-token colour palette; clicking a label scopes the services list to it.
- Service detail → Tags card — edits all three dimensions of one service and saves them in one request.
The canonical guides live in the repository's docs folder.