Skip to content

feat(gateway): robust Smithers Gateway manager + Tailscale exposure - #60

Merged
pgebheim merged 2 commits into
feature/smithersfrom
feat/smithers-gateway-manager
Aug 1, 2026
Merged

feat(gateway): robust Smithers Gateway manager + Tailscale exposure#60
pgebheim merged 2 commits into
feature/smithersfrom
feat/smithers-gateway-manager

Conversation

@pgebheim

@pgebheim pgebheim commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

What

  • scripts/smithers-gateway.sh — an idempotent manager for the Smithers workspace Gateway with Tailscale auto-discovery.
  • gateway config block in rig.schema.json + rig.config.example.json (gateway.{port,mode,servePort,trustAnyHost}).

install.sh already vendors scripts/* into <target>/.claude/scripts/ (and chmod +x's .sh), so no installer change is needed.

Why

The Gateway's token auth is Authorization-header only — a browser navigating to a URL can't send that header, and there's no query-param / cookie / Basic-auth fallback, so a token-gated UI is simply unreachable from a browser. This bit us trying to reach the console over Tailscale.

The manager runs the Gateway on loopback (no token) and publishes it to the tailnet over HTTPS via tailscale serve — making Tailscale device identity the auth boundary while the Gateway stays unauthenticated on 127.0.0.1 where nothing else reaches it. It exports SMITHERS_GATEWAY_TRUST_ANY_HOST=1 so the tailnet DNS name in the Host header isn't rejected as a DNS-rebinding attempt.

Commands

up (default) · down · restart · status · url · discover

  • Auto-discovers Tailscale (ip, MagicDNS name, HTTPS certs) and picks the mode: autotailscale-serve when available, else loopback.
  • Liveness is an HTTP console probe, not smithers gateway status — the status tracker can report running:false for a serving, manually-started/re-adopted Gateway (observed live).
  • Idempotent (reuses a healthy Gateway + existing serve mapping); graceful fallback to loopback when Tailscale is absent; explicit --insecure opt-in for direct tailnet-IP binding.

Verification

Exercised live against a 0.32 gateway + real tailnet:

  • discover → correct dns / ipv4 / https-cert detection.
  • statusrunning (via probe) + serve: https :8443 → 127.0.0.1:7331 (active) (multi-line tailscale serve status parsed correctly).
  • up (idempotent) → detects healthy gateway + serve, mutates nothing, prints https://<name>.ts.net:8443/console.
  • bash -n clean; both JSON files validate; example fields match the schema.

Mutating paths (fresh start / teardown) are covered by the same probe-based health logic used in the verified idempotent path.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TMUG7KT32tVitdDTjjyrgE

pgebheim and others added 2 commits August 1, 2026 22:26
Add scripts/smithers-gateway.sh — an idempotent manager for the Smithers
workspace Gateway that publishes it to a tailnet for token-free browser
access — plus a `gateway` config block in rig.schema.json and the example.

Why: the Gateway's token auth is Authorization-header only, so a token-gated
UI is unreachable from a browser (no query-param / cookie / Basic fallback).
The manager runs the Gateway on loopback (no token needed) and publishes it
over HTTPS via `tailscale serve`, making Tailscale device identity the auth
boundary while the Gateway stays unauthenticated on 127.0.0.1. It exports
SMITHERS_GATEWAY_TRUST_ANY_HOST=1 so the tailnet DNS name in the Host header
isn't rejected as a DNS-rebinding attempt.

Commands: up (default) / down / restart / status / url / discover.
- Auto-discovers Tailscale (ip, MagicDNS name, HTTPS certs) and picks the mode
  (auto -> tailscale-serve when available, else loopback).
- Liveness is an HTTP console probe, not `smithers gateway status` (which can
  report running:false for a serving, manually-started Gateway).
- Idempotent; graceful fallback to loopback when Tailscale is absent; explicit
  `--insecure` opt-in for direct tailnet-IP binding.

Config: gateway.{port,mode,servePort,trustAnyHost}. install.sh already vendors
scripts/* into <target>/.claude/scripts/, so no installer change is needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TMUG7KT32tVitdDTjjyrgE
…sink

Wire scripts/smithers-gateway.sh into rig-sync apply's `workflow` sink: after
`smithers up ... --input`, run `smithers-gateway.sh up` so the durable run gets a
browser-reachable console (loopback Gateway + Tailscale HTTPS when present) and
report the console URL alongside the run id. Document the `gateway.*` config in
the skill's Configuration section.

rig-sync is the only skill that launches a durable Smithers run (rig-epic/rig-task
are agent-orchestrated and don't `smithers up`), so this is the one apply flow
that needs the wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TMUG7KT32tVitdDTjjyrgE
@pgebheim
pgebheim marked this pull request as ready for review August 1, 2026 22:44
@pgebheim
pgebheim merged commit 7624700 into feature/smithers Aug 1, 2026
2 checks passed
@pgebheim
pgebheim deleted the feat/smithers-gateway-manager branch August 1, 2026 22:44
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