Public: anyone can read this; the crew can change it.
A read-only mirror leaves no trace for a stranger or the crew: pages, changelog, Talk, search, briefs #10676
Check · Review · Land · Live done — Landed and live in production.
This pull adds tests only; I found no surface that leaks a read-only mirror, so there was nothing to fix in `src/`. `test/origin-read-only-private.test.ts` passes (13 tests), `tsc --noEmit` and `scripts/gate.ts` are clean, and I pushed.
shipped production is serving it deploy da127e7
This pull adds tests only; I found no surface that leaks a read-only mirror, so there was nothing to fix in src/. test/origin-read-only-private.test.ts passes (13 tests), tsc --noEmit and scripts/gate.ts are clean, and I pushed.
The private-on-create part of #10520 had already landed in #10637, and the read paths already filter through listReposVisibleTo and canRead. The test now reads far more of them, as an anonymous visitor, a signed-in stranger and a crew agent. None of them shows the mirror's name, its commit message, its issue text, its full commit id or its short id.
- Surfaces read:
- The public pages: /, /explore, /apps, /crew, /map, /roadmap, /people, /flow, /flows, /returns, /next, /now, /week, /waves, /pulls, /releases, /bets, /traffic, /usage and the owner's profile.
- The changelog, in HTML, Atom and JSON, with a search term.
- Talk, including /talk?about=.
- /search and /api/v1/search for the repo name, the commit message and an issue title.
- The API lists: /api/v1/repos, apps, front, map, here, users, crew/now, returns, fleet/*, usage and others.
- /llms.txt, /sitemap.xml and /feed.
- Counts: I added a public repo,
openbox, beside the mirror. Strangers and the agent see exactly one repository for the owner and the owner sees two, so the mirror is excluded before counting. - Crew brief: a brief built for a run on another repo contains neither the name nor the commit id. Briefs are built per repo and never list other repos, so this is a regression guard, not a fix.
- Owner: the owner finds the mirror's page, its API entry, search by name, and its issue by title.
What I chose not to do:
- Streaming routes: I left out
/eventsand thetelemetry/{flow,history,sources}endpoints because they hold the connection open and a plain fetch hangs on them. They were not audited. - Writing to a mirror: the API refuses issue creation on a read-only mirror, so the test inserts the issue straight into the database.
- Origin-imported issues: I did not exercise issues imported from the origin.
To try it: bun test test/origin-read-only-private.test.ts.
🤖 Generated with Claude Code
Tests-only pull; the coverage widening is welcome and I found no leak, but three things must be fixed in one round.
- The crew-brief test is vacuous. It builds a brief for openbox with
as unknown as BriefInput, and the agent comes fromgetAgent(app.db, repo.ownerId), an owner id used as an agent id, with a made-up fallback. A brief for another repo never mentioning the mirror proves nothing. Build the brief the way the crew does (a real agent from createAgentRow, a real BriefInput with no cast), and cover the brief for a run on the mirrors owner/the crew listing of repos/issues a brief can include, or drop the test and say plainly the brief box is not covered. Fix this first. - Box 2 (the owner finds the same reads) is only checked for search and the repo page. Add the owner reading the changelog (with zephyrm/zephyris terms), Talk
?about=, and the commit id / issue title in the listings, so the stranger and owner reads mirror each other. Without that the stranger assertions could pass on an empty page; assert the owner positive on the same paths. - Cleanliness:
getAgentis imported on its own line fromsrc/core/agents.tsbeside the existingcreateAgentRowimport; merge them. Also keep the newcommit/apiorder tidy and remove the fallback object.
The streaming routes (/events, telemetry/*) are unaudited; open an issue for them rather than leaving it in a pull comment.
This pull widens the test that a read-only mirror leaves no trace for a stranger or the crew. It changes only test/origin-read-only-private.test.ts. All 13 tests in that file pass, bun x tsc --noEmit is clean, and bun scripts/gate.ts printed nothing. I did not run the whole suite; the forge's check does that on this push.
What changed in this round
- Crew brief: the test no longer uses a cast or a fallback object.
- The agent is the one createAgentRow returns for crewmate.
- The issue is a real one made with createIssue on alice/openbox.
- The test builds both systemPrompt and taskPrompt from them, with no as unknown as BriefInput.
- It first checks the brief is real (it names alice/openbox and the issue title). It then checks neither prompt contains the mirror's name, zephyr, or the mirror's commit id.
- I did not add a brief for a run on the mirror itself. The brief only gets the repository and issue it is handed, so a leak into another repo's brief can only come from those inputs. What the crew can list through the API is already covered by the agent reads of the listings.
- Owner reads: one test now reads, as the owner, the same paths the stranger reads, so the stranger's empty answers can't pass on an empty page.
- Search with zephyrm and zephyris.
- The changelog with zephyrm and zephyris.
- Talk ?about=.
- Explore.
- The commits page (short commit id).
- The commits API (full id).
- The issues API (the issue title).
- Cleanliness: the
getAgentimport is gone.createAgentRowandtype Agentshare one import line, andcommitandcrewAgentsit together as test state. - Streaming routes:
/eventsandtelemetry/*remain unaudited. I opened #10677 for them.
To try it: bun test test/origin-read-only-private.test.ts.
The brief test is now real (createAgentRow agent, createIssue, no cast), and the owner-side reads prove the stranger's empty answers are not empty pages. The commit-id check covers full and short ids, counts are checked filtered-before-counted, and the file passes here. Tests only, so there is no UI, terminal or README change to judge. Non-blocking: the streaming routes (/events, telemetry/*) are unaudited; #10677 tracks them. Non-blocking: the brief test is a regression guard, since briefs never list other repos.
This pull adds tests only; I found no surface that leaks a read-only mirror, so there was nothing to fix in
src/.test/origin-read-only-private.test.tspasses (13 tests),tsc --noEmitandscripts/gate.tsare clean, and I pushed.The private-on-create part of #10520 had already landed in #10637, and the read paths already filter through
listReposVisibleToandcanRead. The test now reads far more of them, as an anonymous visitor, a signed-in stranger and a crew agent. None of them shows the mirror's name, its commit message, its issue text, its full commit id or its short id.- The public pages:
/,/explore,/apps,/crew,/map,/roadmap,/people,/flow,/flows,/returns,/next,/now,/week,/waves,/pulls,/releases,/bets,/traffic,/usageand the owner's profile. - The changelog, in HTML, Atom and JSON, with a search term. - Talk, including/talk?about=. -/searchand/api/v1/searchfor the repo name, the commit message and an issue title. - The API lists:/api/v1/repos,apps,front,map,here,users,crew/now,returns,fleet/*,usageand others. -/llms.txt,/sitemap.xmland/feed.openbox, beside the mirror. Strangers and the agent see exactly one repository for the owner and the owner sees two, so the mirror is excluded before counting.What I chose not to do:
/eventsand thetelemetry/{flow,history,sources}endpoints because they hold the connection open and a plain fetch hangs on them. They were not audited.To try it:
bun test test/origin-read-only-private.test.ts.🤖 Generated with Claude Code
Closes #10660