Skip to content

[DRAFT RFC] Browser-based auth & one-command client provisioning#55

Draft
saadqbal wants to merge 2 commits into
developfrom
docs/rfc-0001-cli-auth-provisioning
Draft

[DRAFT RFC] Browser-based auth & one-command client provisioning#55
saadqbal wants to merge 2 commits into
developfrom
docs/rfc-0001-cli-auth-provisioning

Conversation

@saadqbal

@saadqbal saadqbal commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Draft for discussion — not for merge yet. Inline comments welcome on docs/rfcs/0001-cli-auth-and-client-provisioning.md.

Tracking epic: #54

What this is

Design RFC for replacing the current onboarding (sign up on web → hand-create a client at /clients → copy Client ID + password → paste into installer) with:

sign in (browser device flow) → name this machine + confirm location → done

Why it's mostly additive, not a rewrite

Grounded survey of backend / client-runtime / cli found that most of the model already exists:

  • Client = EdgeDevice; human-readable name (first_name) and structured location (location → Electricity Maps ZONE_CHOICES) already exist and feed a working carbon pipeline.
  • Provisioning API POST /edge-device/ already exists.
  • A maintained Go CLI already exists and is installed by the client installer — the right home for login + client create.
  • Only real gap: an RFC 8628 device-authorization grant on the backend (no device flow / PAT today).

Please weigh in on (RFC §11)

  1. Is air-gapped / no-egress on-prem a real segment? (decides whether the token/enrollment-key fallback is first-class)
  2. Location-change semantics — future-only vs re-baseline historical gCO₂?
  3. Namespace ↔ name reconciliation if we derive the slug from the display name.
  4. RBAC, multi-client-per-host, re-parenting — phase 1 or block?

Not in scope yet

Sub-tickets across backend / cli / client (§12) come after the design firms up.

🤖 Generated with Claude Code

Design epic for replacing copy-pasted Client ID + password onboarding
with a device-flow (RFC 8628) browser sign-in + auto-provisioning.

Refs #54.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@saadqbal saadqbal self-assigned this Jun 5, 2026
@LukasWodka

Copy link
Copy Markdown
Contributor

👋 Heads-up — Code review queue is at 16 / 8

Above the WIP limit. The team convention is to review existing PRs before opening new work.

Open PRs currently in Code review (oldest first):

Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.)

- §6.6: derive namespace slug from display name ONCE then freeze (k8s
  namespaces are immutable); collision-suffix + empty-slug guard +
  --namespace override; backfill leaves existing slugs untouched.
- §6.7: location is soft-required (required but pre-filled); never accept
  a silent empty (reads as carbon-free); explicit "set later" path; keep
  DB blank=True for back-compat, enforce at UX layer.
- Appendix B: name→slug reference algorithm + prototype validation table
  + manage.py query to validate against production namespaces.

Refs #54.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor

Stood up a cross-repo tracking epic so this RFC is tracked as the leading CLI plan: tracebloc/backend#830 (North Stars, Epic, owner @saadqbal). It carries the phased plan (Phase 0/1/2), the cross-repo work breakdown (backend / cli / client), and the open questions for the discussion. This RFC doc stays the source of truth — the epic is just the tracker.

@LukasWodka

Copy link
Copy Markdown
Contributor

Worked the §11 open questions to resolution with a code-grounded sweep (backend / client / cli) and laid out the full cross-repo plan + device-grant design in the tracking epic tracebloc/backend#830. Headlines (most are dictated by the code, not opinion):

  • Q1 air-gap → out of scope. Preflight hard-fails on no egress; #172 is corporate-proxy support, not air-gap. Real segment = egress-restricted-but-online (must work behind a TLS-inspecting proxy).
  • Q2 namespace → name→slug→BOTH EdgeDevice.namespace + TB_NAMESPACE. The heartbeat overwrites namespace every ping, so the provisioned slug must equal the install-time namespace or it drifts.
  • Q3 location change → future-only, already clean. gCO₂ is a frozen per-experiment snapshot — never re-derived from current location.
  • Q4 RBAC → split read from write + "pick existing / ask admin" (today one perm gates both list and create → bare 403).
  • Q5 → multi-client per account/host is free; re-parenting deferred (the viewset force-stamps account to the requester).
  • Q6 IdP → reuse the existing web login as-is. Auth is token-based; Google/GitHub already mint the same token, so /activate is just a token-authed endpoint binding to request.user — no new IdP wiring.

Two need your product nod — Q1 (air-gap out) and Q5 (re-parenting deferred); the rest follow from the code. Full detail, the DeviceGrant design, and the phased per-repo breakdown are in backend#830.

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.

3 participants