feat(cli): location auto-detect for client create (#84)#93
Draft
LukasWodka wants to merge 3 commits into
Draft
Conversation
RFC-0001 P1. Adds the `client` subtree the login flow hands off to: provision a tracebloc client for this machine, list the account's clients, and attach this machine to an existing one. - internal/slug: Go port of RFC-0001 Appendix B (backend common/utils/slug.py) — DNS-1123 slugify (NFKD via x/text) + collision suffix + empty-slug guard, kept in lock-step with the backend that validates the result. - internal/api: CreateClient / ListClients / ListClientAdmins against /edge-device/, Bearer-authed (backend#836). - internal/cli/client.go: create (--name / --location / --yes), list (ls), use <id>. The derived namespace is shown for confirmation; location is required (never silent-empty); a 403 surfaces the ask-an-admin path (backend#836); the generated machine credential is printed once. Location auto-detect (cloud-metadata / GeoIP suggested default) is a fast-follow — this PR takes --location or prompts for it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eractive tests Self-review follow-up on the client commands: - api: ListClients now follows DRF `next` to the end (was page-1 only), so `list`, `use <id>`, and create-time collision detection see every client in the account, not just the first page. - cli: `create` gathers name + location first, then shows one review + a single confirm (was confirm-mid-flow) — matches the dataset-push interactive flow. - tests: committed slug golden-parity test (24 pairs verified byte-identical against the Python slugify_dns1123, incl. NFKD ligatures/fractions/roman/ fullwidth); interactive create + cancel via the prompter seam; paginated list; collision-suffix end-to-end. - slug: doc-note the redundant dash-collapse (mirrors slug.py) and the ""/None fallback divergence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The deferred fast-follow from cli#92: pre-fill `client create`'s location prompt with a detected electricityMaps zone (backend ZONE_CHOICES), so a cloud-hosted client doesn't have to look up its own zone. - internal/geo: Detect() probes cloud instance metadata first (AWS IMDSv2/v1, GCP, Azure — concurrently under one short deadline, first wins → high confidence), then Cloudflare IP geolocation (low confidence, flagged). Returns an ISO country code, always a valid top-level zone; cloud regions map via a curated AWS/GCP/Azure table, and an unmapped region falls through to GeoIP for a valid zone rather than suggest something the backend would reject. - client create: the detected zone pre-fills the prompt default (the user confirms with Enter or overrides) — still never silent, never empty. A detectZone seam keeps the command tests hermetic. - Best-effort: offline / egress-restricted / bare metal → empty default (the prior behavior). Only runs interactively when --location is omitted. Tests: geo per-provider + GeoIP fallback + unmapped-region fallthrough + nothing-detected + region→country table; cli accepts-detected-zone end-to-end. go build/vet/test green. Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Summary
The deferred fast-follow from #92:
client createnow pre-fills its location prompt with an auto-detected electricityMaps zone (the backend'sZONE_CHOICES), so a cloud-hosted client doesn't have to look up its own zone.Stacked on #92 (
feat/84-client-commands) — it wires into that PR'sclient create. Retarget todeveloponce #92 merges.How detection works (
internal/geo)Detect(ctx)returns a best-effortZone{Code, Source, Confidence}or nil:cdn-cgi/traceloc=(HTTPS, no API key) → ISO country.The output is always an ISO alpha-2 country code, which is always a valid top-level
ZONE_CHOICESvalue. An unmapped cloud region falls through to GeoIP rather than suggest a string the backend would reject.UX
--locationis omitted;--location Xskips it entirely.Tests
internal/geo: each provider, GeoIP fallback, unmapped-region fallthrough, nothing-detected, region→country table — endpoints mocked viahttptest(the metadata/GeoIP URLs are overridable package vars).internal/cli: detected zone accepted as the default, end-to-end. AdetectZoneseam keeps the command tests hermetic (no real probes). Fullgo build/vet/test ./...green.Follow-up noticed (separate)
locationisCharField(choices=ZONE_CHOICES)— the backendChoiceFieldrejects any value not in the list. cli#92's free-text--location(and a user override here) can still send an invalid zone that only fails at create time as a raw 400. Worth vendoringZONE_CHOICESinto the CLI to validate / offer a picker — happy to file that.🤖 Generated with Claude Code