Skip to content

feat(website): a website env stores its names from env.toml, and a multi env refuses a name two of its sites claim (FD-4931) - #514

Open
earakely-scale wants to merge 2 commits into
mainfrom
edgararakelyan/fd-4931-site-names
Open

earakely-scale wants to merge 2 commits into
mainfrom
edgararakelyan/fd-4931-site-names

Conversation

@earakely-scale

@earakely-scale earakely-scale commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

A website env's names now live in its env.toml, as decided in #445's design review: env.toml holds what agentenv needs before a site runs, and the card the site serves stays its contract. Before this, a site's names were known only once it ran, read from its card when a computer deployed beside it, so two sites of one multi env could claim one name with nothing said until then.

  • domains in a website env's env.toml (or agent-env env website put --domain, repeatable). Each name is checked as a computer's site table checks it: lowercase, DNS labels, a wildcard only as its whole first label. WebsiteEnv.domains is stored, serialized (only when set, so existing records are unchanged), and round-trips through to_toml.
  • One order for a site's names: its stored domains, else its card's website/v1 domains, else <environment_name>.localhost. Stored names win, and they are not compared with the card's: the required any_host conformance check already makes a conforming site work under any name. deployed_sites reads the stored names first, and skips the live card read for a site whose names are stored.
  • A name claimed twice is refused before deploy. MultiEnv refuses websites whose stored names overlap (an exact name twice, or a wildcard covering another site's name), and a bundle plan refuses the same before any write. Both use site_table's rule, split out as name_conflicts. A site that relies on its card is still checked at deploy, as today.

Design note, with its 4 decisions: FD-4931 design note: site names in env.toml. Left out by those decisions: per-site overrides on a multi env (rename by putting another WebsiteEnv), a gateway site table, AGENTENV_SITE_TABLE (a browser alone is a computer since M8.53), and apps' sites=[...].

Linear: FD-4931

Test plan

  • New unit tests (test_website_site_names.py): stored names and a refused bad name, a multi env refusing a wildcard overlap, and a computer's table taking stored names over the card's with a .localhost default and no live card read.
  • Bundle tests: a bad domains and two sites claiming one name are refused before any write; a website's domains round-trips through export.
  • CLI test: --domain is stored, and a bad one fails before any registry call.
  • Unit tier for the touched areas (bundle, cli, env, serialization, store, task_step): 7,503 passed. The 2 failures (test_disk_recipe.py, a launcher script) also fail on main on macOS.
  • agent-env bundle register --dry-run on real bundle folders: env.toml domains are accepted, a clash between two sites and a bad name are refused before any write.
  • VM e2e and chaos on an agent-environments-admin VM (c6i.2xlarge, local sandbox; 1 passed in 179 s; VM torn down). There were two sites: chat, which stores chat.e2e4931.test and *.chat.e2e4931.test while its card declares slack.e2e4931.test, and notes, with no names stored or declared. A browser computer was deployed beside them with site_routing.
    • put refuses a multi env adding a site that stores team.chat.e2e4931.test: it overlaps *.chat.e2e4931.test.
    • The computer's table routes chat by its stored names and notes as notes.localhost. The deploy checks answer 200, and the browser's first tab opens https://chat.e2e4931.test/.
    • In the computer, chat.e2e4931.test, team.chat.e2e4931.test (the wildcard) and http://notes.localhost answer as their sites. The card's slack.e2e4931.test doesn't resolve.
    • Chaos: a gateway restart, a site restart and a computer reset each leave both names answering, with the same table after the reset. A second computer with site_routing: [<multi id>] gets the same table.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the previous conflict-check bypass is fixed.

Summary

Websites can store domains in env.toml. These names take priority over card names, and overlapping stored names are refused before deployment.

  • Website environments can save their own site names.
  • Computers route websites using saved names first.
  • Multi environments reject websites with overlapping saved names.

Reviews (2) · Last reviewed commit: "fix(website): a multi env tells its webs..." · Reviewed by Greptile

…lti env refuses a name two of its sites claim (FD-4931)

A website env's env.toml (or `website put --domain`) may name `domains`, checked as a computer's site table
checks names, and `WebsiteEnv` stores them. A computer deployed with `site_routing` routes a site by its stored
names before those its card declares, then `<name>.localhost`. `put` and bundle plans refuse a multi env two of
whose websites claim overlapping names, by the rules `site_table` applies at deploy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale requested a review from a team as a code owner November 6, 2026 08:56
Comment thread src/agent_env/env/envs/multi_env.py Resolved
…the list, so two versions of one env claiming a name are refused

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale

Copy link
Copy Markdown
Collaborator Author

🤖 Automated Claude routine — Env Pod PR Context Review. This is a bot, not Edgar Arakelyan; not a human review.

Context from outside this diff: #447 (open) also gives WebsiteEnv a domains attribute, but spells it differently in env.toml.

  • This PR — src/agent_env/env/envs/website.py: toml_keys gains "domains": list, to_toml writes a top-level toml["domains"], and from_toml reads fields.get("domains").
  • feat(website): live sites, browser/v1 sign-in and WARC replay (FD-4683) #447 (open, head wloo/website-live-replay) — same file: toml_keys carries "spec": object and no "domains"; to_toml writes toml["spec"] = {"site": {"domains": [...]}}, and accept_toml sets fields["domains"] = spec.site.domains only after accept_env, from the resolved spec.

main has neither key today, so each is self-consistent on its own branch. Where they meet is toml_keys, which is an allow-list: accepted in src/agent_env/bundle/authoring.py:133 turns every key outside it into an "unknown key" problem, and accept_env refuses on it. So once both have landed, an env.toml written by one side's to_toml is refused by the other's reader — top-level domains against #447's WebsiteEnv, [spec] against this one — even though both serialize the same to_dict key (base["domains"] = list(self.domains)), so stored records themselves stay compatible.

One more thing worth knowing for sequencing: #447 is stacked on wloo/website-authoring-cli → wloo/website-spec, and #445, the PR that introduced the spec, is closed unmerged — so the spec spelling currently reaches main only through that stack, not on a line of its own.


Generated by Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant