Skip to content

[Feature]: add least-privilege GET /v1/catalog for remote Codex clients #809

Description

@nbsp1221

Area

Authentication / catalog distribution / remote clients

Goal

Allow a remote Codex client to download OpenCodex's generated Codex model catalog using the same least-privilege credential class it already uses for inference.

The client must not need the management credential merely to obtain model metadata.

This is primarily needed for centrally hosted and multi-machine deployments such as #95.

Current state

OpenCodex already exposes the generated catalog through:

GET /api/catalog

but that endpoint is intentionally part of the management plane.

The management credential can also access sensitive administrative operations such as:

  • provider configuration;
  • OAuth/account management;
  • server settings;
  • management mutations;
  • proxy shutdown.

Giving that credential to every remote inference client violates least privilege.

The accepted implementation direction is therefore not to weaken admission for /api/catalog.

Instead, add a separate read-only data-plane catalog route.

Accepted route

Add:

GET /v1/catalog

with optional:

HEAD /v1/catalog

using the existing data-plane authentication boundary.

A client that can already call:

POST /v1/responses

should be able to fetch:

GET /v1/catalog

using the same data-plane credential.

That credential must continue to receive 401 / denial for management routes.

Security boundary

The /api/* management namespace remains unchanged.

Do not add a special case such as:

data-plane token
    -> allowed through /api/catalog

The desired separation is:

Data plane
  /v1/responses
  /v1/chat/completions
  /v1/messages
  /v1/models
  /v1/catalog

Management plane
  /api/*

A data-plane credential that can read /v1/catalog must still be unable to access, for example:

GET  /api/config
GET  /api/providers
POST /api/oauth/login
POST /api/codex-auth/login
POST /api/stop

or any other management-only route.

Payload contract

GET /v1/catalog should reuse the same authoritative generated catalog payload and sanitization/redaction rules as:

GET /api/catalog

Do not create an independently generated second catalog.

The two routes should expose equivalent catalog content subject only to differences that are intentionally specific to their transport/auth surface.

The data-plane response must not expose:

  • provider API keys;
  • OAuth credentials;
  • management tokens;
  • account identifiers;
  • raw provider configuration;
  • internal filesystem paths;
  • other management-only state.

Method restrictions

The data-plane catalog surface is read-only.

Allowed:

GET
HEAD

Not allowed:

POST
PUT
PATCH
DELETE

No catalog mutation API should be introduced under /v1.

Response behavior

Preserve the useful catalog-distribution metadata already provided by the management route where applicable, including:

  • bounded response size;
  • content type;
  • cache-related headers;
  • version/skew metadata;
  • deterministic errors when the catalog cannot be materialized.

If the existing management route exposes a Codex-version header, preserve that contract where the corresponding information is available.

Do not fabricate a version when the proxy has no authoritative runtime version.

Remote-client workflow

A centrally hosted OpenCodex deployment should support:

curl -fsS \
  -H "x-opencodex-api-key: $DATA_PLANE_KEY" \
  https://proxy.example.com/v1/catalog \
  > "${CODEX_HOME:-$HOME/.codex}/opencodex-catalog.json"

The same credential can then be used for inference:

curl -fsS \
  -H "x-opencodex-api-key: $DATA_PLANE_KEY" \
  https://proxy.example.com/v1/responses \
  ...

while the management credential remains only on the operator's trusted machine.

Admission tests

Regression coverage must prove both halves of the boundary.

Positive

A valid data-plane credential can:

GET  /v1/catalog
HEAD /v1/catalog

and receives the expected generated catalog metadata.

Negative

The same credential cannot access:

/api/*

including representative reads and mutations.

Also verify that:

  • missing credentials fail when data-plane auth is required;
  • invalid credentials fail;
  • management-only credentials do not accidentally redefine the data-plane contract unless already intentionally accepted there;
  • unsupported methods against /v1/catalog are rejected.

Catalog parity

Tests should establish that the data-plane route and management route consume the same catalog authority.

A change to catalog generation should not require maintaining two independent serialization implementations.

Relevant properties include:

  • model entries;
  • reasoning metadata;
  • context metadata;
  • routed aliases;
  • ownership fields;
  • sanitization;
  • response bounds.

Documentation

Update the credential/surface documentation so the boundary is explicit.

The credential table should reflect conceptually:

Credential class Allowed surface
Data plane inference endpoints plus read-only /v1/models and /v1/catalog
Management plane /api/*
GUI session management API only, subject to GUI-session restrictions

Also document the multi-machine catalog-download workflow.

Relationship to #709

#709 implemented the generated catalog read on the management surface.

This issue does not replace or remove:

GET /api/catalog

The management route remains useful for the Dashboard/operator surface.

This issue adds the least-privilege remote-client projection of that same catalog.

Relationship to #95

#95 tracks the broader centrally hosted / multi-user OpenCodex deployment.

This issue addresses one concrete blocker from that deployment model:

remote clients need the Codex catalog
without receiving management privileges

It does not attempt to solve the rest of #95.

Out of scope

This issue does not require:

  • exposing models_cache.json;
  • moving the management API under /v1;
  • granting data-plane credentials general /api/* access;
  • remote provider configuration;
  • remote OAuth management;
  • distributing management credentials to client machines;
  • introducing a second catalog-generation implementation.

Acceptance criteria

  • GET /api/catalog exists on the management plane.
  • Maintainer-approved architecture uses a separate data-plane route rather than weakening /api/* authentication.
  • GET /v1/catalog exists.
  • HEAD /v1/catalog is supported if consistent with the existing read surface.
  • Existing data-plane credentials can read the route.
  • Catalog content comes from the same authoritative generator/payload contract as /api/catalog.
  • No credentials, provider configuration, or management-only state are exposed.
  • Non-read methods are rejected.
  • A data-plane credential still cannot access any /api/* route.
  • Positive and negative admission tests cover the credential boundary.
  • Response size/cache/version behavior remains bounded and documented.
  • Credential/surface documentation is updated.
  • Remote/multi-machine catalog-download workflow is documented.
  • Accepted implementation is merged into dev.

Related

Activity

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

    account-poolOAuth, credentials, Codex pool, quota, failover, planscatalogModel catalog, slugs, visibility, routed entriesenhancementNew feature or requestmaintainer-sponsoredMaintainer sponsors this change to an auth, workflow, release, or dependency surfaceproxyHTTP proxy, routing, reverse-proxy / management auth

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions