Skip to content

feat(control): dig-node control-panel surface — WS status, cache-LRU, token pairing#16

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
feat/278-control-panel-surface
Jul 10, 2026
Merged

feat(control): dig-node control-panel surface — WS status, cache-LRU, token pairing#16
MichaelTaylor3d merged 1 commit into
mainfrom
feat/278-control-panel-surface

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

TLDR

One coordinated 9778 browser-surface release for the extension control-panel epic (#278): the WebSocket live-status channel (#239), the full OPEN cache-LRU management surface (#279), and control-token PAIRING so the MV3 extension can drive control.* mutations (#280). Additive-only; released-first so the extension consumes it next.

What changed

  • #239 — GET /ws/status WebSocket (prior-lane work, completed here): status snapshot on connect, then a heartbeat (refreshed snapshot + ts) every ~5s plus a transport ping; 20s half-open timeout closes a dead socket; Origin validated against the same local allowlist CORS reflects (CSWSH defense); shares status_fields with /health so the two can't drift.
  • #279 — cache-LRU management (OPEN cache.*): cache.listCached entries gain lru_rank (0 = least-recently-used = next evicted; strict 0..n order). New cache.stats{ cap_bytes, used_bytes, entry_count, total_bytes, evicted_count, evicted_bytes, content_cache:{hits,misses} } (session counters). cache.setCapBytes reserved-cap floor (64 MiB), getConfig/removeCached/clear unchanged.
  • #280 — control-token pairing: OPEN pairing.request/pairing.poll (an MV3 extension can't read the token file) + MASTER-gated control.pairing.list/approve/revoke; a scoped, revocable paired-token store (<config_dir>/paired-tokens.json, owner-only, atomic); the auth gate accepts the master token OR a valid paired token, except pairing-admin methods (master only). New dig-node pair CLI (compare-codes consent). Unpaired callers stay -32030.

How verified (this session)

  • cargo test -p dig-node-service -p dig-node-core — all green, incl. the WS integration tests (snapshot/heartbeat/clean-close/origin), the new cache lru_rank + cache.stats tests, the 6 pairing unit tests, the end-to-end pairing_flow_grants_then_revokes_a_scoped_control_token HTTP test (unpaired→-32030, request→approve→poll→authorized mutation→paired-token-can't-admin→revoke→-32030), and the openrpc drift guard (cache.stats catalogued + resolved).
  • cargo fmt --all -- --check clean; cargo clippy --all-targets --all-features -- -D warnings clean; cargo build --locked OK.
  • CLI smoke: dig-node pair --help lists list/approve/revoke; dig-node pair list --json (no node) emits a clean IO_ERROR envelope.

Bump rationale

featminor: 0.11.1 → 0.12.0. New additive endpoints/fields/methods; no removed or repurposed API, no wire/format break (§5.1 additive-only — older readers ignore the new fields).

Blast radius (gitnexus + survey)

  • Dispatch: server.rs::rpc (new OPEN pairing.* branch before the control gate; gate extended for paired tokens), control.rs::dispatch_control (+control.pairing.*), dig_node_core::handle_rpc (+cache.stats, lru_rank). AppState/ControlCtx gain a shared PendingPairings.
  • New modules pairing.rs (state + store + open/admin dispatch) and pair.rs (CLI client). Catalogue: 5 new methods in meta::methods() (drift guard green).
  • No change to existing method names/shapes/error codes; existing consumers (extension control.status, DIG Browser cache FFI) unaffected.

SYSTEM.md deltas for the orchestrator (do NOT edit superproject here)

The "dig-node control interface" contract gains, on the 9778 browser surface:

  1. WS GET /ws/status (OPEN; snapshot + heartbeat; open socket = liveness).
  2. cache. additions* (OPEN): cache.listCached per-entry lru_rank; new cache.stats.
  3. Pairing: OPEN pairing.request/pairing.poll + gated control.pairing.list/approve/revoke; the gate now accepts a paired token (scoped, revocable; <config_dir>/paired-tokens.json) beside the master token, except for pairing-admin methods. This changes the prior "an MV3 extension CANNOT drive control.* mutations" statement — it now can, after consented pairing.

Refs #278. Closes #239, #279, #280.

… token pairing

Coordinated 9778 browser-surface release for the extension control-panel epic:

- #239 WebSocket status/liveness channel `GET /ws/status` (status snapshot on
  connect + 5s heartbeat + WS ping; 20s half-open timeout; CSWSH Origin
  allowlist; shared status_fields with /health).
- #279 cache-LRU management over the OPEN cache.* family: per-entry `lru_rank`
  on cache.listCached (0 = next evicted), and a new `cache.stats` (cap/used,
  entry_count, total_bytes, session evicted_count/bytes, content-cache
  hits/misses).
- #280 control-token pairing so an MV3 extension can drive control.* mutations
  without reading the token file: OPEN pairing.request/poll + MASTER-gated
  control.pairing.list/approve/revoke, a scoped + revocable paired-token store,
  and a `dig-node pair` CLI approve step (compare-codes consent). Unpaired
  callers stay -32030; a paired token cannot administer pairings.

All additive-only (§5.1). SPEC.md updated (§4.5 WS, §7.2 auth, §7.10 cache,
§7.11 pairing). Version bumped 0.11.1 -> 0.12.0 (feat -> minor).

Closes #239
Closes #279
Closes #280
Refs #278
@MichaelTaylor3d MichaelTaylor3d force-pushed the feat/278-control-panel-surface branch from eaaa87b to e745e72 Compare July 10, 2026 20:52
@MichaelTaylor3d MichaelTaylor3d merged commit ce25911 into main Jul 10, 2026
9 checks passed
@MichaelTaylor3d MichaelTaylor3d deleted the feat/278-control-panel-surface branch July 10, 2026 20:59
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.

1 participant