Did you know? A browser can request a WebSocket connection from a service on a different website, and that request can carry browser-managed credentials. The server must therefore decide whether the connection comes from an allowed origin, authenticate the requester where required, and negotiate the exact application protocol before treating messages as commands. The HTTP/1.1 WebSocket opening handshake establishes a protocol upgrade; it does not automatically authorise an AI agent to read data or carry out actions.
A safe implementation verifies the RFC 6455 handshake, binds the origin and authenticated identity to a tenant and permissions, selects only a subprotocol the client offered and the server supports, and rejects unsupported extensions or ambiguous routing. HTTP/2 and HTTP/3 use a different extended-CONNECT bootstrap, so a hard-coded expectation of HTTP/1.1 status 101 can also be wrong. This guide gives real protocol rules, checked numerical cases, errors and repairs for present-day AI-agent systems. Artificial superintelligence remains hypothetical.
Contents
- The core job: authenticate and negotiate before trusting a live channel
- What the HTTP/1.1 opening handshake actually exchanges
- The Sec-WebSocket-Key proof and a checkable RFC test vector
- Origin checks protect browser contexts but are not authentication
- Subprotocol negotiation determines the application language
- Extension and compression negotiation are independent safety decisions
- Authentication, cookies and the lifetime of authority
- Why HTTP/2 and HTTP/3 do not use the same 101 upgrade
- Reverse proxies, host binding and where the decision is enforced
- Numerical case: transport acceptance versus authorised connections
- Ten handshake mistakes and practical repairs
- Changed-context exercise: a browser dashboard becomes a service agent
- Limitations and what a successful handshake cannot prove
- Frequently asked questions about safe WebSocket admission
- Reader pathways and original specifications
- The server’s handshake decision and the client’s verification duty
The core job: authenticate and negotiate before trusting a live channel
AI systems frequently use long-lived bidirectional connections to deliver status, review requests, agent progress or tool results. WebSockets can provide that continuous channel without creating a fresh HTTP request for every individual event. But a durable connection also creates an attractive security boundary: once the service treats the channel as an authenticated conversation, later messages may trigger consequential operations.
A handshake is not the same as a successful business action. A server can accept a WebSocket upgrade while the client remains unauthorised to call a particular tool, access a document or change another user’s state. Authorisation may need to be checked again for each message or operation, especially after the user’s role, account state or approval changes. Treat opening a channel as establishing transport state, not as a lifelong grant.
WebSocket is a protocol with defined frames and messages after the opening negotiation. It is not interchangeable with an arbitrary HTTP streaming response, server-sent events or a long-running REST request. Those alternatives may be more suitable when the information flows only in one direction or when recovery semantics are central. A protocol choice should follow the required interaction, not a marketing claim that real-time is inherently intelligent.
The primary protocol document is RFC 6455, The WebSocket Protocol. This article focuses on opening identity, origin and application-protocol boundaries. A separate live eduKate article, Agent WebSocket Recovery, addresses heartbeats, missing event sequences and resynchronisation after a connection is already established.
The distinction matters for safe deployment. A perfect heartbeat loop cannot repair a handshake that gave an untrusted client access to another user’s event feed. Likewise, a correct origin check cannot prove the assistant received every event after a network interruption. Treat admission, authority and delivery recovery as distinct requirements.
What the HTTP/1.1 opening handshake actually exchanges
Under RFC 6455’s HTTP/1.1 bootstrap, the client begins with an HTTP GET request for a WebSocket resource. It includes an Upgrade request identifying websocket, a Connection header containing Upgrade, Sec-WebSocket-Version set to 13 and a Sec-WebSocket-Key carrying a base64-encoded 16-byte nonce. Browser requests also carry an Origin value indicating their initiating web origin. A client may offer named subprotocols or extensions.
The server checks whether it supports the requested WebSocket version and whether the request is acceptable under its own access policy. If accepted, it returns HTTP 101 Switching Protocols, including Upgrade: websocket, Connection: Upgrade and a Sec-WebSocket-Accept value derived from the client’s key. Successful negotiation then changes how the connection’s bytes are interpreted. Regular HTTP responses are no longer the format of individual WebSocket messages.
A protocol-conformant 101 does not remove the need for TLS, routing rules, user authentication or application-level validation. The server is agreeing to speak WebSocket frames. A client and server can still disagree about the schema or rights associated with those frames unless the application defines and enforces those conditions.
An explicit handshake state machine helps. Start in HTTP_REQUEST_RECEIVED; verify the version and required fields; identify the intended service and allowed origin; authenticate as applicable; negotiate one supported subprotocol and extensions; then transition to WEBSOCKET_OPEN only after a valid reply is constructed. A failed gate ends in a rejection response and must not leave a partially activated message handler behind.
The server should avoid promoting user-controlled paths, hostnames or query strings into privileged tenant identity without verification. A reverse proxy can change the apparent host or TLS termination point, but a forwarding header is not automatically authoritative. Bind the final application state to trusted deployment configuration and authenticated credentials.
The Sec-WebSocket-Key proof and a checkable RFC test vector
Sec-WebSocket-Key is not a user password or API secret. It is a fresh value chosen by the client to support the specific opening-handshake computation. The server concatenates the key string with the fixed RFC 6455 GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, hashes the resulting text with SHA-1 and base64-encodes the digest as Sec-WebSocket-Accept. The mechanism confirms the server processed this handshake form; it does not authenticate the human user.
RFC 6455 includes a published example. For the client key dGhlIHNhbXBsZSBub25jZQ==, the correct Sec-WebSocket-Accept value is s3pPLMBiTxaQ9kYGzzhZRbK+xOo=. A test should reject a response whose value does not match the computed result. The fixed GUID and the operation are part of the protocol; inventing a different GUID or decoding the input key before concatenation would produce an incompatible result.
The key decodes to 16 bytes in the required client handshake. Yet the response’s SHA-1 operation must not be mistaken for a cryptographic proof of the server’s identity or an access-control token. Server authentication for wss:// comes from the TLS connection and its certificate validation, with additional application credentials if required. The handshake hash solves a different protocol-interoperability problem.
Do not log authentication tokens while debugging the handshake or copy raw sensitive cookies into training data. The WebSocket key itself has a defined nonce function, but surrounding request headers can carry private account information. A diagnostic should be sufficient to confirm header presence, algorithm result and response status without collecting unnecessary secrets.
A failing Sec-WebSocket-Accept comparison is a transport failure, not a hint to skip verification and proceed anyway. The correct client action is to fail the WebSocket connection according to the specification. A fallback that silently accepts an unexpected response would undermine the safety boundary the handshake was designed to establish.
Origin checks protect browser contexts but are not authentication
WebSocket connections initiated by browsers can send cookies or other browser-managed credentials with the opening request, subject to normal browser and cookie rules. Unlike many fetch APIs, opening a WebSocket is not protected by a general automatic same-origin restriction that guarantees the server will reject a foreign site. The server must explicitly decide which origins may use its authenticated WebSocket endpoint.
The Origin header identifies the browser security origin that initiated a browser WebSocket request. A service should compare it with an explicit allowlist of intended origins, after correctly parsing scheme, hostname and port. Substring checks such as permitting any origin containing the word example can be exploited by similarly named attacker domains. Scheme and port can matter, and wildcard allowances should be justified carefully.
Origin is not a reliable credential from arbitrary non-browser clients. A script, command-line tool or agent can construct an Origin header with almost any value. A valid origin is therefore only one admission condition. The server still needs strong authentication and per-operation authorisation when private data or consequential actions are involved. This distinction avoids treating a browser-derived defensive signal as an identity certificate.
Consider a support portal whose legitimate frontend is https://support.example.org and whose WebSocket endpoint is wss://events.example.org. An allowlist entry for https://support.example.org is meaningful because that is the browser origin. An allowance for every subdomain of example.org may be too broad if unrelated applications or less-trusted tenants share the zone. Evaluate trust boundaries, not just naming convenience.
When the intended API supports automated non-browser agents, decide how those clients authenticate and whether Origin is required, absent or treated as an additional signal under that policy. Do not bypass origin protection for browser clients merely because some legitimate software does not send Origin. Different client classes may require different accepted authentication paths, explicitly selected and logged.
A CSRF-like cross-site WebSocket hijacking risk arises when a malicious webpage can start an authenticated WebSocket that the server treats as the user’s trusted conversation. The repair is layered: deliberate origin admission, correct cookie policy, authentication, authorisation and no implicit elevation of unsolicited messages.
Subprotocol negotiation determines the application language
The Sec-WebSocket-Protocol header lets a client offer named application subprotocols. A server can choose one it supports from among those offered. For example, a dashboard might advertise status.v2, while a legacy client offers status.v1 and status.v2 in preference order. The server should select only an actually supported mutually offered value, or decline that application protocol when no safe agreement exists.
RFC 6455 requires clients to reject a server response that announces a subprotocol not offered by the client. This prevents the server from unilaterally changing the meaning of subsequent bytes. Accepting a successful transport upgrade but then guessing the message schema can cause commands to be interpreted in the wrong version, especially when field names have changed.
An AI-agent event stream needs a documented message grammar. A status event, review request and irreversible action request should not all be treated as interchangeable arbitrary strings. If the protocol requires a versioned JSON schema, the handshake can identify the selected protocol while each later message is validated against that schema and the current authorisation state.
Subprotocol names are not bearer credentials. It is tempting to place an access token into a WebSocket subprotocol value because some browser interfaces allow naming protocols but do not allow arbitrary custom request headers. Doing so can expose the token in logs and places intended for protocol negotiation. Prefer a reviewed authentication design appropriate to the application, such as safe cookie or token procedures with explicit access controls.
Fallbacks must be intentional. If the client supports only a v2 protocol with an important authorisation field, silently downgrading it to a v1 grammar that ignores that field can weaken controls. A safe server refuses unsupported versions or obtains an explicit compatible agreement. Protocol negotiation is about meaning, not merely satisfying a string comparison.
Extension and compression negotiation are independent safety decisions
The client may offer WebSocket extensions using Sec-WebSocket-Extensions. The server can accept supported parameters according to the relevant specification but must not announce an extension the client never requested. The client similarly must reject an unrequested extension in the server’s response under RFC 6455’s opening-handshake rules.
An extension can change how frames are interpreted, compressed or processed. Per-message deflate is one common compression mechanism, but its availability and parameter negotiation are separate from whether the application protocol is accepted. A model that understands status.v2 does not automatically understand every framing extension, and vice versa.
Compression introduces operational trade-offs. It can save bandwidth, but it uses CPU and memory and may create side channels when attacker-influenced and sensitive material are compressed together. Apply security analysis to the particular extension and content; turning on compression for all traffic because WebSocket supports extensions would be an unsupported assumption.
Keep negotiation and resource policies visible. A deployment can disable extensions, accept a bounded set with validated parameters, or choose options based on measured workload. Whatever the decision, test both a supported request and an unsupported or malformed offer. If a client claims compression was negotiated when the server did not accept it, the subsequent messages must not be interpreted as if negotiation succeeded.
Treat extension values as protocol inputs requiring parsing and bounds, not as trusted instructions for memory allocation. Very large or malformed frames and decompression amplification are operational risks even after a legitimate handshake. Frame limits, parser safety and application message limits still matter.
Authentication, cookies and the lifetime of authority
The opening handshake may use HTTPS-origin credentials, cookies, a reviewed access-token design or other mechanisms supported by the deployment. The exact choice depends on the browser or non-browser client, threat model and server architecture. A valid WebSocket handshake does not itself assert which user is present; the application must bind the connection to a verified identity before private operations are allowed.
Once a connection is open, an agent may send multiple commands over the same channel. A single authorised connect operation does not guarantee permission for every future action. A user’s role might change, a credential might be revoked or an approval could expire while the connection remains alive. Revalidate sensitive operations against current policy or use a bounded authorisation lease with explicit expiry and revocation handling.
Do not use the origin allowlist as an account database. An allowed origin can host many users, and a compromised or simply unintended page in that origin may attempt a privileged command. The server must verify both which account is connected and whether that account may perform the requested operation in the selected tenant and resource scope.
Consider an agent that streams an answer and later requests permission to write a document. The stream of provisional text and the write action have different consequences. The server may let an authorised user receive progress events but require a fresh consent or capability check before a document update. Message schemas should make the boundary explicit, and the server should not infer approval from the existence of an open socket.
Record enough information to investigate access decisions without exposing bearer credentials. Useful evidence includes verified account and tenant identifiers, selected protocol version, admission outcome, permission-check result and a stable connection ID. Rejected handshakes should not create privileged session objects or misleading success counters.
Why HTTP/2 and HTTP/3 do not use the same 101 upgrade
RFC 6455’s familiar GET and 101 Switching Protocols sequence describes WebSockets over HTTP/1.1. HTTP/2 multiplexes streams and does not use the same connection-wide Upgrade and Connection header fields or status 101 mechanism. A client that assumes every valid WebSocket connection must return 101 will misclassify standards-compliant HTTP/2 connections as failures.
RFC 8441 defines an extended CONNECT mechanism for bootstrapping WebSockets over one HTTP/2 stream. The server advertises support using SETTINGS_ENABLE_CONNECT_PROTOCOL. The request uses the :protocol pseudo-header with value websocket and appropriate HTTP/2 pseudo-headers. It does not send the HTTP/1.1 Connection and Upgrade headers, and the mechanism differs from the Sec-WebSocket-Key and Sec-WebSocket-Accept processing of RFC 6455.
The RFC 9220 mechanism adapts that extended-CONNECT approach to HTTP/3. Platform support and negotiation details depend on client, server and intermediary implementations. This is why it is unsafe to transplant raw HTTP/1.1 handshake bytes into another HTTP version or assume an undocumented downgrade is safe.
The core application policy does not disappear under extended CONNECT. The server must still establish the intended authority, allow the correct origin as applicable, select compatible subprotocols, validate messages and enforce permissions. The transport bootstrap changes, while the security goal remains. Tests should cover the actual HTTP version deployed rather than only a copied HTTP/1.1 example.
A proxy may terminate a WebSocket connection on one HTTP version and establish another upstream. The security design must identify where authentication, origin checks and subprotocol selection occur and how their verified results are transmitted across that trust boundary. An upstream application should not blindly accept an untrusted header declaring that a proxy already checked everything.
Reverse proxies, host binding and where the decision is enforced
Production services often sit behind ingress controllers, load balancers or reverse proxies. A browser may connect through TLS to a public gateway, while the gateway routes to a backend over another internal channel. The request’s external host and protocol can differ from the internal endpoint, which makes host, scheme and origin checks easy to misconfigure.
A defensible deployment documents which component terminates TLS, which chooses a tenant, which validates the WebSocket handshake and which authenticates application identity. If the proxy performs an origin check but the backend can be reached directly from an untrusted network, the check may be bypassed. Restrict backend reachability or make the application enforce its own necessary policy.
Proxy-added forwarding headers may be useful for reconstructing the original public request, but only when they come from trusted infrastructure and are overwritten or sanitised at the boundary. A client that can directly supply a forged Forwarded or X-Forwarded-Host value must not be allowed to choose the authority used for authentication or origin admission.
Subprotocol negotiation can also break across a proxy if request or response headers are removed or rewritten unexpectedly. The application should verify the actual negotiated value seen by both endpoints. A successful TCP or TLS connection to the proxy does not prove the expected WebSocket subprotocol was established at the backend.
Do not assume that an idle timeout or proxy reset represents a valid user logout. A dropped connection is a transport event. If an agent had already issued a write, it may have completed before the socket closed; the safe recovery path needs an operation identifier and independent verification of the result.
Numerical case: transport acceptance versus authorised connections
Take a fictional batch of 120 connection attempts during a planned test. Suppose 12 are rejected because the browser origin is not on the approved list, 8 fail authentication and 5 offer only unsupported subprotocols. Assume these categories are disjoint, so 12+8+5=25 attempts are rejected and 120−25=95 complete the handshake. The transport acceptance rate is 95/120≈79.17%.
Now suppose 15 of the 95 accepted connections request a privileged action later in their lifetime, and 3 of those actions lack the required resource authorisation and are rejected. Under the stated hypothetical observations, the proportion of those privileged requests allowed is 12/15=80%. That is a different denominator and a different security decision from whether the WebSocket was admitted.
If a dashboard counts only successful upgrades, it might claim 95 secure sessions. That wording is too strong. It can truthfully report 95 accepted handshakes, 25 rejections by reason and the separate authorised-action counts. It cannot establish from those figures whether all 95 streams were delivered in order or whether any permitted action actually finished.
Suppose 2 of the 12 approved privileged commands timed out before an acknowledgement. The agent must not assume those two were never executed; a server may have committed the action and lost the response. Recovery needs stable action IDs and readback of application state. Retrying with fresh IDs without reconciliation could duplicate a consequential write.
These numbers are explicitly invented to show how transport, authentication, permission and completion evidence must stay separate. Every percentage has an exact numerator and denominator, and the assumption that rejection reasons are disjoint is stated. Real systems should report their own independently measured values rather than borrowing this illustration.
Ten handshake mistakes and practical repairs
First, treating Sec-WebSocket-Key as a login credential confuses protocol nonce processing with identity. Repair by using a real authentication mechanism. Second, not validating Sec-WebSocket-Accept can admit malformed HTTP/1.1 upgrade responses. Third, accepting a server-selected subprotocol not offered by the client violates negotiation and can change message meaning.
Fourth, allowing arbitrary wildcard origins for credentialed browser connections can facilitate cross-site misuse. Fifth, treating the Origin header from a non-browser client as a cryptographically authentic identity is equally wrong. Repair with explicit origin policy plus separate, verified application credentials.
Sixth, accepting an extension that the client did not request is a protocol mismatch and can lead to unsafe frame interpretation. Seventh, allowing a raw client-supplied proxy header to determine the external host or tenant can bypass authority checks. Eighth, assuming HTTP/2 WebSockets must use HTTP 101 misunderstands extended CONNECT.
Ninth, using successful handshake counts as evidence of business completion conflates transport with application outcome. Tenth, assuming a connection remains authorised for all later actions ignores permission changes, revocation and time limits. Repair with per-operation checks and explicit state transitions.
A productive debugging order checks the request format and HTTP version, accepted origin, verified identity, selected subprotocol and extension, then the schema and authorisation of messages. If all opening checks succeed but events are missing, move to sequence and recovery controls rather than weakening the handshake.
Never bypass a genuine platform or authentication refusal simply to preserve uptime. A deliberate failed handshake is often the correct secure outcome. Record the reason, return an appropriate status and provide the documented route to obtain proper credentials.
Changed-context exercise: a browser dashboard becomes a service agent
Imagine a service originally designed for a dashboard running at https://portal.example.edu. Its browser connects to wss://events.example.edu, and the backend accepts only the portal origin plus a verified user session. Later the organisation adds a non-browser batch agent that consumes the same stream for monitoring. Its WebSocket library may omit Origin or set a manually chosen value. Treating its chosen Origin as proof it is the portal user would be insecure.
The correct solution is a separately designed non-browser authentication path with credentials bound to the intended service identity and minimal permissions. The agent might be allowed to read aggregate status events but not act as individual students. The server should choose the authenticated identity and tenant before making the access decision, regardless of whether the client is a browser or a service process.
Now suppose the dashboard supports status.v2 and the new agent understands only status.v1. If the server no longer supports v1 because it lacked required validation fields, it should reject that offered protocol rather than silently label v2 traffic as v1. The client must be updated under an approved migration, or a deliberately limited and verified compatibility route must be maintained.
The case changes who initiated the connection without changing the basic protocol. The TLS endpoint can remain the same, but the origin’s meaning, credential method and permission set need re-evaluation. Intelligent systems must transfer principles, not merely copy header allowlists from one context to another.
If the connection later fails mid-stream, the agent’s resynchronisation belongs to another layer. The related WebSocket Recovery guide handles heartbeats and sequence gaps; it does not replace the admission rules described here.
Limitations and what a successful handshake cannot prove
A WebSocket handshake establishes a framed connection and any negotiated extensions or subprotocols. It does not prove that every later frame follows the application schema, that a user continues to hold permission or that a downstream write was committed. Those questions require separate validation, authorisation and evidence.
Origin checks protect important browser contexts but can be forged by arbitrary service clients, so they must not be the only authentication control. A secure wss:// TLS connection authenticates the server through the configured certificate trust path but does not automatically establish the end user’s identity or resource permissions.
HTTP/2 and HTTP/3 deployments may use extended CONNECT rather than RFC 6455’s HTTP/1.1 GET/101 exchange. A diagnostic built for one transport mode can misclassify another. The actual implementation’s supported versions, intermediaries and configuration must be checked against RFC 6455, RFC 8441 and RFC 9220.
Resource exhaustion and frame parsing are additional concerns. A properly authenticated client can still send too many messages or overly large payloads. Apply bounded queues, appropriate limits and safe parser behaviour. Compression and extensions add their own risks and deserve explicit testing.
Finally, no current WebSocket design establishes the existence of artificial superintelligence. These are present-day engineering controls for agents and applications, useful precisely because high-capability systems still face ordinary networking, authentication and state-management failures.
Frequently asked questions about safe WebSocket admission
Does HTTP 101 mean the user is authorised? No. It records a successful HTTP/1.1 protocol upgrade, not universal permission for future commands.
What is Sec-WebSocket-Key? It is a base64-encoded client nonce used in the opening handshake computation, not an API credential.
Why check Origin? Browser clients may initiate cross-site WebSocket requests with cookies, so the server must enforce its intended browser-origin policy.
Can a command-line client forge Origin? Yes. For non-browser clients, Origin is not reliable proof of identity; authenticate using an appropriate credential mechanism.
Who chooses Sec-WebSocket-Protocol? The client offers supported values and the server may select a compatible offered value. A server must not invent a different protocol that the client never offered.
What is Sec-WebSocket-Accept for? It demonstrates correct processing of the HTTP/1.1 opening handshake nonce and fixed GUID; it is not user authentication.
Is compression automatic? No. Extensions must be negotiated and supported, with safe parameter parsing and resource limits.
Do HTTP/2 WebSockets send HTTP 101? No. RFC 8441 defines an extended CONNECT mechanism, which differs from the HTTP/1.1 upgrade sequence.
What changes for HTTP/3? RFC 9220 adapts the extended-CONNECT bootstrap to HTTP/3, subject to implementation support.
Does a socket disconnection undo a tool action? Not necessarily. A completed action may precede a lost acknowledgement; use state reconciliation and idempotent operation identifiers.
Reader pathways and original specifications
For developers, start with the appropriate HTTP version and its handshake rules. Test valid and invalid nonce responses, allowed and rejected origins, missing credentials, wrong audiences or tenants, unsupported subprotocols, unrequested extensions and a connection with permissions revoked after opening. Evaluate the actual backend route through the deployed proxy.
For system operators, record which component performs each check and who owns the decision. Distinguish HTTP upgrade success, authenticated session creation, per-operation authorisation and final business completion in dashboards. A meaningful security metric needs a clear denominator and a verified event, not an optimistic status flag.
For reviewers of AI agents, ask what identity the WebSocket holds, how long its permissions last and whether streaming text can be mistaken for an action approval. Investigate what happens when a service agent replaces a browser client, when a proxy changes transport versions and when a message arrives after permissions change.
Primary standards: RFC 6455 — The WebSocket Protocol, RFC 8441 — WebSockets over HTTP/2, and RFC 9220 — WebSockets over HTTP/3. For post-handshake delivery continuity, use the verified WebSocket Recovery guide. The wider pathway begins at How Super Intelligence Works.
The numeric connection counts and example subprotocol names in this article are invented teaching cases. The WebSocket RFC test vector is taken from the protocol standard. No connection to an external service or browser was executed as part of the article.
The server’s handshake decision and the client’s verification duty
Two parties validate different aspects of the upgrade. The server checks whether the incoming request is supported and authorised under its rules. The client checks that the response meets the expected WebSocket protocol, including the Sec-WebSocket-Accept calculation for HTTP/1.1 and that any negotiated subprotocol or extension was actually offered. A mistake at either end can leave an apparent open connection that does not represent the intended protocol agreement.
An agent that acts as a WebSocket client should not suppress validation merely because the remote endpoint has a familiar hostname. DNS naming, TLS identity, HTTP-version negotiation and WebSocket response checks protect different layers. A valid TLS certificate does not justify accepting a fabricated subprotocol, while a correct HTTP 101 does not justify trusting an unverified TLS endpoint.
For a fictional test with 50 upgrade responses, suppose 45 have valid handshake computations and supported negotiated parameters, three contain an incorrect acceptance value and two select unoffered subprotocols. Under the stated disjoint categories, 45/50=90% pass the client-side protocol checks and 5/50=10% should fail. None of these counts demonstrates the permission status of the user or the outcome of a later request.
Testing should deliberately include the wrong-GUID calculation, a malformed base64 key, duplicate required headers, a wrong protocol version, a failed origin, and a server that proposes an extension the client never offered. The system should reject invalid cases without partially activating a privileged message handler. If a failure is transient, reconnect through the same validated policy, not a weakened alternative.
Finally, record the result of each check at its own boundary. A useful incident note says ‘TLS verified, HTTP/1.1 handshake rejected due to unoffered subprotocol’ rather than ‘agent offline’. Precise failure location supports safe repair and avoids the temptation to bypass security controls when a connection fails.
