# TICKET → Camera session lane — Cameras down (502), separate from the VM lane

**Filed:** Thursday, June 25, 2026 · 📈 MIS session (diagnosed, NOT in MIS court).
**Owner:** the **Camera session** (Sam reassigned the camera fix fully to that lane, Jun 25 — it's OFF Brain's deploy bundle). Brain only sets `CAM_CF_*` if the camera session asks for that one value. **Note:** the master→ops-api clobber is fixed (build path-scoped); routes are back. Remaining = the two checks below.
**Symptom:** camera feed not loading on the portal (Sam confirms still broken). Was also listed "broken (camera tile)" in the 2026-06-25 handoff, i.e. pre-existing — not solely today's clobber.

## Verified (read-only, 📈 MIS, Jun 25 ~2:15 PM ET)
- ✅ `ops-api /camera/snapshot` route is **alive** — bare hit returns 401 (referer gate); the portal supplies the referer, so this gate is NOT the problem.
- ✅ `cam.hookstreetservices.com` tunnel host is **alive + reachable** — DNS 0.01s, 302 → Cloudflare Access login (`hookstreet.cloudflareaccess.com`), exactly as designed.
- Chain (per `ops-api/src/index.ts:635-668`): `cameras.html <img>` → `/camera/snapshot` → Worker fetches `cam.hookstreetservices.com/api/frame.jpeg?src=camN` with `CF-Access-Client-Id: CAM_CF_ID` + `CF-Access-Client-Secret: CAM_CF_SECRET` → returns JPEG, else **502 `camera_unreachable`**.

## The break is in ONE of two links (both → same 502) — check in this order
1. **CAM_CF_ID / CAM_CF_SECRET stranded on the ops-api Worker.** These are 2 of the ~30 secrets the bad deploys wipe (the reason ops-api is frozen on `8523bfaf`); multiple clobbering deploys ran today. If empty → Worker sends blank Access headers → cam.* bounces it → 502.
   - **Check:** `wrangler secret list` (or CF dashboard) on ops-api → confirm `CAM_CF_ID` + `CAM_CF_SECRET` present. If missing → re-add (values from the secret store, NOT git/chat).
2. **go2rtc bridge / cloudflared down on Sam's home PC.** The tunnel's origin is go2rtc on the PC. PC asleep/off or process dead → 502.
   - **Check (Sam):** PC awake + go2rtc process running.

## Recommended durable fix (Brain's call)
- **Deploy guard:** declare the required camera secrets so a deploy **fails or alerts** if `CAM_CF_ID`/`CAM_CF_SECRET` are missing post-deploy (Cloudflare Workers supports declaring required vars/secrets in Wrangler config + a post-deploy presence assert). Stops silent secret-stranding.
- **Root cause above that:** separate the **portal deploy from the ops-api Worker** so a `git push` to master stops clobbering ops-api at all (the real bug). Until then, push freeze stands.
- **Un-tie from the PC:** move the go2rtc bridge to an always-on **home box** (mini-PC/Pi) so cameras survive the PC being off (separate from the cloud-VM, which can't reach the LAN).

## ✅ ACCEPTANCE TEST (not "fixed" until all 5 pass)
1. PC awake.
2. go2rtc process confirmed running.
3. ops-api Worker has `CAM_CF_ID` + `CAM_CF_SECRET` set.
4. Worker successfully reaches the tunnel origin (no 502).
5. Feed loads on phone **off Wi-Fi** (cellular).

## ✅ ACCEPTANCE RUN — Camera session, 2026-06-25 ~PM ET (Sam reassigned to me)
1. **PC awake** — ✅.
2. **go2rtc + cloudflared running** — ✅ both up (`tasklist`: go2rtc.exe PID 33124, cloudflared.exe PID 32608). (They WERE the break — go2rtc isn't a persistent service, so a reboot kills it → 502. See durability note.)
3. **CAM_CF_ID + CAM_CF_SECRET set** — ✅ FUNCTIONALLY (cameras render, so the Worker has + uses them). ⚠️ **GOTCHA: `wrangler secret list` reports 0 secrets** for this worker — DO NOT trust it. The live version (rolled-forward via CF-API, not wrangler) holds all secrets; wrangler's local view is blind to them. The reliable check is a live `/camera/snapshot` hit, not `secret list`.
4. **Worker reaches tunnel, no 502** — ✅ `/camera/snapshot?cam=1..8` → **7/8 return real JPEGs** (12–42KB). cam4 = 502 (the long-known physically-disconnected camera, not a system fault).
5. **Feed on phone OFF Wi-Fi (cellular)** — ⏳ **SAM TO VERIFY** (I can't test the external/cellular path). This is the last gate.

**STATUS: 5/5 PASSED briefly (Sam confirmed on cellular ✅) — then RE-BROKE within ~10 min.**

### 🔴 RE-BREAK 2026-06-25 (camera session) — NOT a camera fault, it's ops-api CAM_CF stranded AGAIN
Pinpointed across the chain: **go2rtc local = 200 JPEG ✅ · tunnel host = 302 ✅ · ops-api `/camera/snapshot` = 502 `camera_unreachable` ❌.** So go2rtc + cloudflared are fine; the ONLY break is the Worker sending blank Access headers = **`CAM_CF_ID`/`CAM_CF_SECRET` stranded by a fresh clobber.** → **BRAIN/ops-api lane:** re-add CAM_CF to the live version AND add a post-deploy guard that re-asserts CAM_CF (else every master push re-502s the cameras). Camera session will NOT set ops-api secrets (the stranding minefield). **Root recurrence = the build-clobber is NOT fully fixed.** The CAM_CF service-token values exist (camera session has them / can regenerate) — Brain to pull from secret store, not git/chat.
**DURABILITY (still open):** the feed is PC-tied — go2rtc died on the last reboot = the root of this 502. Interim fix I can do now: make go2rtc auto-start on this PC (Task Scheduler) so a reboot doesn't kill it while the PC's on. Full fix: the always-on home box (survives PC-off).

*Source: 📈 MIS session 2026-06-25, evidence-based diagnosis. Local file, not pushed (push freeze). `outputs/2026-06-25_ticket_cameras-brain-infra.md`.*
