Skip to content

fix(cli): select the Tailscale Serve origin matching the current device - #25

Draft
andromarces wants to merge 1 commit into
rjx18:mainfrom
andromarces:fix/tailscale-serve-stale-hostname
Draft

andromarces wants to merge 1 commit into
rjx18:mainfrom
andromarces:fix/tailscale-serve-stale-hostname

Conversation

@andromarces

Copy link
Copy Markdown
Contributor

Fixes #24.

Problem

With Tailscale Serve access, codor install builds the pairing link from the first https:// origin
in tailscale serve status. After a tailnet DNS rename, Tailscale keeps the Serve handler keyed by the
old MagicDNS name and lists it first, so the link and its ?endpoint= parameter carry a hostname that
no longer resolves. Codor never reads the node's current Self.DNSName, so serve status order alone
decides the endpoint.

Result

The pairing origin is now the HTTPS origin whose host matches the current device name and whose root
handler proxies to Codor, regardless of the order serve status prints.

Implementation

  • Read the current device FQDN from tailscale status --json Self.DNSName (trailing dot removed).
    An unreadable or absent name fails with its own diagnostic.
  • Parse tailscale serve status text into per-origin root-path proxy targets.
  • Select the HTTPS origin whose host matches Self.DNSName and whose / handler proxies to the local
    endpoint.
  • No match fails with a diagnostic that names every HTTPS origin and states that tailscale serve reset
    clears all Serve config on the node. Zero HTTPS origins keeps the existing "did not report a private
    HTTPS origin" message.
  • A tailscale status --json failure now reports "Tailscale status command failed" instead of the Serve
    label.
  • The dry-run transcript prints the tailscale status --json read.

Parser scope

Matches Tailscale's port/path granularity, checked against cmd/tailscale/cli/serve_legacy.go and
cmd/tailscale/cli/serve_status.go at v1.102.4:

  • an origin line of either scheme closes the previous origin, so an HTTP handler cannot attach to the
    HTTPS origin printed before it;
  • only the root / handler qualifies, so a /sub proxy does not;
  • Web origins print in sorted HostPort order, which is why host:10443 can precede host on 443, and
    why order alone is not authoritative.

Compatibility decision

Codor's serve command publishes the root handler on HTTPS 443, so the HTTPS-only, root-only match
reflects what Codor itself created. This adds a dependency on the tailscale status --json shape. The
read degrades to a clear failure, never a silent stale pick.

Harn

Touches setup-bounds-tailscale-serve-consent-and-keeps-diagnostics-actionable, nested in
setup-resolves-and-capability-probes-tailscale-serve. The bounds contract stays intact: only
serve --bg is bounded; status --json and serve status stay unbounded. .harn/ is not edited.

Tests

pnpm install --frozen-lockfile
pnpm -r build
cd packages/cli
pnpm exec vitest run src/setup-tailscale.spec.ts   # 21 passed
pnpm exec vitest run                               # 11 failed | 275 passed | 18 skipped
  • setup-tailscale.spec.ts passes, including 7 new cases: stale-first two-origin selection, all-origins
    no-match diagnostic, current-name wrong-proxy rejection, unreadable device name, non-root /sub
    ignored, HTTP-handler boundary, and the status --json failure label.
  • Whole-CLI suite, Windows 11 only: the branch run is 11 failed | 275 passed | 18 skipped. A targeted
    baseline run on unmodified main (03481a3) reproduced the same 11 failures, 5 in
    launcher-install.spec.ts and 6 in update.spec.ts. Earlier runs also reported an index.spec.ts
    worktree lifecycle timeout that did not recur. None of the failures is Tailscale-related. The suite
    total grows from 297 to 304, the 7 new cases.
  • pnpm -r test aborts in packages/adapters/antigravity on Windows before reaching @codor/cli. CI
    runs pnpm -r --workspace-concurrency=1 test on Ubuntu; that gate was not run on this platform.

Not tested

  • Platform: Windows 11 only. The index.spec.ts setup integration case is posixHostIt-guarded, so it
    did not execute here; the parser cases run on every platform.
  • Real device: a live rename-and-install cannot be reproduced on the repro node now because
    tailscale serve reset removed the old handler. Stale-first selection is unit-tested.
  • A live single-origin probe on this node (Tailscale 1.102.4, Windows) returned
    https://<device>.<current-tailnet>.ts.net with the call order serve --bg, status --json,
    serve status.

codor install built the pairing link from the first https origin in tailscale serve status. Tailscale keeps a handler keyed by the old MagicDNS name after a tailnet rename and lists it first, so the link carried a hostname that no longer resolves.

Read Self.DNSName from tailscale status --json and return the origin whose host matches it and whose handler proxies to the local endpoint. Fail with a diagnostic naming the configured origins and the tailscale serve reset escape when none matches.

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.

install generates pairing links with a stale hostname after a tailnet DNS rename

1 participant