feat(server,agent): v2 secure-session-core Task 5 - attended consent
Some checks failed
Build and Test / Build Server (Linux) (push) Failing after 5m42s
Build and Test / Build Agent (Windows) (push) Successful in 8m22s
Build and Test / Security Audit (push) Successful in 5m12s
Build and Test / Build Summary (push) Has been skipped

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>
This commit is contained in:
2026-05-30 07:44:09 -07:00
parent 8cb0b5b16b
commit 9082e11490
10 changed files with 906 additions and 5 deletions

View File

@@ -294,6 +294,40 @@ enum AdminCommandType {
ADMIN_UPDATE = 2; // Download and install update
}
// ============================================================================
// Attended-mode Consent (Task 5)
// ============================================================================
//
// For an ATTENDED (support-code) session, the end user on the managed machine
// must explicitly accept a consent prompt before the technician's session goes
// live. The server holds the session in `consent_state = pending` and does NOT
// surface it to the technician (no viewer join / no streaming) until the agent
// returns a ConsentResponse with granted = true. A denial or timeout tears the
// session down. Managed/unattended sessions are `not_required` and never see a
// ConsentRequest (Phase-1 default policy).
// Server/relay -> Agent: ask the end user to allow this support session.
message ConsentRequest {
string session_id = 1; // Session awaiting consent (UUID string)
string technician_name = 2; // Display name of the requesting technician
ConsentAccessMode access_mode = 3; // View vs. control, so the prompt is honest
int32 timeout_secs = 4; // How long the agent should wait before auto-deny
}
// Agent -> Server: the end user's decision.
message ConsentResponse {
string session_id = 1; // Echoes the ConsentRequest session_id
bool granted = 2; // true = allow, false = deny (incl. dialog closed)
string reason = 3; // Optional human-readable reason (e.g. "timeout")
}
// Whether the technician is requesting view-only or full control. Mirrors the
// viewer access mode the server already enforces; used only to phrase the prompt.
enum ConsentAccessMode {
CONSENT_VIEW = 0; // Technician will VIEW the screen
CONSENT_CONTROL = 1; // Technician will VIEW and CONTROL
}
// ============================================================================
// Auto-Update Messages
// ============================================================================
@@ -374,5 +408,9 @@ message Message {
// Auto-update messages
UpdateInfo update_info = 75; // Server -> Agent: update available
UpdateStatus update_status = 76; // Agent -> Server: update progress
// Attended-mode consent (Task 5)
ConsentRequest consent_request = 80; // Server/relay -> Agent: prompt end user
ConsentResponse consent_response = 81; // Agent -> Server: end user's decision
}
}