Skip to content

lbzfai.com ↔ Jetson dashboard integration

Bucket: Backend (Agent B) Status: Reviewed — 2026-05-12 (Phase B seams applied: Cloudflare Tunnel parked per ADR-005) Owner: Sophia · Reviewers: Andrew, Agent C (front-end consumer), Agent A (network / Tailscale)

lbzfai.com is a static Astro page with Auth0 login. The CV monitoring runs on a Jetson on LBZF’s local network with no public IP. The question this doc answers: how do authenticated users on lbzfai.com see Jetson data in Phase I?

ADR-005 (Tailscale-only Phase I) locked the answer: Phase I users install Tailscale and reach the Jetson dashboard directly (http://<jetson-tailscale-ip>:5000). lbzfai.com stays a static + Auth0 landing; it does not proxy live Jetson data.

The outbound-tunnel + Worker-as-proxy architecture proposed in round-1 is parked to docs/design/60-parking/cloudflare-tunnel-from-jetson.md and resumes in Phase II if Mariana (or a future executive user) refuses Tailscale.

  • Phase I path for authenticated users to reach Jetson data without exposing the Jetson to the public internet.
  • Identity flows cleanly from Auth0 login → role-aware UI on lbzfai.com → user clicks “Open dashboard” → Tailscale-direct to the Jetson where the same identity is recognized.
  • Works for Sophia, Andrew, Armando, Ronald, Mariana, and the ITBA team (all install Tailscale; Tailscale paid tier per ADR-005).
  • A documented migration path to Phase II Cloudflare-Tunnel-mediated proxy access (preserved in parking).
  • Mariana viewing live data on her phone without Tailscale — Phase II per ADR-005.
  • Public video streaming. Phase I is JSON dashboards + small frame thumbnails reached via Tailscale only.
  • Multi-Jetson load balancing — Phase I has one LBZF Jetson + one ITBA twin, both on Tailscale with different tags (tag:lbzf-pereira, tag:itba-dev).
  • Replacing Tailscale; Tailscale is the secure transport.

Phase I architecture — Tailscale-direct, lbzfai.com stays static

Section titled “Phase I architecture — Tailscale-direct, lbzfai.com stays static”
public internet
user browser ───────── https://lbzfai.com ───────── Cloudflare Workers
(any device, │ │
on Tailscale) │ ▼
│ static Astro shell
│ + Auth0 SPA login
│ + role-aware /app/ pages
│ (NO Jetson proxy)
Auth0 ◀──── login redirect
▼ Auth0 JWT contains:
https://lbzfai.com/role (singular string)
https://lbzfai.com/org_id (integer)
https://lbzfai.com/module_scope (array or null)
▼ /app/ingeniero (Ronald) or /app/ejecutivo (Mariana)
│ shows: "Open dashboard" link
▼ user clicks → http://<jetson-tailscale-ip>:5000
▼ Tailscale wire
┌────────────────┐
│ Jetson │
│ :5000 ───▶ │ FastAPI dashboard
│ │ ─ Tailscale-User-Login header → identity
│ │ ─ users.json lookup → role + module_scope
│ │ ─ endpoint role checks
└────────────────┘

Jetson FastAPI middleware resolves identity in this order:

  1. Tailscale-User-Login header (set by Tailscale Serve when reached through Tailscale’s HTTPS proxy) — Phase I primary path.
  2. Local cookie session (/auth/local break-glass — see dashboard-api.md).
  3. Reject — 401.

Auth0 JWT validation on the Jetson is not wired in Phase I. The Worker-validated-JWT → X-LBZF-Identity header flow is preserved in 60-parking/cloudflare-tunnel-from-jetson.md for Phase II.

The static Astro app reads role from the Auth0 access token’s https://lbzfai.com/role custom claim (see user-org-and-auth.md) and renders one of:

  • /app/admin (Sophia, Andrew) — admin home.
  • /app/ingeniero (Ronald) — landing page with “Abrir tablero (Tailscale)” link to the Jetson.
  • /app/ejecutivo (Mariana) — placeholder dashboard with mocked aggregates in Phase I; Phase II wires the Worker proxy from the parked design and renders real numbers.
  • /app/investigacion (parked, see 60-parking/full-role-matrix.md).
  • /app/cuenta — fallback for users with no assigned role.

No /api/* fetch from the browser to a Worker in Phase I. The Worker’s role today is purely to gate the static pages by role claim.

FailureBehavior
Tailscale partitioned (user can’t reach Jetson)lbzfai.com still loads; “Open dashboard” link fails until Tailscale reconnects. UI shows a “Sin conexión a la planta” banner per localization-es-co.md.
Auth0 downLogin fails on lbzfai.com; users already on Tailscale can still hit the Jetson directly with the local-auth break-glass route.
Jetson downBoth surfaces show “factory offline.”
Cloudflare Workers downlbzfai.com itself goes down (acceptable; uptime is very high).
User on cellular without TailscaleCannot reach the Jetson. lbzfai.com loads but Ronald/Mariana sees a “Install Tailscale to view live data” instruction page. Phase II removes this constraint via the parked Worker proxy.
  • Cloudflare Workers Static Assets: free tier covers Phase I traffic.
  • Tailscale paid Starter tier needed by 2026-05-15: ~$6/user/mo × ~9 users ≈ $45/mo. Free tier blocks at 3 users.
  • Auth0: free dev tenant covers <7,000 MAU.
  • No outbound proxy infrastructure: $0.

Total: ~$45/mo for the integration layer in Phase I (the Tailscale paid tier per ADR-005).

Migration path to Phase II (Worker proxy via Cloudflare Tunnel)

Section titled “Migration path to Phase II (Worker proxy via Cloudflare Tunnel)”

Preserved verbatim in docs/design/60-parking/cloudflare-tunnel-from-jetson.md. Resume that doc when Mariana refuses Tailscale or a non-Tailscale user joins the project.

  • Cloudflare Tunnel + Worker proxy — the round-1 default; parked per ADR-005. See above.
  • Fly.io / EC2 Tailscale-egress box proxying for the Worker — equivalent shape to the parked outbound-tunnel design, slightly more ops; same Phase I non-need.
  • Direct Worker→Jetson with a public Tailscale Funnel URL — exposes the Jetson; rejected.
  • NGINX on the Jetson as the public ingress — requires opening a port through LBZF’s NAT; rejected.
  • Skip lbzfai.com entirely; ship a desktop app — fails Andrew’s “full prod stack day 1” framing.
  • OPEN: Tailscale Serve / Funnel plan tier confirmation — Sophia must confirm the paid Starter tier supports identity-header injection. Owner: Sophia, target: 2026-05-13 (before BA handoff).
  • OPEN: How does Mariana access the dashboard the first time? lbzfai.com → Auth0 invite email → role granted via PR → install Tailscale → “Open dashboard”. Need an onboarding doc. Owner: Sophia + Armando.
  • OPEN: Can ITBA’s twin Jetson share lbzfai.com? Yes — same Cloudflare Worker, but the “Open dashboard” link reads from the user’s https://lbzfai.com/org_id claim and routes to the right Tailscale node. Confirm wiring before 2026-05-15. Owner: Andrew + ITBA.
  • OPEN: What’s the SLO? “Available during LBZF working hours (6am–6pm CO, Mon–Fri).” Owner: Sophia / Andrew.
This doc depends onOwner bucketWhat we need
Auth0 custom-claim ActionThis bucket (user-org-and-auth.md)JWT contains role / org_id / module_scope under https://lbzfai.com/… namespace
Dashboard API on JetsonThis bucket (dashboard-api.md)Endpoints exist; middleware reads Tailscale-User-Login header
Tailscale set up on JetsonHardware (Agent A) + ADR-005/006Already locked
This doc impliesOwnerAsk
Frontend role-aware Astro pages without any /api/* proxy in Phase IAgent CPlumb the JWT role claim only
Tailscale install runbook for Mariana / Ronald / ITBASophia + ArmandoPhase I prerequisite
  1. The “Install Tailscale” gate excludes anyone unwilling to install client software. Mariana might object; if she does, ADR-005 gets re-opened and the parked Worker-proxy design comes back.
  2. No fallback when Cloudflare itself is degraded. lbzfai.com goes down; users on Tailscale can still hit the Jetson directly though, which is a nice property of this architecture.
  3. The lbzfai.com role-aware UI shows aggregates that aren’t real in Phase I (/app/ejecutivo is mocked). Mariana opens the page and sees fake numbers labeled clearly as such. Round-2 critique flagged this; the Phase II Worker proxy is what fills in real data.
  4. Identity on the Jetson relies entirely on Tailscale’s identity-header injection. If Tailscale’s Serve mode misconfigures or downgrades that feature, the break-glass /auth/local is the only fallback.
  • Now (May 2026): Auth0 custom claims live; Astro pages render role-aware shells; Tailscale paid tier upgrade by 2026-05-15.
  • Before Argentina (2026-05-15): end-to-end Tailscale demo: Sophia logs in at lbzfai.com → sees admin role → clicks “Open dashboard” → reaches Jetson over Tailscale.
  • Before Pereira (Jul 2026): Ronald, Mariana, ITBA all enrolled in the tailnet; tested end-to-end.
  • Day-1 Pereira: documented runbook for “Tailscale is offline; here’s how to check.”
  • Phase II: thaw 60-parking/cloudflare-tunnel-from-jetson.md if Mariana-no-Tailscale becomes a hard requirement.

Unblocks: every “lbzfai.com authenticates users” deliverable; Argentina demo end-to-end.