Repository navigation
feat(computer): a computer reaches the run's websites by their names (FD-4683) - #448
Conversation
earakely-scale
left a comment
There was a problem hiding this comment.
We've reviewed this against our plan for websites in the computer. Three parts are better than what we'd planned, and we've changed our design docs to follow them:
- the CA made for each deploy, limited to the run's site names, with its key discarded after signing;
- the transparent loopback routing;
- the site table's rules.
The latest commits already fix three things we'd found: Chromium's trust (the CACertificates policy), the check's time budget, and WebSockets through the gateway. Four things are inline. Three smaller ones are below, and are optional.
Smaller things:
- Leaf keys:
RootChannel.write(sites.py:324) sends them base64-encoded in abash -cargument, through a staging file in the VM host's/tmp.write_secret_fileavoids both. site_routingvalidation:run_env_params(computer/env.py:172) uses the value beforeComputerParamsvalidates it."web-env"becomes one env id per character, and1raises a TypeError.- Rewrites:
- a scheme-relative
Location: //gw/website/notes/xis passed through unchanged (site_proxy.py:181), so the browser leaves the site's name for the gateway; Set-Cookie: ...; Path = /website/notes/x, with spaces around=, isn't rewritten (site_proxy.py:200).
- a scheme-relative
… traffic/v1 (FD-4683) This PR's change, rebased as one commit onto #448. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
a50d72f to
a767a25
Compare
cb672e5 to
306587d
Compare
… traffic/v1 (FD-4683) This PR's change, rebased as one commit onto #448. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
a767a25 to
d160d31
Compare
306587d to
2b782e9
Compare
2b782e9 to
0d613b8
Compare
d160d31 to
5953d5a
Compare
… traffic/v1 (FD-4683) This PR's change, rebased as one commit onto #448. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
0d613b8 to
9495ed2
Compare
5953d5a to
9f2a5ca
Compare
|
@earakely-scale thanks for the review. Everything you raised is now addressed in #448: Inline (replied to and resolved on each thread):
The smaller three (
Each new test fails on the code before its fix. |
… traffic/v1 (FD-4683) This PR's change, rebased as one commit onto #448. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
f813a59 to
faf8e7c
Compare
04d3f23 to
956163f
Compare
… traffic/v1 (FD-4683) This PR's change, rebased as one commit onto #448. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
faf8e7c to
27a865f
Compare
…te at its own root, and the provider's headers kept from sites The gateway side of a computer reaching the run's websites by their names, lifted from #448: - A WebSocket to /website/<name>/ is relayed to the site, under the HTTP route's rules: refused at the paths the site's card reserves, with the role and forwarded address the gateway writes. - AgentEnv-Site-Root: a front that serves a site's route at a root of its own, as a computer's site proxy does, gets no X-Forwarded-Prefix. - The headers the sandbox provider in front of the gateway is sent, its credentials, are taken off every request the gateway forwards (AGENTENV_PROVIDER_REQUEST_HEADERS). - website/v1 browse_url: where a composer serves a site to a browser. Co-Authored-By: William Loo <william.loo@scale.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es either The website browser's CDP answer, its discovery and its WebSocket relay forwarded a request's headers on routes of their own, before the withheld filter; BrowserRoutes now takes the withheld names and drops them on all three. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(FD-4683) The computer side of #448, on the gateway's site routes: - env_params.site_routing (true, or env ids): deploy_env fills the computer's sites from the websites the run deployed before it, read from their cards (Env.run_env_params). - The name table (computer/utils/sites.py): each site's names claimed once, a site's names over the network's allowlist; two sites claiming a name are refused. - A CA made for the deploy, name-constrained to those names, signs a certificate for each site. - site_proxy.py, standard library only, runs on the computer's python3: it maps the names to loopback, trusts the CA (system store, Firefox policy, NSS) and proxies 443 and 80 (and DNS for wildcards) to the site's gateway route with X-Forwarded-Host, -Proto and AgentEnv-Site-Root, rewriting redirects and cookies and relaying WebSockets. - Once the computer is ready the provider installs the proxy and records the table, the CA and each name's check; boot apps launch once the sites are routed; a reset routes the new computer under a new CA. Live sites are left out until they land (FD-4945). Co-Authored-By: William Loo <william.loo@scale.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27a865f to
1f97138
Compare
Comments Outside DiffThese findings could not be posted inline.
|
…, and is readied after its held apps launch A deploy routing sites holds the launch of the computer's boot apps until the names, CA and proxy are in place, but its boot waited for the computer to be ready, and a page driver, whose screen is its browser's page, can't be ready before the browser launches. The boot now waits only for the driver to answer (ready(answering=True)), and the computer is readied, its display then checked, once the sites are routed and the held apps launched; a reset does the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
client_headers is what the gateway may pass on of a connection's headers, minus the hop-by-hop set and the provider's credentials; upstream_headers builds on it, and the CDP routes' discovery and WebSocket relay call it instead of filtering their own copies, so a header withheld once is withheld on every route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ders, whoever runs the tests CodeBuild runs the unit tier as root, which reads a file whatever its mode, so chmod 0 didn't stand for the session user; the read is refused instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… with its server, and the record keeps the ready card On a VM, a browser computer routing sites failed at deploy: its page driver answers before the browser's server does and lists the browser by its name alone, so launch wasn't on the card the boot read. The deploy now waits until the driver lists each held app with its server (boot.listed), launches them, and keeps the card the ready computer answers on its record, in place of the boot's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d lists, though the computer has its name A browser alone is a computer named for its app, chromium, and invoke by that name reached the computer's own card, which offers no launch; the deploy now passes the listed child. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… startup limits Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tes the forwarded host On a boat gateway, the site behind it named the gateway's public host in base_url and redirects: boat's ingress, between the computer's site proxy and the gateway, sets X-Forwarded-Host to its own. The site proxy now names the browser's origin in AgentEnv-Site-Root, and the gateway takes a Site-Root naming an origin as the site's address ahead of X-Forwarded-Host/-Proto; any other value is the root flag as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e the driver answers _finish_boot routes the sites, launches the held boot apps and checks the display, in that order, for both, so the order lives in one place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The computer side of this change; its gateway side landed first as #505. Rebased onto main without #444–#447.
A deployed computer reaches the run's websites by their own names (
https://notes.test/), opt-in.site_routing: the boot waits only for the driver to answer, then the sites are routed, the held boot apps launched, the computer readied and its display checked, so a browser computer, whose page driver's screen is its browser's page, boots too; a reset does the same.computer/utils/sites.py): each site's names claimed once, a site's names over the network allowlist. Live sites are left out until they land (FD-4945).site_proxy.py, standard library only, runs on the computer's python3: it maps the names to loopback, trusts the CA (system store, Firefox policy, NSS) and proxies 443/80 (and DNS for wildcards) to the site's gateway route withX-Forwarded-Host/-ProtoandAgentEnv-Site-Root(feat(gateway): WebSockets on a site's route, a site served at a front's own root, and the provider's headers kept from sites (FD-4683) #505), rewriting redirects and cookies and relaying WebSockets.env_params.site_routing(true, or env ids):deploy_envfills the table from the websites deployed before the computer, read from their cards; once the computer is ready the provider installs the proxy and records the table, the CA and each name's check. A reset routes the new computer under a new CA. Withoutsite_routingnothing changes.Before merging
WebsiteBrowserEnvironment(feat(computer): WebsiteBrowserEnvironment, the base class for website browsers #449): this proxy answers on loopback through the hosts file, so a website browser in a computer, which bypasses loopback and has noAGENTENV_SITE_PROXYset there yet, reaches the sites through it. SettingAGENTENV_SITE_PROXYin a computer (M5.5/M5.7) would need a forward proxy, which this isn't.Test
slack.e2e448.testbehind a gateway), inside two deployed Linux computers withsite_routing:base_url(https://slack.e2e448.test, no prefix), a trailing-slash redirect (307 onto the name), a session cookie (Path=/, no domain), a WebSocket (101 and an echo), port 80 (308 to https) and 50 requests at once all answer through the proxy over TLS the system trusts; the site's data plane and card are 404; Chromium opens the site by its name. The proxy killed is back within 20 s; a gateway restart, a site restart and a paused gateway recover; a reset routes the fresh computer under a new CA, Chromium and the WebSocket working again.🤖 Generated with Claude Code


Confidence Score: 5/5
The changes appear safe to merge; the shared boot path preserves the required order.Summary
Adds opt-in website routing inside Linux computers, including local names, trusted certificates, and an HTTP/WebSocket proxy.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR A[Driver answers] --> B{Site routing enabled?} B -->|Yes| C[Install names, certificates, and proxy] C --> D[Launch held apps] D --> E[Wait for computer readiness] E --> F[Check display] B -->|No: already ready| F F --> G[Return deployment or finish reset]Reviews (28) · Last reviewed commit: "refactor(computer): one sequence for wha..." · Reviewed by Greptile