Documentation
Package registry guide

Package registries

Store and distribute packages in project-owned registries. Mozaic supports NuGet, npm, Maven, OCI, and Debian APT. This guide walks through NuGet setup and publication, with separate Maven and Debian APT instructions.

NuGet v3npmMavenOCIDebian APT
Discover native contentOrganization › Artifacts, or project › Artifacts
Manage feedsProject settings › Packages
Successful resultA listed, published package that a permitted client can restore
Artifacts / Discover published content

Find native versions, revisions, and retained files.

Open Artifacts in the organization to search published content across currently authorized projects, or open a project's Artifacts page to stay within that project. The catalog covers NuGet, OCI, NPM, Maven, and Debian through their native identities. Registry settings and scoped client credentials remain separate management workflows.

Search and project, adapter, and NuGet listing filters run on the server. Each page reports only its returned items and offers a continuation when more results are available. Filters and page cursors remain in the URL through reload and Back navigation. Organization membership is required; this reader does not replace anonymous public pages or extend personal access token permissions.

  1. Open an artifact identity.Each result names its project and registry. The same package name in two feeds identifies two distinct artifacts. Existing project Packages pages remain available for the earlier NuGet workflow.
  2. Select immutable native content.NuGet history leads to an exact retained version and package SHA-256. Listed state, deprecation, and public availability are separate facts. OCI history leads to an immutable manifest digest, media type, and size; Current tags is a separate paged view because tags can move to different digests.
  3. Use the verified endpoint.Copy the displayed POSIX-shell command for an exact NuGet or NPM version, or OCI digest. NuGet uses the server-supplied stable service index. OCI uses the server-supplied tenant authority and immutable registry UUID with the native repository and digest. A usage command grants no registry credentials; private pulls, installs, or restores still require separately authorized credentials.
NPM
A scoped or unscoped name belongs to one registry. Each retained version selects an immutable version row with SHA-256, SHA-512 integrity, size, and publication time. Deprecation and availability are independent. Current dist-tags is a separate bounded mutable snapshot; selecting a tag opens its exact returned version. Neither the tag name nor version ordering establishes a latest release.
Maven
The case-sensitive native file path is the identity, including JARs, POMs, classifiers, snapshots, sidecars, and metadata. Each revision has its own immutable revision ID and hash. The current path head is a separate fact. Coordinates appear only when the native file has one; maven-metadata.xml does not acquire an invented package version. Maven clients use the current path, while Download exact revision retrieves the selected retained bytes.
Debian
The identity includes registry, actual suite, component, package, and binary architecture; no architecture means a source package. A retained version binds an exact generation ID and native version, including its epoch. Current-generation status, Release expiry, and public availability remain separate. Every file in the exact generation/version is downloadable; source packages include the .dsc and every source file it binds, such as upstream and Debian archives. APT uses the currently published repository generation; a historical or expired Release is not current public APT availability. Earlier generations without verified package-index membership remain protocol evidence and are not inferred into catalog packages.

NPM, Maven, and Debian downloads use the authorized exact content route. A current dist-tag, Maven path head, or APT path never substitutes for a selected immutable version, revision, or generation. Download access is checked again when the file is requested.

The catalog displays current native content identity and availability. It does not infer a producing pipeline, private publication provenance, or a deployment result. Exact identity and version URLs read that content directly without scanning earlier result pages. Missing, revoked, retired, or inaccessible content becomes unavailable on the next read.

01 / Before you begin

Separate feed administration from package use.

Prerequisites

  • A verified Mozaic account and membership in the organization that owns the project.
  • An existing project. Every feed belongs to one project; there is no personal package namespace.
  • The Manage packages claim at the project or organization scope to create feeds, issue credentials, change lifecycle state, or configure upstreams.
  • A fresh sign-in for credential creation and destructive lifecycle actions.
  • A current .NET SDK for the dotnet CLI workflows below.

Feed management permission does not become a NuGet client credential. Create a separately scoped, expiring token for each developer workstation or automation client.

Registry identity: the Registry ID is immutable and provides stable client URLs; the editable slug provides convenient URLs that change when the slug changes. A protocol slug must be unambiguous for that adapter across the operated service; if another organization uses the same slug, the convenient URL fails closed and the Registry ID URL remains available. Adapters may also expose a permanent Protocol namespace for protocol-native package or repository coordinates. This is distinct from both the Registry ID and slug.

11 / Debian APT repositories

Consume an atomic repository generation with ordinary APT.

Create a Debian APT registry from Project settings › Packages › Registries and permanently choose Managed indexes or Immutable snapshot import. Copy either the stable /apt/<registry-id>/ URL or the convenient /apt/<registry-slug>/ URL, along with the repository public key.

deb [signed-by=/etc/apt/keyrings/mozaic.asc] https://packages.example/apt/<registry-id>/ stable main
deb-src [signed-by=/etc/apt/keyrings/mozaic.asc] https://packages.example/apt/<registry-id>/ stable main

Registry ID URLs survive registry renames and slug changes. Slug URLs are easier to recognize, but clients must be updated when the slug changes. The registry page displays and provides copy buttons for both variants.

Managed repositories validate each .deb control archive and require every file referenced by a .dsc source package before generating binary/source indexes. Snapshot-import repositories verify a complete bounded, path-safe pre-indexed tree and its supplied signatures. Each publication advances one active generation, so APT cannot observe partially rebuilt indexes.

Private repositories use an expiring show-once token as the HTTP Basic password. Release metadata includes SHA-256 hashes and Valid-Until. Unmapped upstream coordinates never fall through to a public archive.

02 / Feed setup

Create a private project feed.

Organization›Projects›project›Project settings›Packages›Feeds
  1. Choose New feed.Use a name people will recognize in the project package picker.
  2. Set the slug.Use lowercase letters, digits, and internal hyphens. The slug provides a convenient, readable client URL; the generated Registry ID provides the stable URL.
  3. Understand the fixed defaults.The current creation form always makes the feed private and permits explicitly addressed restores of unlisted versions; those values are shown in the feed inventory rather than chosen in this form.
  4. Create the feed.Return to the feed inventory and copy the generated service-index URL.

Success state

The feed appears under Packages and exposes two NuGet v3 service-index URLs: the stable https://<tenant-host>/nuget/<registry-id>/v3/index.json and the convenient https://<tenant-host>/nuget/<registry-slug>/v3/index.json. The page displays the Registry ID and slug and offers a copy button for each URL.

Choose the Registry ID URL for automation that must survive renames. Choose the slug URL for readable local configuration, and update clients whenever the registry slug changes.

Registry addresses use your organization's tenant host, such as acme.mozaic.space. Copy the address from that organization's registry page. OCI login, image references, and protected deployment evidence must use the same tenant authority.

Feed names contain 1-120 characters. Slugs are at most 63 ASCII characters and contain lowercase letters, digits, and hyphens, with no leading or trailing hyphen.

03 / Credentials

Issue one show-once token per client.

Project settings›Packages›Credentials

Credential creation requires Manage packages and the current organization action policy, with fresh MFA required by default. The raw value begins with mznuget_, is displayed once, and cannot be recovered later.

New package credentials default to human use; the creation form also offers explicit machine purpose to authorized administrators. Sign in to the organization first: the token is bound to that organization and its issuing session. Logout or session rotation requires a replacement token. Restore, download and publish requests enforce the current action policy, including fresh MFA and provider revalidation when required. The token expiry does not extend the session.

For unattended automation, select machine purpose at issuance (or explicitly request purpose: "machine" through the API). This additionally requires organization administration and the existing package permissions. Machine credentials retain package scopes, expiry, revocation and current owner access checks; individual actions can disallow them. A client name or non-browser endpoint does not confer automation access. Older personal credentials without session evidence can satisfy only actions that require no MFA in organizations accepting personal accounts.

read
Read a private feed, search packages, and restore package bytes.
push
Publish primary .nupkg files whose normalized IDs match the token pattern.
push_symbols
Publish .snupkg or symbols-package bytes for matching package IDs.
lifecycle
Unlist through NuGet delete and perform permitted package lifecycle operations.
  1. Name the client.Use a name such as Ada workstation or release automation; names contain 1-120 characters.
  2. Constrain package IDs.Enter one exact ID, a prefix with one trailing wildcard such as Contoso.*, or * only when the client truly needs the whole feed.
  3. Select scopes.At least one is required. Restore-only clients normally need only read; a release client commonly needs push and push symbols.
  4. Set expiry.Enter 1-8,760 hours (up to 365 days) in the current creation form.
  5. Copy and store the token.Put a human token in the intended user credential store, or an explicitly authorized machine token in the CI secret store, then close the show-once view.
Authorization remains live

A token authenticates its owner and scopes. Revocation, expiry, feed ownership, and the user's current organization authorization are still enforced; issuing a token does not preserve removed access.

Provision a private OCI deployment registry through the API

A tenant PAT issued with fresh MFA can select Provision packages independently. This permits OCI registry creation at POST /api/v1/organizations/{organization_id}/projects/{project_id}/package-registries, bounded repository listing and creation at /api/v1/organizations/{organization_id}/package-registries/{registry_id}/repositories, and pull credential issuance at POST /api/v1/organizations/{organization_id}/package-registries/{registry_id}/credentials. Send a stable idempotency key for every POST and use the exact tenant host.

For repeated publication under a fixed candidate alias, use mutable tags and deploy only the immutable accepted publication digest. Supply the OCI repository UUID in each credential scope with can_pull: true. PAT credential requests cannot use registry-wide scopes, push, delete, registry management or another package adapter. The issued pull credential expires no later than its provisioning PAT and belongs to the same user. Save the show-once secret through the private deployment credential channel. Provisioning PAT revocation does not revoke issued pull credentials; revoke those separately when needed. Current project package authority, protected command replay and audit remain required.

04 / Client configuration

Connect the dotnet CLI.

Use the exact service-index URL from the feed page. NuGet accepts a non-secret username; Mozaic authenticates the password value.

Terminalprivate feed
dotnet nuget add source "https://<app-host>/nuget/<feed-id>/v3/index.json" \
  --name mozaic \
  --username token \
  --password "<show-once-mznuget-token>" \
  --store-password-in-clear-text

dotnet nuget list source

The clear-text flag is needed on clients without a supported encrypted NuGet credential store. It writes the token to the user's NuGet configuration, so protect that file with operating-system permissions and never add it to the repository. Prefer an environment-provided temporary NuGet configuration in automation.

Terminalpublic feed
dotnet nuget add source "https://<app-host>/nuget/<feed-id>/v3/index.json" \
  --name mozaic-public

Success state

dotnet nuget list source shows the new source as enabled, and requesting the service index returns NuGet resources rather than an authentication error.

05 / Search and restore

Use the feed without changing project-wide sources.

Terminaluse the exact service-index URL
dotnet package search Contoso.Widget --source "https://<app-host>/nuget/<feed-id>/v3/index.json" --exact-match

dotnet add src/MyApp/MyApp.csproj package Contoso.Widget \
  --version 1.2.3 \
  --source "https://<app-host>/nuget/<feed-id>/v3/index.json"

dotnet restore MySolution.slnx --source "https://<app-host>/nuget/<feed-id>/v3/index.json"

Search and version discovery return listed, explicitly published, non-quarantined versions. If the feed allows unlisted restore, a client requesting an exact unlisted version can still restore it; broad search and version enumeration will not rediscover it.

For repeatable builds, commit package references and a lock file, but not credentials. Keep the source URL in NuGet.config only if it is safe for every repository reader to know; put authentication in a user or build-time configuration.

06 / Direct publication

Push packages and symbols deliberately.

Project›Packages›feed
Terminalrelease client with matching scopes
dotnet pack src/Contoso.Widget/Contoso.Widget.csproj \
  --configuration Release \
  --output ./artifacts/packages \
  -p:IncludeSymbols=true \
  -p:SymbolPackageFormat=snupkg

dotnet nuget push "./artifacts/packages/Contoso.Widget.1.2.3.nupkg" \
  --source "https://<app-host>/nuget/<feed-id>/v3/index.json" \
  --api-key "<push-token>" \
  --symbol-api-key "<push-token>"
  1. Inspect the package locally.Confirm ID, version, dependency ranges, license metadata, and intended files before uploading immutable release coordinates.
  2. Use a matching token.The normalized package ID must match its exact or trailing-wildcard pattern. Primary and symbol uploads require their corresponding scopes.
  3. Push the primary package.Mozaic validates the NuGet archive, computes hashes and signature evidence, and records publisher provenance.
  4. Confirm the retained version.Use Artifacts to inspect the exact package hash, listed state, deprecation, and public availability. Inspect signature and publication evidence in the applicable native or producing-run records rather than relying only on a successful CLI exit.

Success state

The version is explicitly published, not quarantined, listed, and visible in package search. A matching client can restore the same bytes by exact ID and version.

07 / Pipeline publication

Publish exact build artifacts with provenance.

A pipeline artifact declaration retains files but does not publish them. Add a terminal publish_in_package_registry step to the job that produced the packages. Identify exactly one registry by ID or slug and use an adapter-tagged source declaration.

.mozaic/pipeline.ymlfragment
      - name: Publish packages
        publish_in_package_registry:
          registry:
            slug: releases
          source:
            adapter: nuget
            paths:
              - artifacts/packages/*.nupkg
              - artifacts/packages/*.snupkg
            allow_untrusted: false

Create the target NuGet feed in the same project first. Its slug is resolved when scheduling, even for a run that will skip publication. This native publication step uses short-lived runner-bound credentials, so it requires no feed token in your repository, shell script, or job environment.

With allow_untrusted: false, manual, push, and pull-request runs build and retain declared artifacts but skip NuGet publication with a warning. An accepted tag or trusted_branch event can publish after successful execution. A manual run of a tag remains restricted. See pipeline triggers and trust for the required actor permissions.

For a tag release, commit the intended package version, push that revision, then create and push the tag. The YAML has no tag-name filter or injected tag-version variable. Use a new version for each new release: NuGet coordinates cannot be replaced with different bytes. Primary packages are published before their matching symbol packages.

The publication record links the native coordinate and exact files, digests, and sizes to the run, attempt, repository revision, plan hash, runner lease, and trust class. NuGet's older publish_in_feed spelling remains a compatibility alias for the same resolved contract.

Use the pipeline result as evidence

Open Project › Pipelines › run › Published packages and verify each entry. One failed publication does not become successful merely because the job produced an artifact.

Move a complete native identity

NuGet and OCI identity pages offer Review complete identity transfer in the existing project-settings workflow. Select the exact identity from the current source inventory, then review and acknowledge destination access before confirming with fresh MFA. All retained versions move together; registry namespaces and UUID client endpoints stay unchanged. NPM, Maven and Debian transfers remain unsupported. Registry administration uses its returned current project, and an OCI identity can have a separate current project within the same registry namespace.

Historical publication receipts keep their original run and native identity. A current-catalog action appears only when the server independently authorizes an exact current destination; absence removes the action while preserving the receipt. Review transfer blockers and receipt recovery.

08 / Lifecycle

Prefer reversible release controls.

Project›Packages›package›version
Deprecate
Add a reason and message while leaving the version restorable.
Unlist
Remove the version from search and version discovery. Exact restore remains possible only when the feed explicitly allows unlisted restore.
Relist
Return a previously unlisted, available version to normal discovery.
Purge
Permanently remove package and symbol bytes while retaining a tombstone so the coordinate and audit history are not silently reused.

Unlist with the NuGet client

Terminalrequires lifecycle scope
dotnet nuget delete Contoso.Widget 1.2.3 \
  --source "https://<app-host>/nuget/<feed-id>/v3/index.json" \
  --api-key "<lifecycle-token>"

NuGet delete maps to unlisting, not byte deletion. To deprecate, relist, or purge, use the version lifecycle controls in Mozaic. Purge requires fresh authentication, an audit reason, and the exact normalized confirmation package-id@version.

A deprecation reason contains 1-120 characters; its message is limited to 2,048 characters. Purge is not an escape hatch for replacing an incorrectly published version—publish a corrected version whenever possible.

09 / Distribution and upstreams

Make external reads explicit.

Understand public-feed gates and the current UI boundary

An existing feed is anonymously readable only when its visibility is Public, it has been explicitly published, and both its organization and project are publicly available. Setting one child resource to Public never overrides a private parent. The current project feed settings list each feed's visibility and unlisted-restore policy, but do not provide a feed publication editor; new feeds are always private. Treat the inventory as evidence, not as a publication workflow.

Configure an upstream

Project settings›Packages›Upstreams
  1. Add an HTTPS flat-container source.Mozaic accepts public DNS destinations and rejects unsafe loopback, private-network, or credential-bearing URLs.
  2. Constrain the package pattern.Route an exact ID or one trailing-wildcard prefix instead of mirroring every request by default.
  3. Set priority and enabled state.Priority controls selection where more than one mapping applies.
  4. Choose cache-on-error behavior.Serving an already verified cache entry during an upstream error improves availability but can intentionally return older upstream bytes.

Fetched bytes are hashed and cached. If an upstream later returns different bytes for the same package coordinate, Mozaic quarantines the changed result instead of silently replacing trusted cached content.

10 / Maven repositories

Use the repository URL with an ordinary Maven client.

Create a Maven registry from Project settings › Packages › Registries, then choose its stable /maven/<registry-id>/ repository URL or convenient /maven/<registry-slug>/ URL. The Registry ID URL remains valid across renames; the slug URL changes with the registry slug. Issue a scoped credential using a canonical group path such as com/example/; use the credential name as the Maven server username and the show-once token as its password.

<server>
  <id>mozaic</id>
  <username>release-bot</username>
  <password>${env.MOZAIC_MAVEN_TOKEN}</password>
</server>

Configure the matching repository ID in the POM or deployment command. Release paths and timestamped snapshot files are immutable. Maven metadata may advance through retained revisions. POM and metadata XML is bounded and DTDs are rejected; SHA-1 compatibility plus SHA-256 and SHA-512 checksum requests are supported.

Detached .asc files from the Maven GPG Plugin are verified against the repository's configured OpenPGP keys before they are stored. Mozaic records cryptographic validity separately from registry trust and rejects tampered or unknown-signer signatures. When a repository requires signatures, unsigned primary files are not served.

10 / Limits and security

Design releases inside the registry envelope.

BoundaryCurrent behavior
Primary package512 MiB maximum per .nupkg.
Symbol package256 MiB maximum per .snupkg or symbols package.
Multipart overhead1 MiB above the permitted archive size.
Versions per package ID128 versions in one feed.
Collection page size1-100 results.
Token expiry1-8,760 hours in the current creation form (up to 365 days).
Token package pattern128 characters maximum; one exact ID, *, or one safe prefix ending in a single wildcard.
Feed identityName 1-120 characters; slug at most 63 lowercase ASCII letters, digits, or internal hyphens.
  • Never put a feed token in source, command output, pipeline logs, package metadata, or a committed NuGet.config.
  • Give restore, publication, and lifecycle automation separate tokens so compromise or rotation has a narrow effect.
  • Use exact or team-prefix package patterns; reserve * for deliberately feed-wide clients.
  • Inspect SHA-256, NuGet SHA-512, signature evidence, provenance, and quarantine state when validating a release.
11 / Troubleshooting

Resolve common package failures.

The service index returns unauthorized or not found

Copy the URL from the feed page and confirm it contains the feed ID. For a private feed, use an unexpired, unrevoked token with read scope and a package pattern that matches the request. Anonymous access additionally requires all organization, project, feed-visibility, and explicit-publication gates.

Push is forbidden although restore works

Read does not imply push. Check the token's push scope, package-ID pattern, expiry, feed binding, and current owner authorization. Symbols need the separate push-symbols scope.

The package was pushed but search cannot find it

Open the version page. It must be explicitly published, listed, and not quarantined. An unlisted version is intentionally absent from search; a changed upstream digest is quarantined rather than trusted.

An exact restore of an unlisted version fails

Exact restore is available only when Allow exact restore of unlisted versions is enabled for that feed. A purged or quarantined version cannot be restored under that setting.

The version already exists

NuGet coordinates are immutable. Compare the published hash and metadata, then increment the package version and publish again. Do not purge merely to replace bytes at the same coordinate.

A pipeline artifact exists but the package does not

Artifact retention and registry publication are distinct. Add a terminal publish_in_package_registry step, identify exactly one registry, keep the paths within the selected adapter's rules, and inspect each Published packages result.