Skip to content

fix(registry): show public agents when the session cookie is stale - #7825

Merged
bokelley merged 1 commit into
mainfrom
w-550/adcp-registry-empty-bug
Oct 1, 2026
Merged

bokelley merged 1 commit into
mainfrom
w-550/adcp-registry-empty-bug

Conversation

@bokelley

@bokelley bokelley commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Reported in Slack: https://adcontextprotocol.org/registry/ showed an empty Agents list for a signed-in user (repro: open the site in two tabs, log in on one, refresh the other).

Since #7462, optionalAuth returns 401 when a wos-session cookie is present but unusable, instead of treating the caller as anonymous. /api/registry/agents sits behind optAuth. The Agents page then did data.agents || data, .map() threw on the error object, the catch swallowed it, and the page rendered zero agents. Meanwhile the HTML render path (getUserFromRequest) quietly treats the same cookie as logged out, and the AdCP session bridge skips because a cookie is present, so the page never recovers.

Verified against production:

GET /api/registry/agents                               → 200 (34 agents)
GET /api/registry/agents  Cookie: wos-session=<bad>    → 401 {"error":"Invalid session"}

Changes

  • server/public/agents.html: a new fetchRegistryAgents() helper used by all three list fetches. On a 401 it retries once with credentials: 'omit'. A request with no cookie at all is still anonymous under fix(auth): hydrate primary authorization snapshots per request #7462's policy, so this keeps it intact. Any other failure now shows an error message instead of an empty grid.
  • server/tests/unit/public-agent-registry-ui.test.ts: behavioral tests that run the helper against a mocked fetch: 401 → anonymous retry succeeds; 503 surfaces as an error without a retry.

Brands, Properties, Policies and Members call endpoints that don't use optionalAuth, so they weren't affected.

When the retry kicks in, that load shows only public agents. Members-only agents need a valid session.

Follow-ups (not in this PR)

  • getUserFromRequest refreshes sessions without calling storeRefreshedSession. Other copies of the cookie (the AdCP copy made by the bridge, in-flight requests) then can't recover and turn into dead cookies. That's the likely source of the stale cookie.
  • Clear a definitely-dead cookie so the bridge can pick up a fresh AAO session. This needs care around the Set-Cookie race with concurrent refreshes.
  • Other public pages backed by optionalAuth endpoints (events, committees, perspectives, /api/config) can probably fail the same way.

Test plan

  • npx vitest run tests/unit/public-agent-registry-ui.test.ts (6 passed)
  • Pre-commit unit suites passed
  • Page module script passes node --check

🤖 Generated with Claude Code


Open workspace in Conductor

Since #7462, optionalAuth returns 401 for a present-but-unusable
wos-session cookie instead of treating the caller as anonymous. The
Agents page swallowed that error and rendered an empty registry.

Retry the public list once with credentials omitted on 401, and show an
error instead of an empty grid for any other failure.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Approve

Approve — clean, well-targeted UI fix.

Checked:

  • server/public/agents.html: fetchRegistryAgents now retries a stale-cookie 401 anonymously and fails-closed to an error surface instead of rendering an empty registry. Dropping the data.agents || data fallback is verified dead against the endpoint contract (registry-api.ts:1713 returns { agents: [...], count }).
  • App-only change with no protocol surface touched (no static/schemas/source/**, docs/reference/**, dist/**, or release scripts), so no changeset is required and none is needed.
  • Both branches covered by tests in server/tests/unit/public-agent-registry-ui.test.ts; test plan fully checked.

Gate evaluation:

  • No critical/high findings (row 1 n/a).
  • gated_paths: false, so row 2 does not apply despite review_decision: REVIEW_REQUIRED.
  • high_risk: false; no deleted/modified high-risk paths (rows 3, 5 n/a).
  • No medium findings (rows 4, 8 n/a).
  • No no-auto-approve team match (row 7 n/a).
  • No prior decision (row 6 n/a).

Falls through to row 9 → approve.

@bokelley
bokelley merged commit ba5735a into main Oct 1, 2026
31 checks passed
@bokelley
bokelley deleted the w-550/adcp-registry-empty-bug branch October 1, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant