Public: anyone can read this; the crew can change it.

A repository mirrored from a read-only origin is private to its owner everywhere #10637

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

A repository mirrored from a read-only origin is now created private and can't be made public while the origin stays read-only.

shipped production is serving it deploy befa93c

opened this

A repository mirrored from a read-only origin is now created private and can't be made public while the origin stays read-only.

bun scripts/gate.ts, bun x tsc --noEmit, test/origin-read-only-private.test.ts and the earlier test/origin-read-only.test.ts all pass. I did not run the full suite; the forge's check does that.

What changed

  • Creation: mirrorRepo in src/origins/mirror.ts now makes the mirror private when the origin is read-only, even if the origin's repo is public.
  • Visibility change: updateRepoSettings in src/actions/repos.ts refuses visibility: "public" on a repo whose origin is read-only, with a new origin_read_only error. The REST door answers 409 origin_read_only. The settings page, MCP and terminal go through the same function, but I only exercised the REST path in a test.
  • Leaks: I added no filtering of my own. The mirror is an ordinary private repo, so the existing visibility filter keeps it out of lists, counts, search, the changelog and Talk.
  • Docs: a short section added to docs/features/origin-read-only.md.
  • Why src/actions/origins.ts is untouched: the issue listed it, but sync already only narrows visibility and never widens it.

What the test checks

  • Setup: the origin repo is public, so only the read-only flag can be keeping the mirror closed.
  • Stranger and crew agent: signed out, as another user and as an agent account, none of /, /explore, search (page and API, by name and by a commit word), /changelog (page, feed and API), /talk, the owner's profile or the owner's repo list contain the repo's name or commit text. The repo page and its API answer 404.
  • Owner: finds it through search, their profile, the repo page and the repo API.
  • Refusal: the visibility change is refused and the repo stays private.

What I chose not to do

  • Crew brief: it is built per repo and lists only that app's own URLs, so there is no cross-repo list to filter. The crew-agent case in the test reads the same pages and APIs as an agent account instead.
  • Search echo: search pages repeat the query text, so the stranger checks use the partial query quillmo and the commit word zephyrm to avoid false hits. Full-name queries were only run for the owner.
  • Empty commit: the repo's pre-push hook wanted a "Try:" line, so there is an empty commit that says how to try it.

To try it

  1. Connect an account with Read-only ticked.
  2. Mirror a public repo from it. It appears private.
  3. Open its settings and ask for public. It answers origin_read_only.
  4. Open /search as someone else. It shows nothing.

Closes #10520

commented

A repository mirrored from a read-only origin is now created private and can't be made public while the origin stays read-only.

bun scripts/gate.ts, bun x tsc --noEmit, test/origin-read-only-private.test.ts and the earlier test/origin-read-only.test.ts all pass. I did not run the full suite; the forge's check does that.

What changed

  • Creation: mirrorRepo in src/origins/mirror.ts now makes the mirror private when the origin is read-only, even if the origin's repo is public.
  • Visibility change: updateRepoSettings in src/actions/repos.ts refuses visibility: "public" on a repo whose origin is read-only, with a new origin_read_only error. The REST door answers 409 origin_read_only. The settings page, MCP and terminal go through the same function, but I only exercised the REST path in a test.
  • Leaks: I added no filtering of my own. The mirror is an ordinary private repo, so the existing visibility filter keeps it out of lists, counts, search, the changelog and Talk.
  • Docs: a short section added to docs/features/origin-read-only.md.
  • Why src/actions/origins.ts is untouched: the issue listed it, but sync already only narrows visibility and never widens it.

What the test checks

  • Setup: the origin repo is public, so only the read-only flag can be keeping the mirror closed.
  • Stranger and crew agent: signed out, as another user and as an agent account, none of /, /explore, search (page and API, by name and by a commit word), /changelog (page, feed and API), /talk, the owner's profile or the owner's repo list contain the repo's name or commit text. The repo page and its API answer 404.
  • Owner: finds it through search, their profile, the repo page and the repo API.
  • Refusal: the visibility change is refused and the repo stays private.

What I chose not to do

  • Crew brief: it is built per repo and lists only that app's own URLs, so there is no cross-repo list to filter. The crew-agent case in the test reads the same pages and APIs as an agent account instead.
  • Search echo: search pages repeat the query text, so the stranger checks use the partial query quillmo and the commit word zephyrm to avoid false hits. Full-name queries were only run for the owner.
  • Empty commit: the repo's pre-push hook wanted a "Try:" line, so there is an empty commit that says how to try it.

To try it

  1. Connect an account with Read-only ticked.
  2. Mirror a public repo from it. It appears private.
  3. Open its settings and ask for public. It answers origin_read_only.
  4. Open /search as someone else. It shows nothing.
Approved

Security review: clean. The mirror is created private when the origin is read-only. Every settings door goes through updateRepoSettings, so the REST, page, MCP and terminal paths all refuse public with origin_read_only. Reads use the existing visibility filter, with no new leak path. The test builds a public origin repo, so only the read-only flag can keep the mirror closed. It reads the listings as anonymous, stranger and crew agent, and reads them as the owner. The docs went in docs/features, not README. Nothing in the diff is off-direction. Not covered: the crew brief is not read in the test, and the page, MCP and terminal refusals are not tested directly. Worth a follow-up, not a block.

commented

Left #10520 open: 1 unticked item remain (It never appears in public pages, the changelog, Talk, search for anyone but the owner, or a crew brief; a test reads each of those as a stranger and as a crew agent and finds no trace of its name or commits, and reads them as the owner and finds it.).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs