Skip to content

[Bug][2.36.0] /api/models drops entitled GPT-5.6 rows after the 5-minute entitlement cache expires #3023

Description

@kaicot

Client or integration

OpenCodex dashboard

Area

Catalog / models

Summary

On OpenCodex 2.36.0, the dashboard/management model list loses the entitled native OpenAI GPT-5.6 rows when the five-minute account-model roster cache expires.

Immediately after a successful entitlement discovery, GET /api/models contains seven native openai rows:

  • gpt-5.5
  • gpt-5.4
  • gpt-5.4-mini
  • gpt-5.3-codex-spark
  • gpt-5.6-sol
  • gpt-5.6-terra
  • gpt-5.6-luna

After five minutes, with no account or configuration change, the same endpoint returns only the first four. Calling GET /v1/models immediately restores all seven rows in /api/models for another five minutes.

The account is entitled to the three GPT-5.6 models: /v1/models returns them, the generated Codex catalog contains them with visibility: "list", and they remain usable. This appears to be a management/catalog projection bug rather than a loss of model access.

Expected: management readers should trigger or receive a current entitlement discovery before projecting account-gated native rows. The dashboard and exports should not silently change from 7 to 4 solely because the in-memory evidence cache expired.

Reproduction

  1. Start OpenCodex 2.36.0 with an authenticated ChatGPT/Codex account entitled to gpt-5.6-sol, gpt-5.6-terra, and gpt-5.6-luna.

  2. Set ADMIN_TOKEN to a valid local management API token. Do not print it.

  3. Warm entitlement discovery once:

    curl -s -H "Authorization: Bearer $ADMIN_TOKEN" \
      http://127.0.0.1:10100/v1/models > /dev/null
  4. Count the native OpenAI rows returned by the management endpoint every 30 seconds:

    curl -s -H "Authorization: Bearer $ADMIN_TOKEN" \
      http://127.0.0.1:10100/api/models \
      | grep -o '"provider":"openai"' | wc -l
  5. Observed timeline:

    02:48:32  openai_rows=7
    02:49:03  openai_rows=7
    02:49:33  openai_rows=7
    02:50:03  openai_rows=7
    02:50:33  openai_rows=4  # roster cache expired
    
    02:50:50  GET /v1/models
    02:51:04  openai_rows=7  # restored immediately
    02:51:34  openai_rows=7
    ...
    02:55:38  openai_rows=7
    
  6. A separate cold/warm check produced the same result:

    BEFORE /v1/models
    count=4
    gpt-5.3-codex-spark,gpt-5.4,gpt-5.4-mini,gpt-5.5
    
    GET /v1/models returned
    gpt-5.6-luna,gpt-5.6-sol,gpt-5.6-terra
    
    AFTER /v1/models
    count=7
    gpt-5.3-codex-spark,gpt-5.4,gpt-5.4-mini,gpt-5.5,gpt-5.6-luna,gpt-5.6-sol,gpt-5.6-terra
    

Suspected root cause

  • src/codex/catalog/native-models.ts: Sol/Terra/Luna are members of ACCOUNT_GATED_NATIVE_OPENAI_MODELS.
  • src/codex/catalog/metadata.ts: nativeModelRows() filters gated slugs through cachedAvailableAccountGatedNativeModels().
  • src/codex/model-entitlements.ts: the roster evidence is stored in the process-local accountModelsCache; MODEL_ROSTER_TTL_MS = 5 * 60_000. The cache projection requires entry.expiresAt > now.
  • src/server/management/model-routes.ts: GET /api/models calls only listManagementModelRows(config).
  • src/server/management/model-rows.ts: listManagementModelRows() calls fetchAllModels(config) and then nativeModelRows(config), but it does not call resolveCodexModelEntitlements(config) first.
  • In contrast, src/server/index.ts runs resolveCodexModelEntitlements(config, ...) on the GET /v1/models path. The resolver reuses a live cache entry and performs a new upstream roster fetch on a cache miss/expiry.

This also affects /api/client-config because loadExportModels() delegates to listManagementModelRows(). The live-service path used by ocx export reads /api/models, so an export performed while the cache is cold can silently omit the three GPT-5.6 entries.

A narrow fix may be to refresh entitlement evidence in the shared listManagementModelRows() path (or pass an explicit entitlement snapshot into the native-row projection) so /api/models, /api/client-config, and CLI exports stay aligned. The existing five-minute resolver cache would still prevent a remote request on every dashboard refresh.

Relationship to existing issues

Version

2.36.0

Operating system

Microsoft Windows 11 Pro, version 10.0.26200, build 26200, x64

Provider and model

Canonical openai provider using ChatGPT/Codex account authentication:

  • gpt-5.6-sol
  • gpt-5.6-terra
  • gpt-5.6-luna

Logs or error output

GET /api/models while entitlement cache is cold: openai_rows=4
GET /v1/models: GPT-5.6 Sol/Terra/Luna returned
GET /api/models immediately afterwards: openai_rows=7

Screenshots and supporting files

The complete redacted timeline and source trace are included above. No local patch has been installed.

Redacted configuration

{
  "providers": {
    "openai": {
      "adapter": "openai-responses",
      "authMode": "forward"
    }
  }
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

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

    bugSomething isn't workingcatalogModel catalog, slugs, visibility, routed entriesproxyHTTP proxy, routing, reverse-proxy / management auth

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions