SPEC-002 Phase 1 Task 7 (the last), code-reviewed APPROVED, locally verified
(cargo fmt + clippy -D warnings exit 0 + cargo test --workspace 89 pass + build).
- Encoder trait + factory: RawEncoder (salvaged, UNCHANGED) and H264Encoder,
selected by negotiation; factory falls back to raw on H.264 init failure.
- Negotiation: agent advertises supports_h264 (MFTEnumEx HW probe, cached) in
AgentStatus; server picks the codec via select_video_codec(supports, prefer)
and stamps StartStream.video_codec; agent re-guards on local HW. Policy
constant DEFAULT_PREFER_H264 = false, so RAW is negotiated for every session
today - H.264 stays dormant until live hardware validation (Task 8).
- MF H.264 encoder (h264.rs, FIRST-CUT / compile-verified-only): HW encoder MFT,
BGRA->NV12 (color.rs, unit-tested), sync drain, fall-back-to-raw on any failure.
- Viewer H.264 decoder (decoder.rs, FIRST-CUT): MF decoder on a dedicated COM
thread; drops+logs on failure, raw render path untouched.
- proto additive: VideoCodec enum, StartStream.video_codec=3,
SessionResponse.video_codec=5, AgentStatus.supports_h264=11.
- Raw+Zstd path byte-for-byte unchanged; remains the guaranteed default/fallback.
Review confirmed unsafe impl Send for H264Encoder is sound (single-owned &mut on
the block_on thread; session future never spawned) and every MF failure degrades
to raw. H.264 is NOT claimed functional - compile/clippy/build-verified only;
live validation + force-IDR + the no-spawn-invariant doc are Task 8 go-live gates.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SPEC-002 Phase 1 Task 6, code-reviewed APPROVED (2 rounds), locally verified
(cargo fmt + clippy -D warnings exit 0 + cargo test --workspace 70 pass + build).
- Viewer WH_KEYBOARD_LL hook diverts system combos (Win/Win+R, Alt+Tab, Alt+Esc,
Ctrl+Esc) to the remote as a full KeyEvent (vk + scan + is_extended + modifiers)
and suppresses local handling - GATED on the viewer window having focus AND a
"send system keys" toggle (default on; Pause/Break host-key), so it never bricks
the technician's local keyboard when unfocused.
- Agent injection via SendInput KEYEVENTF_SCANCODE + correct KEYEVENTF_EXTENDEDKEY
(right Ctrl/Alt, arrows, nav, Win, NumLock, numpad Divide) - layout-independent,
extended-key-correct.
- Ctrl+Alt+Del completes through the SAS helper (SYSTEM SendSAS); installer sets
the SoftwareSASGeneration policy; 3-tier fail-loud (no false success). SAS named
pipe DACL tightened from NULL/Everyone to Authenticated Users.
- Modifier hygiene: viewer emits key-ups for held Ctrl/Alt/Shift/Win on focus loss
/ close so modifiers never stick on the remote.
- proto: KeyEvent.is_extended = 7 (additive; older agents derive the flag).
Closes Win+R / Ctrl+C-V / Ctrl+Alt+Del / arrows-vs-numpad fidelity. Live on-device
testing is plan Task 8.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SPEC-002 Phase 1 Task 5, code-reviewed APPROVED. An attended (support-code)
session is invisible and inert to the technician until the end user accepts a
consent prompt on their own machine.
- proto: ConsentRequest / ConsentResponse + ConsentAccessMode enum (oneof
fields 80/81; no existing field renumbered).
- server: ConsentState on Session; attended -> Pending, managed -> NotRequired;
join_session refuses viewers unless Granted/NotRequired (single chokepoint -
StartStream only fires from join_session, so no frames or input flow pre-
consent); run_consent_handshake sends ConsentRequest, 60s timeout, granted ->
proceed, denied/timeout/disconnect -> teardown (end_session denied, machine
offline, support code released). consent_state persisted; consent_requested/
granted/denied audited.
- agent: Windows MessageBox (topmost/system-modal) on spawn_blocking; anything
but an explicit Yes = deny; non-Windows build is a fail-closed stub.
Not cargo-check-verified locally (no toolchain). Server verified on the build
host; the Windows agent half is verified by CI build-agent (Pluto).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Added organization, site, tags columns to connect_machines table
- Agent now sends org/site/tags from embedded config in AgentStatus
- Server stores org/site/tags metadata in database
- Enables grouping machines by client/site/tag in dashboard
Features:
- Agent checks for updates periodically (hourly) during idle
- Admin can trigger immediate updates via dashboard "Update Agent" button
- Silent updates with in-place binary replacement (no reboot required)
- SHA-256 checksum verification before installation
- Semantic version comparison
Server changes:
- New releases table for tracking available versions
- GET /api/version endpoint for agent polling (unauthenticated)
- POST /api/machines/:id/update endpoint for admin push updates
- Release management API (/api/releases CRUD)
- Track agent_version in machine status
Agent changes:
- New update.rs module with download/verify/install/restart logic
- Handle ADMIN_UPDATE WebSocket command for push updates
- --post-update flag for cleanup after successful update
- Periodic update check in idle loop (persistent agents only)
- agent_version included in AgentStatus messages
Dashboard changes:
- Version display in machine detail panel
- "Update Agent" button for each connected machine
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AdminCommand message to protobuf (uninstall, restart, update)
- Add DELETE /api/machines/:agent_id endpoint with options:
- ?uninstall=true - send uninstall command to online agent
- ?export=true - return session history before deletion
- Add GET /api/machines/:agent_id/history endpoint for history export
- Add GET /api/machines endpoint to list all machines
- Handle AdminCommand in agent session handler
- Handle ADMIN_UNINSTALL error in agent main loop to trigger uninstall
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add StartStream/StopStream/AgentStatus messages to protobuf
- Agent now starts in idle mode (heartbeat only, no capture)
- Agent enters streaming mode when viewer connects (StartStream)
- Agent returns to idle when all viewers disconnect (StopStream)
- Server tracks viewer IDs and sends start/stop commands
- Heartbeat mechanism with 90 second timeout detection
- Session API now includes streaming status and agent info
This allows 2000+ agents to connect with minimal bandwidth.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ChatMessage to protobuf definitions
- Server relays chat messages between agent and viewer
- Agent chat module shows messages via MessageBox
- Dashboard chat modal with WebSocket connection
- Simplified protobuf encoder/decoder in JavaScript
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>