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

@@ -55,6 +55,10 @@ pub struct SessionInfo {
pub uptime_secs: i64,
pub display_count: i32,
pub agent_version: Option<String>,
/// Attended-consent state (Task 5): `not_required` | `pending` | `granted`
/// | `denied`. The dashboard can surface "awaiting consent" for an attended
/// session that has not yet been accepted on the managed machine.
pub consent_state: String,
}
impl From<crate::session::Session> for SessionInfo {
@@ -75,6 +79,7 @@ impl From<crate::session::Session> for SessionInfo {
uptime_secs: s.uptime_secs,
display_count: s.display_count,
agent_version: s.agent_version,
consent_state: s.consent_state.as_db_str().to_string(),
}
}
}