fix(registry): the public catalog defaults to verified-only - #953
Open
lilyshen0722 wants to merge 2 commits into
Open
fix(registry): the public catalog defaults to verified-only#953lilyshen0722 wants to merge 2 commits into
lilyshen0722 wants to merge 2 commits into
Conversation
fable-lead's "do now regardless of ratification" item, and a live leak. Measured 2026-08-14: GET /api/registry/agents returned 66 rows, 52 unverified — and among those were every internal and smoke-test agent we have ever created: smoke-claude, demo-claude, demo-claude2, demo-target, demo-clean2, the smokea50698-* family, smoke-stub, test-agent, test-agent2, plus our own working seats pod-architect, cl-critic, cl-strategist, claude-on-dev, sam-claude, sam-local-codex, nova-claude, hq-support and carol. `search()` already excluded ephemeral rows, so that was never the leak — the internal rows are ordinary registry documents from our own dev work. The landing-page footer links this endpoint, so a logged-out visitor could browse the lot, and it is where the 2026-08-14 casualty picked the `claude-code` template that produced their dead seat. `verified` is exactly the axis that separates them: every leaked row is commonly-community + unverified, while the curated set is verified. So the default flips to verified-only. Nothing becomes unreachable — an explicit ?verified=false still works. Only the default stops being "show everything we ever wrote." A garbage value resolves to the RESTRICTIVE side, which is the property worth testing: the old code treated unparseable as "no filter", i.e. show all. Stopgap, not the answer: ADR-022 (#950) replaces this surface with a persona catalog, at which point the curated set is the catalog by construction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XeUH4HVDsDHYPsHJthXjB8
… filter Replaces this branch's first attempt, which CI correctly rejected. **Why the filter was wrong.** Defaulting the catalog to verified-only broke `self-serve-install.test.js` — `public-marketplace-bot` is a legitimately published third-party agent and is also unverified. The filter would have hidden real publishers in order to hide our fixtures. `verified` is a TRUST signal, not a visibility one, and the junk is not distinguishable by schema — it is distinguishable by being OURS. **The right lever already exists.** `ephemeral` means exactly "private to its owner; getByName still resolves it, marketplace browse does not" (AgentRegistry.search:167 filters it; ADR-006 self-serve rows use it for the same reason). Our test seats fit that definition, so this is a data correction, not a new concept — and no code change at all. Names are enumerated, never pattern-matched. A regex over agent names would eventually swallow a real user's agent called "demo-something", and the blast radius of a wrong guess is a publisher silently delisted. **The dry run found the list is INCOMPLETE, and that is the finding.** All 21 named rows exist and are unmarked — but the catalog would still hold ~28 more internal rows afterwards: fc-verify, target, filebot, laptop-codex, cloud-codex, duo, pixel-stub, lily-live, solo, diana, codex-impl, bob, alice, clark, xu-claude-code-local, xu-codex-local, fable-lead, asker, reader, codex-bot, echobot, aria, dex, ux-lead, sprint-impl, sprint-review, local-claude — plus a row with an EMPTY agentName, which is data corruption worth its own look. Deliberately NOT applied. Sorting genuine catalog entries (pod-welcomer, task-clerk, scout, claude-code, openclaw, webhook, newshound, …) from internal seats across those 28 is a judgement call that delists a real publisher if wrong, and the script's own contract is to leave unrecognised rows alone and report them. Next session: extend the list, dry-run, then --apply. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XeUH4HVDsDHYPsHJthXjB8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fable-lead's "do now regardless of ratification" item, and a live leak.
What was exposed
GET /api/registry/agentsreturned 66 rows, 52 unverified — and among those, every internal and smoke-test agent we have ever created:search()already excluded ephemeral rows, so that was never the leak — these are ordinary registry documents from our own dev work.The landing-page footer links this endpoint, so a logged-out visitor could browse the lot. It's also where the 2026-08-14 casualty picked the
claude-codetemplate that produced their dead seat.The fix
verifiedis exactly the axis that separates them — every leaked row iscommonly-community+ unverified, while the curated set is verified. So the default flips to verified-only.Nothing becomes unreachable. An explicit
?verified=falsestill works; only the default stops being "show everything we ever wrote."The property worth testing
A garbage value resolves to the restrictive side. The old code treated unparseable as "no filter," i.e. show all — which is the wrong direction for a default on a public surface.
Scope
Stopgap, not the answer. ADR-022 (#950) replaces this surface with a persona catalog, at which point the curated set is the catalog by construction.
🤖 Generated with Claude Code
https://claude.ai/code/session_01XeUH4HVDsDHYPsHJthXjB8