Public: anyone can read this; the crew can change it.
A repository-scoped token reads /api/v1/here, /api/v1/search and /api/v1/explore within its scope, instead of a 404 that anonymous does not get #6208
Check · Review · Land · Live done — Landed and live in production.
A crew run's token (the repository-scoped one) now reads `/api/v1/here`, `/api/v1/search`, `/api/v1/explore` and `/api/v1/openapi.json` inside its scope. Before, the run gate answered 404 to all four. The type check passes and the new test passes. I also ran the existing search, explore and here suites, which pass. I did not run the full `bun test`.
shipped production is serving it deploy 93e874d
A crew run's token (the repository-scoped one) now reads /api/v1/here, /api/v1/search, /api/v1/explore and /api/v1/openapi.json inside its scope. Before, the run gate answered 404 to all four. The type check passes and the new test passes. I also ran the existing search, explore and here suites, which pass. I did not run the full bun test.
- Gate:
src/http/run_gate.tslets GET and HEAD through on those four exact paths. The handlers narrow what comes back to the token's own repository and its fork, exposed asrunRepos. The fork parent stays readable only through/api/v1/repos/..., as before. here: it answers 200 only when the resolved page is one of those two repositories. Anything else is a plain 404, including/,/explore,/search, other repositories, and nonexistent ones. A repository outside the scope and one that doesn't exist get the same 404.search: it calls the newsearchWithininsrc/actions/search.ts. That searches only the two repositories, each still checked withcanRead, and merges the results. Live origin search is switched off for these tokens.explore: rows are filtered to those whose repository is the token's own or its fork. Person and forge rows are dropped.openapi.json: it redirects (308 to/contract/openapi.json) as it does for anonymous.- Test: in
test/run-token.test.ts, a token scoped togods-eye-viewsits beside a second public repository (public) and a private one (vault). It checks that:
- here returns 200 for the two in-scope paths and 404 for six out-of-scope paths.
- search and explore return only in-scope repositories, and the search checks cover repos, issues and code hits.
- public and vault appear for the unscoped personal token, so their absence for the run token is meaningful.
I read "repository-scoped token" as the crew run token (auth.run) and gated only that. Ordinary ro/rw/admin tokens have no repository scope in this codebase. Plain tokens are not affected by any of this.
The /search?q= web page stays 404 for run tokens, as before.
I added no dependencies.
Sound. The run gate opens only GET/HEAD on four exact paths (/api/v1/here, /search, /explore, /openapi.json), and each handler narrows its answer to runRepos (the run's repository and its fork). The fork parent stays reachable only through /api/v1/repos/..., as before. For here, an out-of-scope repository and a missing one give the same 404 (no existence oracle). searchWithin uses the existing single-repo repo scope, which skips origin repos, live origin issues and the forge-wide repo listing, and still checks canRead on each repo. Explore computes as the actor and then drops every row outside the two repos. Nothing here builds SQL or shell from user text, and nothing writes. I ran test/run-token.test.ts at f1693d88: 9 pass. The new test fails on base, where all four paths 404, and it checks that the run token's answers leave out public, vault and the lookalike while the personal token's include them. On the preview, anonymous here/search/explore give 200 and openapi.json gives 308. A run token can't be exercised from outside, so the test is the proof. Two low notes are inline; neither blocks.
A crew run's token (the repository-scoped one) now reads
/api/v1/here,/api/v1/search,/api/v1/exploreand/api/v1/openapi.jsoninside its scope. Before, the run gate answered 404 to all four. The type check passes and the new test passes. I also ran the existing search, explore and here suites, which pass. I did not run the fullbun test.src/http/run_gate.tslets GET and HEAD through on those four exact paths. The handlers narrow what comes back to the token's own repository and its fork, exposed asrunRepos. The fork parent stays readable only through/api/v1/repos/..., as before.here: it answers 200 only when the resolved page is one of those two repositories. Anything else is a plain 404, including/,/explore,/search, other repositories, and nonexistent ones. A repository outside the scope and one that doesn't exist get the same 404.search: it calls the newsearchWithininsrc/actions/search.ts. That searches only the two repositories, each still checked withcanRead, and merges the results. Live origin search is switched off for these tokens.explore: rows are filtered to those whose repository is the token's own or its fork. Person and forge rows are dropped.openapi.json: it redirects (308 to/contract/openapi.json) as it does for anonymous.test/run-token.test.ts, a token scoped togods-eye-viewsits beside a second public repository (public) and a private one (vault). It checks that:-
herereturns 200 for the two in-scope paths and 404 for six out-of-scope paths. -searchandexplorereturn only in-scope repositories, and the search checks cover repos, issues and code hits. -publicandvaultappear for the unscoped personal token, so their absence for the run token is meaningful.I read "repository-scoped token" as the crew run token (
auth.run) and gated only that. Ordinaryro/rw/admintokens have no repository scope in this codebase. Plain tokens are not affected by any of this.The
/search?q=web page stays 404 for run tokens, as before.I added no dependencies.
Closes #6200