Skip to content

feat(now-client): add session lock and logoff requests - #123

Merged
Marc-André Moreau (mamoreau-devolutions) merged 4 commits into
masterfrom
claude/now-client-session-api-b07027
Oct 30, 2026
Merged

Marc-André Moreau (mamoreau-devolutions) merged 4 commits into
masterfrom
claude/now-client-session-api-b07027

Conversation

@mamoreau-devolutions

Copy link
Copy Markdown
Contributor

Adds NowClientHandle::session_lock and NowClientHandle::session_logoff, which send NOW_SESSION_LOCK_MSG and NOW_SESSION_LOGOFF_MSG. These let an RDP client lock or log off the interactive user session that hosts the NOW agent. RDP itself can only disconnect, so a client-initiated logoff has to go through NOW.

  • Response: neither message has a response, so both methods complete once the request is written and flushed. A successful logoff ends the session that carries the channel, and the handle then returns WorkerClosed.
  • Capability check: each request requires the matching negotiated session capability (NowCapabilities::supports_session_lock / supports_session_logoff).
    • The worker checks the capability when it writes the request, so a capset refresh from the peer is honored.
    • A request that isn't negotiated fails with NowClientError::UnsupportedCapability and writes nothing. This matches how the exec styles and the .NET client behave.
  • Default config: the default NowClientConfig capset now advertises LOCK | LOGOFF. Callers that build their own client_capset must add these flags themselves.

Tests cover:

  • the exact header-only frames on the wire;
  • the default capset advertisement;
  • a peer omitting a capability;
  • a peer capset refresh withdrawing lock;
  • negotiation requiring both sides;
  • the handle closing after the channel ends.

🤖 Generated with Claude Code

NOW_SESSION_LOCK_MSG and NOW_SESSION_LOGOFF_MSG let a client lock or
end the user session that hosts the NOW agent, which is the only way an
RDP client can log the user off: RDP itself can only disconnect.

`NowClientHandle::session_lock` and `NowClientHandle::session_logoff`
check the negotiated session capability and complete once the request
is written, because neither message has a response.
`NowCapabilities` reports both capabilities, and the default client
capset advertises them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Session lock and logoff requests are header-only PDUs, so the tests now
compare the exact frames on the wire and check that the default client
capset advertises both capabilities. They also cover a peer capset
refresh that withdraws lock: the rejected request writes nothing, and
logoff still goes out. A unit test checks that negotiation keeps a
session capability only when both sides advertise it.

The docs now say that "session" means the interactive logon session,
not a NOW execution session. They also say that success only means the
request was flushed, and that a custom client capset must advertise the
session flags for the requests to be allowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 30, 2026 12:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Capability checks occur before queuing rather than transmission, allowing a request blocked by backpressure to be sent and report success after the peer withdraws the required capability.

1 open issue
What changed in this PR

Adds session lock and logoff requests to the Rust NOW client, allowing RDP clients to request these operating-system actions through the NOW agent.

Changes:

  • Adds asynchronous handle methods that complete after the request is written and flushed.
  • Advertises lock and logoff capabilities by default and adds negotiated capability checks.
  • Documents the API and tests wire frames, capability negotiation, refresh handling, and channel closure.
File Description
protocols/​rust/​now-client/​src/​config.rs Advertises session capabilities by default and documents custom capsets.
protocols/​rust/​now-client/​src/​client.rs Adds session request methods, worker handling, and transport tests.
protocols/​rust/​now-client/​src/​capabilities.rs Adds session capability queries and negotiation tests.
protocols/​rust/​now-client/​README.md Documents session requests, capability requirements, and completion semantics.

Review effort: Balanced

Comment thread protocols/rust/now-client/src/client.rs Resolved
…equest

A session request was checked against the negotiated capset only when
it entered the write queue. While it waited behind a blocked write, a
peer capset refresh could withdraw the capability, and the request was
still sent and reported success.

The worker now rechecks unsent session requests at the head of the
write queue before writing their first byte. Withdrawn requests fail
with `UnsupportedCapability`. A paused-clock test reproduces the
withdrawal behind a blocked Run request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ession-api-b07027

# Conflicts:
#	protocols/rust/now-client/src/capabilities.rs
#	protocols/rust/now-client/src/client.rs
#	protocols/rust/now-client/src/config.rs
@mamoreau-devolutions
Marc-André Moreau (mamoreau-devolutions) merged commit 41ef257 into master Oct 30, 2026
9 checks passed
@mamoreau-devolutions
Marc-André Moreau (mamoreau-devolutions) deleted the claude/now-client-session-api-b07027 branch October 30, 2026 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants