Repository navigation
feat(core): an app-chosen hostname prefix, with app membership from Hostinfo.App (sidecar protocol 12) - #243
Merged
Merged
Conversation
…ostinfo.App (sidecar protocol 12)
- NodeBuilder::hostname_prefix("vibefield") names the node vibefield-{slug}
instead of truffle-{app_id}-{slug}; validated as a DNS label of 1-61
chars, and exclusive with hostname().
- Every start announces Hostinfo.App = "truffle:{app_id}" (tsnet:start's
app; the sidecar calls hostinfo.SetApp before srv.Start).
- Peer rows carry app, the peer's Hostinfo.App as control relays it. The
sidecar reads it through LocalClient.PeerByID once per peer, and the IPN
bus's full-node notifies keep it current.
- Admission is tag-first: a tagged row is ours only if its tag is
truffle:{app_id}, whatever its name. An untagged row (an older sidecar)
falls back to the truffle-{app_id}- prefix.
- A hello-less peer named {prefix}-{slug} resolves by its slug.
- Sidecar protocol 11 -> 12. A sidecar below 12 ignores app. A node whose
name is outside the convention then logs a warning that its peers will
not recognise it.
- A real-tailnet probe (2026-11-01, tailscale v1.104.1) found that a peer's
netmap row keeps App, Hostname, OS and Services, and drops Package.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
An app can choose the name its devices show on Tailscale's own pages. App membership moves off that name and onto a tag
the node announces in
Hostinfo.App.NodeBuilder::hostname_prefix("vibefield")names the nodevibefield-{slug}instead oftruffle-{app_id}-{slug}.hostname():build()refuses both.Hostinfo.App = "truffle:{app_id}".tsnet:startcarriesapp, and the sidecar callshostinfo.SetAppbeforesrv.Start().SetAppis process-wide, and one sidecar process carries one node.tsnet:peers,tsnet:peerChanged) carriesapp, the peer'sHostinfo.Appas control relays it.ipnstate.PeerStatushas noApp, so the sidecar reads it throughLocalClient.PeerByIDonce per peer.PeersChanged, whichthe bus watch already subscribes to.
is_app_row):truffle:{app_id}, whatever its name. So a node ofanother app under the same prefix stays out.
truffle-{app_id}-prefix, exactly as before.
claim by its name.
{prefix}-{slug}resolves by its slug under the node's own prefix. The convention stillresolves, for a peer on an older release.
app. A node whose name is outsidetruffle-{app_id}-then logs a warning that its peers will not recognise it. The node still starts, as an explicit
hostname()alwayshas.
Additive. An app that sets no prefix keeps
truffle-{app_id}-{slug}and today's discovery.TailscaleConfigisunchanged: the tag is derived from its
app_id.Why: a real-tailnet probe first
The open question was whether control relays a peer's
Hostinfo.Appinto the netmap a tsnet node receives."tsnet".own go.mod:
hostinfo.SetApp("truffle:vibefield-t8probe"); node b set nothing.PeerByID.So a peer's row keeps App, Hostname, OS and Services, and Package is stripped (no carrier). The tag shape stands.
Rollout hazard (read before turning a prefix on)
is_app_peeradmitstruffle-{app_id}-alone, so itwill not see a node with a custom prefix. An app should turn
hostname_prefixon only once every shipped devicereads the tag: two releases, or one upgrade whose builder call waits a version.
apple/Sources/Truffle/Identity/Slug.swift(Hostname.isAppPeer, used atMeshNode.swift:616and:677) still filters by the prefix, and the Swift node announces no tag. A custom-prefixdesktop is invisible to a Swift node until that plane reads and announces the tag, which is a follow-up.
admin console at its next start. Release notes should say so.
NodeOptions.hostnamePrefixin truffle-napi regeneratesindex.d.ts, so itrides its own change.
Tests
The tests were written first and run red against stubs that ignored the tag and the prefix (logs kept):
The new tests:
is_app_row: a present tag decides whatever the name; a foreign tag under our prefix is refused; a same-prefixnode of another app is refused; an absent or empty tag falls back to the prefix.
classify_rowadmits a tagged custom-prefix row, and calls the same row untagged a stranger.appfrom the wire; a protocol-11 row has none.tsnet:startcarries"app":"truffle:playground".hostname_prefixcomposes{prefix}-{slug}. It cuts a long device name to 63 characters, rejects bad and over-longprefixes, and refuses one together with
hostname().hostname_sluglearns the prefix and keeps the convention. A peer namedvibefield-ec2-smokeshowsec2-smokebefore hello and resolves by it.
applyAppreacheshostinfo.New().Appand clears. The app cache fetches once, follows full-node notifies,forgets removed peers, never caches a failure, and tolerates a node without Hostinfo. An
Appchange counts as apeer change.
peer_watchtests feed nodes without Hostinfo, and a bare.App()panicked.TestStatusEventAdvertisesProtocolVersion, the v11 status test).Run locally at this commit, all green, with no tailnet key in the environment:
cargo fmt --check.cargo clippy --locked --workspace --all-targets --exclude truffle-tauri-plugin --exclude truffle-napi --exclude truffle-bench-app -- -D warnings.RUSTDOCFLAGS='-D warnings' cargo doc --locked --no-deps --workspace(the same excludes).cargo test --locked --workspace(the same excludes): 21 suites, 773 passed, 0 failed, 30 ignored.packages/sidecar-slim:gofmt -lis empty;go vet ./...andgo test ./...pass;go test -race -run 'App|Peer|Watch|Status'passes.Not run here: CI's real-tailnet integration jobs. They need
TRUFFLE_TEST_AUTHKEY, and CI runs them on this PR.Petition: VibeField's T8 (track TS, TS-D10).
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.