Add BEE-ACCESS-PLAN.md — full access + liberation plan

This commit is contained in:
Kayos 2026-03-22 01:53:42 -07:00
parent 2455241345
commit a67247df68

267
BEE-ACCESS-PLAN.md Normal file
View file

@ -0,0 +1,267 @@
# Truck Bee Access Plan
_Updated 2026-03-22 — read this before touching the Bee_
---
## Step 1 — Get Clean Access
**Physical requirement:** Be near the truck with your phone.
### 1a. Connect before zerocool does
Boot the Bee and **immediately** connect your phone to `dashcam-4A928016A02C1046` before it associates with zerocool. If zerocool connects first, we get routing hell again.
### 1b. Set up reverse tunnel correctly
From the Bee (via your phone SSH session on the AP):
```bash
ssh -R 2222:192.168.0.10:22 -N -o StrictHostKeyChecking=no root@192.168.0.5 &
```
> **Critical:** must be `192.168.0.10:22` not `localhost:22` — sshd only binds to the AP interface.
**Auth question to resolve:** What key does the Bee use to connect to Lucy? Either:
- Check `/root/.ssh/` on the Bee for existing keys
- Or add the Bee's pubkey to Lucy's `authorized_keys` during this session
### 1c. Verify tunnel from OpenClaw
Once tunnel is up, I'll verify with:
```bash
# Lucy should show port 2222 listening
ss -tlnp | grep 2222
```
Then I connect via `127.0.0.1:2222` on Lucy.
### 1d. Optional: disconnect Bee from zerocool
To avoid routing conflict entirely, kill the WiFi client connection while we work:
```bash
ip link set wlp1s0f1 down
```
Re-enable after: `ip link set wlp1s0f1 up`
---
## Step 2 — Read-Only Recon (NO WRITES)
Once I'm in via the tunnel, I run these in order. Read only.
### 2a. Storage inventory
```bash
df -h
du -sh /data/recording/*/
ls -la /data/recording/ml_metadata/ | head -20
ls -la /data/recording/unprocessed_framekm/ | head -5
sqlite3 /data/odc-api.db ".schema"
sqlite3 /data/odc-api.db "SELECT COUNT(*) FROM framekms;"
sqlite3 /data/odc-api.db "SELECT * FROM framekms LIMIT 3;"
```
**Goal:** Understand how much data is stored and in what state.
### 2b. Redis key scan (live detections)
```bash
redis-cli keys "*"
redis-cli type GNSSFusion30Hz
redis-cli zrevrange GNSSFusion30Hz 0 2
# Look for detection/landmark keys map-ai publishes to:
redis-cli keys "*landmark*"
redis-cli keys "*detection*"
redis-cli keys "*sign*"
redis-cli keys "*map*"
```
**Goal:** Find the exact Redis key(s) map-ai writes detections to.
### 2c. Read odc-api source — find detection key
```bash
grep -i "landmark\|detection\|redis\|publish\|set\|zadd" /opt/odc-api/odc-api-bee.js | head -50
```
**Goal:** Confirm exactly how odc-api reads detections from Redis so we know what key to poll.
### 2d. Read map-ai source — confirm write pattern
```bash
grep -i "redis\|set\|zadd\|publish\|landmark\|detection" /opt/map-ai/map-ai.py | head -50
# Also check if there's a compiled version or if it's pure Python:
ls /opt/map-ai/
```
**Goal:** Confirm what Redis key map-ai writes detections to after inference.
### 2e. Check ml_metadata contents
```bash
ls -la /data/recording/ml_metadata/ | tail -20
# Look at a sample file:
cat $(ls /data/recording/ml_metadata/ | head -1)
```
**Goal:** Understand if detection metadata is also written to disk files (backup to Redis).
### 2f. Check frame storage
```bash
ls /tmp/recording/pics/ | head -5
ls /tmp/recording/pics/ | wc -l
# Filename format:
ls /tmp/recording/pics/ | head -1
```
**Goal:** Confirm frame filename format for detection-to-image correlation.
### 2g. Check existing SSH keys on Bee
```bash
ls -la /home/root/.ssh/ 2>/dev/null || ls -la /root/.ssh/ 2>/dev/null
cat /root/.ssh/authorized_keys 2>/dev/null
ls /root/.ssh/id_* 2>/dev/null
```
**Goal:** Know what keys exist for tunnel auth and for our post-liberation access.
### 2h. Check service file for map-ai dependency
```bash
cat /lib/systemd/system/map-ai.service 2>/dev/null || \
systemctl cat map-ai.service
```
**Goal:** Confirm the `Requires=odc-api.service` line so we know what to override in the drop-in.
---
## Step 3 — Decisions Based on Recon
After recon, we decide:
### 3a. Detection key confirmed?
- **Yes:** Write forwarder to poll that Redis key directly
- **No Redis key found:** Use ml_metadata files OR keep polling odc-api endpoints (low frequency, not localhost)
### 3b. ml_metadata has useful files?
- **Yes:** Primary source for detections — tail by mtime, parse directly
- **No:** Redis is the only path
### 3c. How much data is stored?
- Estimate backfill time/volume to ADAMaps
- Decide if we do a one-time backfill before liberation or after
---
## Step 4 — Liberation Plan (v0.6)
Based on recon findings, update `liberate-v0.5.sh` to `v0.6`:
### Kill list (services to stop + disable)
```
hivemapper-data-logger ← the uploader, MUST kill
mitmproxy ← Hivemapper proxy, MUST kill
beekeeper-plugin ← Hivemapper telemetry/HW comms, kill
here-plugin ← HERE Maps integration, kill
mender-client ← OTA update client, kill (recovery via USB still works)
odc-api ← Node.js REST layer, kill (we read from Redis/files directly)
lte.service ← Kill LTE upload path (no SIM = irrelevant, but block anyway)
```
### Keep list (services that stay running)
```
redis ← IPC backbone, keep
depthai_gate ← Camera hardware init, keep
map-ai ← ML inference (sign detection), keep ← THIS IS THE VALUE
jpeg-recorder ← Frame storage, keep
video-processor ← Frame pipeline, keep
RedisHandler ← Sensor fusion, keep
datalogger ← GPS/IMU logging, keep
hostapd ← AP, keep (how we connect)
dnsmasq ← DHCP on AP, keep
```
### New service to install: adacam-forwarder (rewritten)
Lightweight Python service that:
1. Polls the detection Redis key (found in step 2b/2c) for new entries since last ID
2. Grabs corresponding JPEG from `/tmp/recording/pics/` by timestamp match
3. POSTs to ADAMaps `/api/ingest` with correct payload:
```json
{
"device_id": "bee-{SERIAL}",
"detections": [{
"ts": 1709920000000,
"lat": 34.05357,
"lon": -118.24545,
"class_label": "speed_limit_35",
"overall_confidence": 0.88
}]
}
```
4. Uploads image via `POST /api/images` (multipart)
5. Tracks last processed ID in `/data/adacam/forwarder-state.json`
6. Runs every 30s — low overhead, no Node.js
### systemd drop-in for map-ai (removes odc-api dep)
```ini
# /etc/systemd/system/map-ai.service.d/override.conf
[Unit]
Requires=redis.service
# Remove: Requires=odc-api.service
```
### SSH key installation
Drop OpenClaw pubkey to `/root/.ssh/authorized_keys`:
```
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOQxwJU91TCxds34P18D3xRbu7rxlrgTUoml/H8nxeDK kayos@openclaw
```
### Domain blocks (append to /etc/hosts)
```
0.0.0.0 data.api.hivemapper.com
0.0.0.0 api.hivemapper.com
0.0.0.0 edge.hereapi.com
0.0.0.0 direct.data.api.platform.here.com
0.0.0.0 account.api.here.com
0.0.0.0 mender.io
```
### What we do NOT touch
- `/etc/ssh/sshd_config` — no changes, password auth stays
- AP config (`/var/hostapd.conf`) — no changes
- IP (`192.168.0.10`) — stays forever
- Firewall — no changes yet
---
## Step 5 — Test Before Commit
Before calling liberation complete:
1. Verify `map-ai` still starts and `MAP_AI_READY` appears in Redis
2. Verify our forwarder receives detections and posts successfully to ADAMaps
3. Verify `depthai-device-kb` process still spawns (ML inference running)
4. Check `/data/adacam/forwarder-state.json` updating
5. Confirm no Hivemapper upload traffic (check hosts block is working)
---
## Step 6 — Build bee-tunnel.service (permanent tunnel)
After liberation, install a persistent reverse tunnel service so we never need physical access again:
```ini
[Unit]
Description=AdaCam Reverse Tunnel to Lucy
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/ssh -N -R 2222:192.168.0.10:22 \
-o StrictHostKeyChecking=no \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes \
root@192.168.0.5
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target
```
---
## Known Issues / Gotchas
| Issue | Notes |
|-------|-------|
| sshd binds to `192.168.0.10` only | Never use `localhost:22` in tunnel |
| depthai-device-kb runs at 98% CPU | Normal — that's the VPU doing ML inference |
| rngd at 20% CPU | Suspicious — investigate if it's needed |
| Redis is localhost:6379 only | Need to be on Bee to query it |
| GNSSFusion30Hz not in recon redis-keys | Recon was only 5min post-boot — key appears later |
| map-ai Requires=odc-api in systemd | Must add drop-in override before killing odc-api |
| ml_metadata limited to 20MB | Small — Redis is likely primary detection source |
| Lots of unprocessed data on disk | Backfill to ADAMaps before or after liberation TBD |