Skip to content
qibdo qibdo
Theme
Book a demo

Namespaces, repositories, and artifacts

Registry organises everything you store into a three-level hierarchy. This page explains each level, the artifact and tag model beneath it, and the invariants the service enforces. It stays conceptual; the API reference is where the exact fields, values, and limits live.

flowchart LR
  classDef primary fill:#e8e8ff,stroke:#1100ff,stroke-width:2px,color:#0e0d1a
  classDef accent fill:#e2faec,stroke:#00e64d,stroke-width:2px,color:#0e0d1a
  classDef neutral fill:#ececf1,stroke:#302e45,stroke-width:2px,color:#0e0d1a

  ws["workspace"]:::neutral --> ns["Namespace"]:::primary
  ns --> repo["Repository"]:::accent
  repo --> art["Artifact"]:::primary
  art --> tag["Tag"]:::accent

A namespace is the top-level isolation boundary inside a workspace’s registry. It owns repositories and namespace-scoped access policies. A namespace has a DNS-style name (3 to 63 characters, matching ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$), is pinned to a region at creation, and exposes a registry host that clients log in against.

Deleting a namespace requires it to be empty. The call fails with a not-empty error while the namespace still has any repository, so delete the repositories first.

A repository is a named collection of artifacts inside a namespace, with the same DNS-style name rules. Two choices shape it:

  • Visibility: a repository is either private or public. A private repository requires a pull grant even to read from it; a public one is readable without one.
  • Format: Docker, Helm, or OCI. The format is chosen at creation and fixed afterward; an update does not change it.

A repository can also enforce an immutable-tag policy, where the registry refuses to overwrite an existing tag on push.

Deleting a repository removes the repository. The deployment-lock guard that protects an in-use artifact applies to artifact deletion, not to repository or namespace deletion (see The two deletes below).

An artifact is one OCI artifact: a manifest (the JSON document the registry stores) plus the blobs it references (image layers, configs). Key invariants:

  • It is identified by a content-derived digest of the form sha256:…, which is stable for the lifetime of the manifest. Identical content always yields the same digest.
  • It reports its total size (the manifest plus its referenced blobs) and its OCI media type, for example application/vnd.oci.image.manifest.v1+json.
  • It lists every tag currently pointing at the manifest, returned inline. The list is empty when the artifact is referenced only by digest.

You do not create an artifact through the control plane: artifacts come into existence when a client pushes through the registry data plane, and the control plane exposes them read-only.

A tag is a mutable label that points at an artifact’s manifest digest. A tag’s name is what you use in docker pull foo:<name> and is unique per repository; it records the digest it currently points at and when it was last pushed. A tag is immutable when the repository’s immutable-tag policy applies, in which case the registry refuses to overwrite it on push.

Multiple tags can point at the same digest. Re-pushing image:latest moves the latest tag to a new digest (unless that tag is immutable); the previously tagged manifest survives if any other tag still references it or it is referenced by digest.

Listing the artifacts in a repository supports filtering and ordering, but on two deliberately different field sets. Artifacts are read through the registry engine rather than the platform’s own query layer, which is why the two sets differ.

Filter on any of these three:

FieldMatches
digestthe manifest digest, exactly
tagsa tag name, exactly
scan_statusthe artifact’s scan state, for example ARTIFACT_SCAN_STATUS_SCANNED

Only = is available, and terms combine only with AND. Other comparison operators and OR are rejected. Note that tags is matched with = on a single tag name, even though an artifact response carries a list of tags:

Terminal window
curl --get https://api.qibdo.example.com/registry/v1/workspaces/$WORKSPACE/engines/qibdo/repositories/$REPO/artifacts \
--header "Authorization: Bearer $QIBDO_API_TOKEN" \
--data-urlencode 'filter=tags = "v1.0" AND scan_status = "ARTIFACT_SCAN_STATUS_SCANNED"'

Order by any of these three, which are sortable rather than filterable:

FieldOrders by
push_timewhen the artifact was pushed
pull_timewhen it was last pulled
size_bytestotal manifest and blob size
Terminal window
curl --get https://api.qibdo.example.com/registry/v1/workspaces/$WORKSPACE/engines/qibdo/repositories/$REPO/artifacts \
--header "Authorization: Bearer $QIBDO_API_TOKEN" \
--data-urlencode "order_by=push_time desc"

The split is worth reading carefully: a field that appears in one table does not appear in the other. Ordering by push_time works, filtering on it does not.

For the filter language itself, see Filtering.

Registry exposes two intentionally separate delete operations, because detaching a label is not the same as destroying content:

  • Deleting an artifact removes the manifest and detaches all of its tags. It is blocked when an active deployment lock pins the (repository, digest) pair.
  • Deleting a tag removes a single tag (a “detag”). The manifest survives if any other tag still references it, or if it is referenced by digest.

Both return an operation so the deletion is audited. An artifact may be addressed by either its digest (sha256:…) or a tag name; the registry resolves both.