fix(start-cli): stop scaffolding a host that breaks every command - #3752
fix(start-cli): stop scaffolding a host that breaks every command#3752MattDHill wants to merge 2 commits into
Conversation
6113403 to
ab5c947
Compare
| # The StartOS devices you install to. Uncomment and set `default` to your own | ||
| # box's address — shown in its web interface — to enable `make install`. | ||
| # host: | ||
| # default: https://adjective-noun.local |
There was a problem hiding this comment.
we don't do adjective-noun anymore, this is a bad placeholder
There was a problem hiding this comment.
Fixed, and swept the rest — it was in two books, three sets of web fixtures, and two scripts as well.
server-name wherever it stands in for a name the reader substitutes, per @MattDHill.
One that wasn't a placeholder: setup.rs said --hostname "defaults to a random adjective-noun pair", which is a claim rather than a stand-in — and a wrong one, since generate_hostname() produces startos-<4 hex digits> and the ADJECTIVES/NOUNS lists it names are still compiled in but referenced by nothing. That's a clap doc comment, so it was wrong in --hostname's help text too. I first swapped in the real format, then reconsidered on Matt's point that the field is user-settable and changeable: naming any scheme is what went stale, so it now just says the name is generated if unset and can be changed later.
Left alone: assets/adjectives.txt and assets/nouns.txt themselves. They appear to be dead — nothing references either static — but deleting compiled-in assets is a different change from retiring a placeholder, and it's your call whether something still wants them.
There was a problem hiding this comment.
Correcting myself above: I said the word lists "appear to be dead", which is misleading. Adjective-noun server names are a live feature — @MattDHill points out they are the re-rollable suggestions in the UI, which the user can cycle or free-form override.
They come from a TypeScript copy: shared-libs/ts-modules/shared/src/util/server-name-words.ts, via randomServerName(), used in the setup wizard's password page and the system → general server-name dialog. Untouched by this PR.
What is orphaned is only the Rust pair — hostname.rs's ADJECTIVES/NOUNS statics and the assets/*.txt they include_str! — which nothing in any .rs references. Still not deleting them here, and now for a better reason than "they look unused": the feature they're named after is alive elsewhere, so whether Rust ever needs its own copy is a question for someone who knows the plan, not a side effect of a placeholder sweep.
This also sharpens why setup.rs was wrong rather than merely stale. Those are two different fields:
/// Friendly server name
name: Option<InternedString>,
/// Hostname (LAN advertised) — defaults to a random adjective-noun pair
hostname: Option<InternedString>,Adjective-noun is the name convention. hostname is generated by generate_hostname() as startos-<4 hex digits>. So that comment described the wrong field's behavior, in text that clap surfaces as --hostname help.
There was a problem hiding this comment.
Removed the orphaned Rust copy after all — @MattDHill pushed back on my leaving it dangling, and once the finding held up there was no reason to.
hostname.rs'slazy_static!block (both statics)src/assets/adjectives.txt+nouns.txt— 9,072 lines,include_str!'d into every binary
They are private statics, so nothing outside the module could reach them even in principle, and nothing inside does. The live adjective-noun feature is the TypeScript copy — shared-libs/ts-modules/shared/src/util/server-name-words.ts via randomServerName() — which this PR does not touch. generate_hostname() has produced startos-<4 hex digits> for a while, so the Rust lists were serving a scheme that is gone.
assets/ held nothing else, so the directory goes with them. lazy_static stays a dependency — lib.rs, sound.rs, net/wifi.rs and net/ssl.rs still use it.
Note
Not compile-verified locally — a cold start-core build is more than my machine takes gracefully. The risk is about as low as a Rust deletion gets: removing a private unreferenced static cannot break anything that compiles today, and a stale include_str! is a hard compile error rather than a silent one, so CI will say so immediately if I have this wrong.
`s9pk init-workspace` wrote `host.default: https://dev-vm.local` as a placeholder for the packager to replace. That is not inert. `CliContext::init` pins a `.local` host eagerly, before the command runs: musl's getaddrinfo cannot do mDNS, so start-core shells out to getent, and the lookup's failure propagates and aborts context construction. Since `dev-vm.local` resolves on nobody's network, every command in a fresh workspace died on DNS — including `s9pk pack` and `s9pk list-ingredients`, neither of which opens a socket. Those two are what `s9pk.mk` calls, so `make` could not run at all until the file was edited. Environment Setup has the packager set `host.default` in the *Install to StartOS* step, after Quick Start has them run `make x86`. So the documented order walks into it, and the error names neither the placeholder nor the file it came from. The `host` block now ships commented out, with a line saying what to do with it. An unset host falls back to `http://localhost`, which is not `.local` and so is never resolved. Repointing the placeholder at an address would work equally well for the DNS failure but would assert a default that is wrong for everyone; there is no address that is right. The scaffold test asserted a non-empty host map. It now asserts the opposite — no host at all — so a future placeholder cannot come back unnoticed. Existing workspaces are untouched: `write_if_absent` never rewrites a config that exists, so a packager on 1.1.0 picks this up by commenting out or repointing `host.default` themselves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ab5c947 to
024e685
Compare
024e685 to
32cf2cc
Compare
StartOS hasn't generated adjective-noun hostnames for a while — `generate_hostname()` produces `startos-<4 hex digits>`, and the word lists it used to draw from are still compiled in but referenced by nothing. The placeholder outlived the scheme it was named after, across two books, three sets of web fixtures, and two scripts. `server-name` everywhere it stands in for a name the reader substitutes: it reads as generic, which the old one stopped doing the moment it implied a convention that no longer exists. `setup.rs` was not a placeholder but a stale claim, on a clap doc comment that becomes `--hostname` help text. It now says the name is generated if unset and can be changed later, and names no scheme — the specificity is what went stale, so a fresh specific claim would only do it again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
32cf2cc to
dd210f4
Compare
s9pk init-workspacescaffoldshost.default: https://dev-vm.localfor the packager to replace. That placeholder is not inert — it breaks everystart-clicommand in a fresh workspace, including ones that never open a socket.Why a wrong default host stops local commands
CliContext::initcallspin_mdns_host(&mut url)?before the command runs. For a.localhost that resolves the name eagerly throughgetent— musl'sgetaddrinfocan't do mDNS, so start-core shells out to the system resolver — and pins the address into the URL. The?propagates a failed lookup, aborting context construction.dev-vm.localresolves on nobody's network, so context construction always fails.s9pk packands9pk list-ingredientsare collateral: neither wants a host, and both are whats9pk.mkcalls, somakecannot run in a freshly scaffolded workspace until the packager editsconfig.yaml.Non-
.localhosts returnOk(())without resolving, which is why this is specific to the placeholder rather than to having a default at all.The documented order walks into it
Quick Start has you scaffold, then
make x86. Environment Setup has you sethost.defaultin the Install to StartOS step — after that build. So a packager following the guide in order hits this on their firstmake, with an error naming neither the placeholder nor the file it came from.The fix
The
hostblock ships commented out, with a line saying what to do with it. An unset host falls back tohttp://localhost, which is not.localand so is never resolved.Repointing the placeholder at some address would fix the DNS failure equally well, but it would assert a default that is wrong for everyone — there is no address that is right. Shipping none is the honest state, and it is also what the file now says.
Environment Setup is updated to match, and the scaffold test — which asserted a non-empty host map — now asserts the opposite, so a placeholder can't come back unnoticed.
Existing workspaces are untouched:
write_if_absentnever rewrites aconfig.yamlthat exists. A packager already on 1.1.0 picks this up by commenting out or repointinghost.defaultthemselves, which the changelog entry says.Verification
A/B against the released 1.1.0 binary — same command, same directory, only
.startos/config.yamldiffering:list_ingredientsand fails on the missing manifest — the command randev-vm.local)Network Error: Failed to resolve hostname: dev-vm.local— dead before doing anythingThe new constant also parses to exactly
{schema, registry}with three registry entries and nohostkey.Note
I did not run
cargo test -p start-corelocally — it compiles the whole backend from cold, which my box doesn't tolerate well. The one test I changed (scaffolded_config_parses_as_workspace) is a pure assertion swap against the same constant, but it wants CI's eyes rather than mine.Found via
Helix hit this after Start9Labs/helix#72 gave its repo pool a real packaging workspace: signing started working and
makepromptly failed on DNS instead. Start9Labs/helix#76 drops the block on that box; this is the same fix where it belongs.Left alone deliberately
The deeper question is whether
pin_mdns_hostshould abort context construction at all for commands that never open a socket — that is what turns a wrong default into a total outage rather than a connection error at first use. Deferring the pin means resolving at each use site, sincerpc_urlandregistry_urlare derived frombase_urlat construction, so it is a real refactor with its own trade-offs. Worth deciding separately; this PR removes the trigger, not the mechanism.