registry: search page #241
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
A search page for the package registry: a visitor types a query, sees the ranked packages of
GET /api/1/search(name, version, description, keywords, capabilities), and can follow each to its package page.Source
Design
/search/) with a plain<form method="get">and one small script that calls/api/1/searchon the same origin and renders the answer; without the script the page says so and links to the API. No new route is needed (/apialready goes to the write service), no server-rendered HTML in the write service.brand/tokens.cssonce #12 has landed; until then it is blocked, not built twice.Acceptance criteria
/search/renders the results of a query in the registry's shell; empty result and API error states are shown.skills/and the site build (torb docs site --check) green.Seed impact
None expected (site generator and static assets; no syntax, native or driver flag).
Size and dependencies
One PR, one or two Conventional Commits. Depends on #18 (the API) and #12 (the shell and package page). Deploying the site is outside the loop.
[loop:torbscript] intake: in scope (author orion, label loop), source ROADMAP.md (registry), not a duplicate. Search page over GET /api/1/search (landed with #18). next: waiting (refine queued, ready buffer full) until 2026-10-10T04:00:00Z
torb deprecate: flag a whole package as deprecated #279[loop:torbscript] intake: unchanged. Blocked on #12 (the site shell and package page), which is itself still in refine; refining #12 first this tick. next: waiting (#12) until 2026-10-10T04:00:00Z
[loop:torbscript] claim refine by session:loop-torbscript-20261010 until 2026-10-10T12:44Z (#12 is merged, the dependency is gone)
[loop:torbscript] refine: ready-to-build spec (main
1724b82; #12 and #18 are merged).Goal
https://packages.torb.dev/search/lets a visitor type a query and see the ranked packages ofGET /api/1/search(name, version, description, keywords, capabilities), each linking to its package page/packages/<owner>/<name>/.Implements
ROADMAP.md "the package manager" (registry);
docs/design/RELEASE.md7.9 (search and ranking, the API is built), 7.11 (the pages: "The search page (#241) ... not built"), readiness slice 13. The shell iscompiler/src/documentation/site-registry.trb(registryPageHtml,registryScript,registryStylesheet).Design (as found in main)
searchAction: Some("/search/")(a plain<form method="get">), andnginx.conffor packages.torb.dev already hasconnect-src 'self'andform-action 'self'in the/packages/policy;/answers 404 there, so/search/needs a location./apiis routed to the write service by Traefik and is untouched.search/index.htmlin the registry's storage, written by the write service at every start (overwrite, so a new toolchain's shell reaches it), next tofillPagesintools/registry/src/main.trb/registry.trb. Its HTML is a pure function in a newtools/registry/src/searchpage.trb(or next topackagePageHtml) built withregistryPageHtml("Search", body, searchAction: Some("/search/")). No server-rendered results.assets/registry-search.js(functionregistrySearchScript()insite-registry.trb, written bytorb docs sitebesideassets/registry.js,texts.setinsite.trb). It is a separate file so package pages do not load it; the search page loadsregistry.js(theme) andregistry-search.js.registryPageHtmlgets an optionalscripts: List<String> = []parameter for the extra<script src>(no inline script).qandoffsetfromlocation.search, putsqin the field, calls/api/1/search?q=..&limit=20&offset=..on the same origin, renders withcreateElement/textContentonly (neverinnerHTML, neverinsertAdjacentHTML), sets hrefs only fromowner/namevalidated against^[a-z0-9][a-z0-9-]*$as/packages/<owner>/<name>/(otherwise the row is shown as text without a link). Previous/next are plain links?q=..&offset=... States: no query (a hint), loading,total0 ("No package matches"), API error (400 shows the API'smessage/problemsas text; network or 5xx a short sentence with a link to/api/1/search?q=...). Ano-scriptnote in the page ("Search needs JavaScript; the API answers at /api/1/search?q=...") is visible by default and hidden by the script via thehiddenattribute, nostyle=.owner/name(link), version, description, keywords and capabilities as chips (existing.chiprules), dependents count. CSS goes intoregistryStylesheetby tokens only (the existing tests forbid own colours).location /search/ { index index.html; try_files $uri $uri/ =404; Cache-Control public, max-age=60; same CSP and nosniff as /packages/ }; the CSP stays strict (script-src 'self').Acceptance criteria (testable)
registrySearchScript()is written asassets/registry-search.jsbytorb docs site;compiler/tests/site-registry.test.trbasserts it exists, makes exactly one request to/api/1/search, contains noinnerHTML/outerHTML/insertAdjacentHTML/document.write/eval, and that every state (empty query, no result, API error, network error) has its text in the script.tools/registry/tests) has the shell, thepackageslabel, a<form method="get" action="/search/">with a fieldq, both scripts as<script src>, no inline script, nostyle=, no handler attribute, and the no-script note naming/api/1/search.<img src=x onerror=alert(1)>and"><script>and shows the output is text (a pure TorbScript twinfoundRow(...)used to generate a documented fixture is not required; if the script cannot be run in the test runner, the criterion is the source assertions above plus the manual check recorded in the PR: the page loaded in a browser with the markup description from a staging registry)./packages/<owner>/<name>/; a name that does not match the name rule is not linked.search/index.htmlat start (registry test on a temp storage: absent, then present; present with other content, overwritten).tools/deploy/nginx.confhas the/search/location with the same CSP; the existing nginx config check in CI stays green.docs/design/RELEASE.md7.11 no longer says the search page is not built and names/search/;tools/registry/README.mdlists the page;torb docs site --check, the regeneratedskills/and the full CI gates are green.Seed impact
None. No syntax, no native, no driver flag, no std name looked up by string; the code uses the std the registry already uses (
std/storage) and string constants. The two-commit rule is not triggered.Size
One PR, two Conventional Commits: (1)
feat(site): the registry's search script and styles(script, CSS,scriptsparameter, site.trb asset, compiler tests); (2)feat(registry): the search page at /search/(page function, write at start, nginx location, tests, docs). Deploying is outside the loop.Out of scope
The search field in the header of package pages (existing package pages are only written when missing, so adding it needs a rewrite of every page): follow-up issue filed, depends on this one. Ranking on package checks (RELEASE.md 7.9, waits for the checks).
[loop:torbscript] decided by the loop: (1) the search script is its own asset
assets/registry-search.js, not part ofregistry.js, so package pages do not download code they never run; (2) the page is a file the write service writes at every start into the storage (like the package pages, overwritten so a toolchain update reaches it) and not a page oftorb docs site, because the docs site is served at torb.dev and a registry page there would be a second, wrong URL; the registry host's nginx serves storage, the assets come from the image as before; (3) results are rendered withtextContentonly and package links are built from names that match the name rule, so third-party text never becomes markup; (4) the header search field on package pages is split off (follow-up) because existing pages are not rewritten at start.[loop:torbscript] refine: spec, criteria, design points and seed impact (none) recorded above, one PR of two commits; split-off follow-up #306 (search field in package page header, depends on #241), next: ready
[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T16:52Z
[loop:torbscript] implement: PR #308 (head
95c0f460, CI pending: pdisc fixed and green, bootstrap green, tier/gates jobs still queued on the two torb runners after 58 min, argus requested), est. tokens 120k, next: waiting (review by argus)[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T15:30Z
[loop:torbscript] implement: PR #308 (head
14d394d8, rebased onto main after #307, CI pending, argus requested), est. tokens 60000, next: waiting (review by argus)