Skip to content

Format-agnostic repositories and routing (groundwork for new formats) #38

Description

@schmitch

Groundwork so that new formats (Docker, npm, raw, Helm) can be added without touching the NuGet code paths.

Where things stand

Some pieces are already format-neutral:

  • repository.format exists and defaults to 'nuget'.
  • component and asset are generic, Nexus-like tables.
  • forge_core::format::Format is an object-safe trait behind a registry (crates/server/src/state.rs).

The rest assumes NuGet:

  • POST /admin/repositories refuses any format other than nuget (crates/server/src/admin/repositories.rs).
  • The format registry only knows nuget, and unknown values fall back to it.
  • All feed traffic goes through /v3/{repo} (crates/server/src/app.rs, dispatch.rs).
  • ParsedUpload is NuGet-shaped: nuspec_bytes, and dependency groups per target framework.
  • Format::parse_upload assumes one uploaded archive per version. That doesn't fit Docker (manifests plus blobs) or raw files (arbitrary paths, no manifest).

Scope

  • A per-format route mount. Each format registers its own router under a prefix:
    • NuGet stays at /v3/{repo}.
    • Proposed: /npm/{repo}/…, /raw/{repo}/…, /helm/{repo}/…, and /v2/… for Docker (Docker clients require the host root).
    • Dispatch resolves the repository, checks that its format matches the mount, and hands over to the format's hosted/proxy/group implementation.
  • Per-format repository config. Validate and type the format-specific keys in repository.config. Unknown keys are refused, consistent with Admin API: retention, repository and realm bodies silently ignore misspelled fields #12.
  • Per-format limits. An upload limit per format, e.g. Docker layers can be far above server.max_upload_bytes. These have to interact correctly with the staging budget.
  • Group rules. Members must share the group's format. The member priority and failing-member handling move into shared code.
  • RBAC content selectors.
    • Selectors are package-id based today.
    • Raw needs path-based selectors (path =~ "^chromium/"), and Docker needs image-name selectors.
  • Retention. Policies are per format (by version, by tag, by path age).
  • Browse UI and API. A format column and filter, a per-format detail view, and per-format client snippets.
  • Shared proxy plumbing. Upstream client, SSRF guard, encrypted credentials, negative cache and publication delay become reusable by every format.

Acceptance criteria

  • A second format can be registered and mounted without changes to the NuGet routes or NuGet tests. Raw (Raw (generic file) repositories: hosted, proxy and group, Nexus-style #42) is a good first consumer.
  • The admin API accepts the registered formats and refuses unknown ones (it no longer falls back to NuGet).
  • A group cannot get a member of another format.
  • Existing NuGet behaviour, tests and e2e are unchanged.

Activity

  1. modified the milestones: 1.2.0, 1.1.0 on Oct 21, 2026
  2. added a commit that references this issue on Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions