# Web Automation Methodology

Use this workflow for an AI-generated dashboard or an HTTP/SSE/WebSocket client.
BMCLI owns hardware acquisition, buffering, DBC decoding, and the Web transport;
the generated project owns presentation and application-specific behavior.

## Discover the live contract

1. Resolve and validate the project bench first.
2. Query `bmcli help web start --format=json` and open the required daemon
   channels with explicit stable `SN/port`, role, timing, and electrical state.
3. Start loopback service with `bmcli web start --listen=127.0.0.1:8080
   --format=json`.
4. Read `/api/v1/capabilities`, `/api/v1/openapi.json`, and
   `/api/v1/operations`. Generate requests from the live OpenAPI document.
5. Treat an operation whose registry metadata says `migrated=false` or
   `http_policy=disabled` as CLI-only. Do not route it through `/execute`.

The v1 Web surface currently covers service discovery, bench/device snapshots,
bounded firmware-check jobs, typed channel list/info/open/config/close and
statistics, database load/list/info/unload, TX tasks, routes, logging, replay,
remote-BMAPI gateway lifecycle, CAN/CAN FD/LIN message send, raw history, SSE,
binary WebSocket, DBC signal plans, latest values, signal history, and signal
SSE. It does not claim HTTP coverage for every CLI command.

## Select the data path

- Use `POST /api/v1/messages` for a bounded send or LIN transaction. Add a
  unique `Idempotency-Key` when retry behavior matters.
- Use `/messages/history?after=<cursor>` for deterministic pagination and
  reconnect. A `409 cursor_expired` means retained history was overwritten.
- Use `/messages/stream?from=now` for ordinary JSON event rates. Persist each SSE
  event ID only after the application accepts the event; reconnect with
  `Last-Event-ID`.
- Use `/messages/ws?from=now` with subprotocol `bmcli.frames.v1` for high-rate raw
  frames. Parse BMF1 with explicit big-endian fields from OpenAPI/reference data;
  never map the bytes to a compiler C struct.
- Create `/signals/plans` for the specific DBC message needed by the UI, then use
  `/signals/latest`, `/signals/history`, or `/signals/stream`. Keep database
  identity/revision visible in engineering diagnostics.
- Use `/channels`, `/databases`, `/tx-tasks`, and `/routes` for their typed
  lifecycle operations. Percent-encode `/` in a channel path selector such as
  `10356%2F0`; keep `10356/0` unchanged in query parameters and JSON bodies.
- Database load accepts only existing files inside the BMCLI project working
  directory. Do not work around that boundary with a custom file proxy.
- Use `/logging`, `/replay`, and `/gateway` for service lifecycle instead of
  constructing CLI text. Logging outputs and replay inputs are confined to the
  project root, including resolved Windows junction and Linux symlink targets.
- Read `/channels/{selector}/stats` and `/metrics` before sizing retention.
  Monitor retained bytes/duration plus each consumer's backlog and pending gap;
  event capacity alone is not a time guarantee.
- Submit `/devices/{selector}/firmware-check` only for a version check and poll
  `/jobs/{job_id}`. Actual firmware transfer remains a local-only,
  device-disruptive CLI operation.
- Send only one hardware setter group per channel PATCH. Treat CAN timing and
  LIN protocol pairs as their documented groups; split other desired-state
  changes into separate idempotent requests.

For a lossless curve, append every unique sequence in order, reject duplicates,
detect gaps, and recover from history before resuming live display. UI refresh
may downsample, but retained engineering data must not silently drop or repeat a
sample.

## Preserve ownership and safety

One RxBroker owner reads each daemon channel. CLI receive, logging, gateway,
raw Web streams, and signal decoding have independent cursors; do not start a
second BMAPI reader in the generated application. Keep the service loopback by
default. A non-loopback listener requires an explicit bearer token,
`--allow-insecure-http`, and network authorization; CORS remains disabled. The
current embedded server is plain HTTP:
the token authenticates but does not encrypt credentials, API payloads, or bus
traffic. Use non-loopback only on a trusted isolated engineering network with a
host firewall, or behind an approved HTTPS reverse proxy. Never present a token
as transport encryption or expose the listener directly to an untrusted network.
The package includes `share/bmcli/packaging/https/configure-nginx.sh`; use a
certificate trusted by the browser and keep BMCLI bound to loopback. Do not use
`--ignore-certificate-errors`, `curl -k`, or a disabled HTTPS-first policy as a
deployment solution.

Sending traffic and creating active decode state require the same reviewed
bench context as direct BMCLI. Do not expose firmware update, device reset, UDS
programming, arbitrary file access, or daemon administration through a custom
browser proxy. Query `web status` for clients/counters and call `web stop` in
cleanup without stopping a daemon that predated the workflow.
