Technical Brief

AffirmedID Sentinel

Per-User Endpoint Background Service for Continuous Authentication & Identity Assurance

Device-anchored trust, from one-time enrollment through every session, on Windows, macOS, and Linux — running in the user's own session, never elevated.

AffirmedID  |  affirmedid.com  |  July 2026

Sentinel is not a monitoring agent. It is a cryptographically registered, per-user background service that establishes a Continuous Authentication session the first time anything on the endpoint actually asks it for one, and serves as the local trust broker, over loopback HTTP, for every AI agent operating within that session. Note: AffirmedID Sentinel is unrelated to Microsoft Sentinel, which is a SIEM product.

About This Revision: This brief describes Sentinel's current architecture as implemented in the active development build. Sentinel is under active development: the service bootstrap, session-commissioning logic, local MCP and AuthZEN endpoints, storage, and cryptographic channel security are implemented and callable. Sentinel remains in active development with projected completion and general availability in Q3 2026.

Executive Summary

AffirmedID Sentinel is an installable background service for Windows 10/11, macOS, and Linux that extends the Pulse Continuous Authentication & Identity Assurance framework directly to the user's endpoint. Where the Auth mobile app provides the user-side trust signal and the Pulse PDP provides the cloud analysis engine, Sentinel provides device-side presence and local brokering, the component running on the machine the user is actually working on.

Sentinel runs as a per-user background process, launched by Windows Task Scheduler at logon, a systemd --user unit, or a macOS LaunchAgent, rather than as a system-wide service running under an elevated service account. This is a deliberate architecture decision: everything Sentinel does, resolving the logged-in user, enrolling a federated identity, brokering local MCP and AuthZEN requests, runs with exactly the privileges of the person sitting at the machine, never more.

Sentinel is an optional component of the Pulse CA framework. Most Pulse CA capabilities operate fully without it. For organizations that need a local, low-latency trust broker for endpoint-side AI agents, or active BLE proximity verification, Sentinel is the mechanism that will deliver those capabilities as it matures.

Core Value Proposition: Sentinel places a per-user, cryptographically registered background service on the endpoint. It resolves who is logged in. It brokers local MCP and AuthZEN requests over loopback HTTP so agentic AI frameworks on the same machine don't need a cloud round trip for every check. And its Continuous Authentication session doesn't exist until something actually asks for one, fail-closed by design.

What Sentinel Is

Sentinel is a multipurpose background service built from nine cooperating components, each mapping to a distinct part of its architecture:

  • Per-User Hosting & Device Identity, a background process launched in the user's own session (not a system service account), backed by a local SQLite store and a single device identifier registered once with the Pulse API.
  • One-Time Username Enrollment, a native OS dialog racing a headless CLI/loopback fallback to solicit the person's federated email address exactly once per device.
  • CA Session Commissioning, a lazy trigger: no Continuous Authentication session exists until the first local MCP or AuthZEN request asks for one.
  • Headless OIDC & FIDO2 Login Ceremony, Sentinel submits the resolved username to a headless OIDC endpoint; the phone-side dual-assertion FIDO2 ceremony and token issuance happen off-device, between the cloud API and the Auth app.
  • Cryptographic Session Identifier (SSDI), a per-session, per-agent hash binding local activity to the device identity without registering every short-lived agent connection with the cloud.
  • Local MCP Server, a loopback-only (127.0.0.1) HTTP endpoint exposing Sentinel's login and session tools to MCP clients on the same machine.
  • Local AuthZEN Evaluator, a loopback-only HTTP endpoint answering AuthZEN-shaped access-evaluation requests locally, fail-closed until a CA session is authorized.
  • Active Proximity Verification (BLE), a Bluetooth Low Energy scanner that detects a session-scoped UUID advertised by the user's Auth mobile app.
  • Post-Quantum Channel Security, an ML-KEM (FIPS 203) key exchange establishing the AES-256-GCM session keys that protect Sentinel's WSS traffic.

Security Assurance: All exchanges with cloud or remote services are over HTTPS/WSS, with WSS channel traffic additionally protected by an ML-KEM-derived AES-256-GCM session key. Local MCP and AuthZEN endpoints are bound exclusively to 127.0.0.1 and are never reachable from outside the machine. The local SQLite store is not currently encrypted at rest; see Implementation Status.

Per-User Hosting and Device Identity

Sentinel is launched in the interactive user's own session, Task Scheduler "At log on" on Windows, a systemd --user unit on Linux, a LaunchAgent on macOS, rather than as a SYSTEM/root service account. This means Sentinel reads and writes under the user's own profile (%LOCALAPPDATA%\AffirmedID\Sentinel on Windows, ~/Library/Application Support/Sentinel on macOS, $XDG_DATA_HOME/sentinel or ~/.local/share/sentinel on Linux), holds no elevated privileges, and, correspondingly, resolves whoever is actually logged in rather than a generic service identity.

On first launch, Sentinel opens a local, unencrypted SQLite database and, the first time a CA session is commissioned, mints a persistent device identifier, a GUID prefixed s., and registers it with the Pulse API. This is the only identifier Sentinel registers with the cloud on an ongoing basis; subsequent launches read the stored identifier rather than re-registering. It is the foundation of session accountability within the Pulse CA framework and the basis for every interaction with other Pulse services.

Edge Case: OS Reinstall or Hardware Replacement. The device identifier's persistence is tied to the Sentinel installation's local SQLite store on a specific device. OS reinstall or physical hardware change constitutes a new installation requiring re-enrollment and re-registration. The prior device record is non-transferable, consistent with the framework's physical device binding model.

One-Time Username Enrollment

Sentinel operates in a closed loop architecture for security reasons. identity must be actively confirmed by the person physically present. When the system starts whether power ON, restart, or wake after sleep, it was query for active user identity, username: Sentinel solicits the person's federated email address through two parallel paths, racing each other, whichever answers first wins:

  • Native OS Dialog: a PowerShell InputBox on Windows, an osascript dialog on macOS, zenity falling back to kdialog on Linux, none of which require any additional software install.
  • Headless CLI Companion: running sentinel --enroll from any terminal, SSH session, or remote shell prompts for the address with plain console input and posts it to a loopback listener the running Sentinel process is already waiting on. This exists specifically for headless deployments, a server reached only over SSH or VPN with no display and no browser ever, where a native dialog has no path forward at all.

The submitted value must be email-formatted; a bare OS account name or a value with no "@" is rejected with specific, immediate feedback. Once accepted, the device identifier and the enrolled username are written to storage together as a single, one-time event; this pairing cannot be repeated or overwritten on that device once set. Every later Sentinel startup reads the stored username directly and proceeds to session commissioning without prompting again.

CA Session Commissioning: First Reference, Not Launch

A foundational architecture decision governs Sentinel's Continuous Authentication session: no CA session exists before something actually asks Sentinel for one. Launching the Sentinel process and commissioning a CA session are two different events. The two loopback listeners, the local MCP server and the local AuthZEN evaluator, are enabled unconditionally at launch, but they start out as dormant sockets answering "not authorized" to everything. The first local MCP request or the first local AuthZEN evaluation request, whichever happens first, is what triggers commissioning: username enrollment (or a read of the memorized username) followed by submission to the headless OIDC login ceremony, run in the background so the triggering request is never blocked waiting on a phone-paced ceremony.

This trigger is idempotent and singular. Only the very first reference, across MCP and AuthZEN combined, from any caller, starts commissioning; every later reference, from the same agent or a different one, simply attaches to the CA session already underway or already established. Sentinel's CA session is one activity that every local consumer shares, not a separate ceremony per agent.

The Rule: Every commissioning event runs the full login ceremony from the beginning, whether the username was just enrolled or read from memorized storage. A memorized username only ever saves re-asking who is logging in; it never shortcuts or skips the ceremony that establishes the session. The one legitimate exception is step-up authentication, a separate, later, in-session re-verification event for elevated actions, which is a distinct mechanism from establishing the session itself and is not yet built.

Headless OIDC Login and FIDO2 Ceremony

Sentinel participates only at the two ends of the login ceremony it triggers. The chain runs as follows:

  1. Sentinel submits the resolved username to the headless OIDC endpoint over a dedicated WSS connection.
  2. The OIDC provider requests dual assertion of that username's identity from the AffirmedID cloud API.
  3. The API dispatches a FIDO2 challenge to the user's enrolled phone via push notification.
  4. On the phone, the user verifies a PIN or biometric; the Auth app's FIDO service verifies the relying-party ID.
  5. The phone returns the FIDO2 and ID assertions to the API for verification over its own secure channel.
  6. The API acknowledges the verified assertions back to the OIDC provider.
  7. The OIDC provider issues tokens, or denies the ceremony, back to Sentinel.

Steps two through six happen entirely off-device, between the cloud API and the phone; Sentinel neither participates in nor waits synchronously on them. Because that round trip is paced by the user tapping their phone rather than a fixed timeout, submitting the username and learning the outcome are two separate calls: RequestSession returns as soon as the request is sent, and the eventual result, tokens issued or denied, arrives later over the same connection and is delivered to whatever consumer registered to receive it.

A dropped or failed connection during this ceremony is itself surfaced as a denial, with the error as the reason, rather than leaving a caller waiting indefinitely.

Cryptographic Session Identifier (SSDI)

Once a session is established, Sentinel derives a Sentinel Session Device Identifier, an ephemeral, per-session cryptographic identity distinct from the persistent device identifier. It is a SHA-256 hash of the device identifier concatenated with the session identifier. Anchoring the SSDI to the registered device identifier, rather than a bare transient value, ties every session record back to a specific physical device for its full lifecycle.

Local AI agents attaching to that session over MCP receive their own SSDI, formed the same way: a SHA-256 hash of the Sentinel session identifier concatenated with a fresh GUID for that agent connection. Here the architecture makes a deliberate tradeoff: only the device-level identifier is registered with the Pulse API. Agent-level SSDIs are tracked locally, in memory, and are never individually reported to the cloud. Registering every agent connection externally would create a high-frequency write path capable of overwhelming the API in agentic frameworks where tool invocations spawn and close in well under a second. Local tracking gives Sentinel complete visibility into which agents are active without externalizing that load; when an MCP connection closes, its local registration is simply removed; there was never an external record to unwind.

Identity TypeScopeRegistered WithPurpose
Device Identifier Persistent (installation lifetime) Pulse API, once, on first session Device accountability across all sessions
Session SSDI Ephemeral (per session) Pulse API, via the session's OIDC provider Session binding, per-session attribution
Agent SSDI Ephemeral (per agent connection) Local only, in memory; not reported to Pulse API Local agent tracking without high-frequency cloud writes

If audit completeness for very short-lived agents becomes a requirement, the intended extension is a session-end summary flush, a batch report of the agents that were active, rather than registering each one individually as it connects.

Post-Quantum Channel Security (ML-KEM)

Sentinel establishes the session keys protecting its WSS traffic using ML-KEM-768, the NIST-recommended parameter set of the FIPS 203 Module-Lattice-Based Key Encapsulation Mechanism, rather than relying on classical key exchange alone. Sentinel generates a key pair and sends the public key to the Pulse API; the API encapsulates a shared secret against that public key and returns the encapsulation; Sentinel decapsulates it to recover the same 256-bit shared secret the API holds. That shared secret feeds directly into AES-256-GCM as the encryption key for the WSS channel, and is zeroed from memory once the session ends.

Post-quantum key establishment is a forward-looking hardening measure: it protects today's session traffic against a future adversary who records encrypted traffic now with the intention of decrypting it once a sufficiently capable quantum computer exists.

Local MCP Server

Sentinel exposes a local Model Context Protocol server for MCP clients on the same endpoint, agentic AI frameworks, IDE extensions, local tooling. This runs as an embedded, loopback-only HTTP host (its own dedicated instance, bound exclusively to 127.0.0.1), not over stdio: the port is supplied at runtime rather than fixed at process startup, defaults to 5285, and is never reachable from outside the machine. Any request to this endpoint, including the initial MCP handshake, is what can trigger CA session commissioning if no session yet exists.

The current MCP tool surface resolves and reports the logged-in user (login_get_username, an unverified OS-level claim) and submits that username to start the federated login ceremony (login_request_oidc_session). Wire types for publishing live trust metrics and active policies to MCP clients are defined and ready to be populated as the cloud PDP integration matures; broader resource and gating capabilities, described under Implementation Status below, are the design target this foundation is built toward.

Local AuthZEN Evaluator

Sentinel also hosts a local AuthZEN-shaped access evaluator, a second embedded, loopback-only HTTP endpoint (default port 5287) implementing the OpenID AuthZEN Access Evaluation request shape, subject, action, and resource in, an authorization decision out. The intent is to let endpoint applications and local agents ask "is this action currently authorized" without a cloud round trip for every check.

The evaluator's decision logic is currently a deliberate, minimal stub: it caches the outcome of the most recent OIDC login ceremony and answers every evaluation request with that cached Authorized flag, with no distinction yet by subject, action, or resource. It does, however, implement the one rule that matters most at this stage: it fails closed. Before any login ceremony has ever completed on a device, there is no cached result, and every evaluation is denied. There is no default-allow state. Per-subject and per-resource evaluation, BLE proximity conditions, and revocation on mid-session trust loss are the design target this fail-closed foundation is built toward.

Active Proximity Verification (BLE)

Sentinel includes a Bluetooth Low Energy scanner intended to confirm that the user's Auth mobile device is physically near the endpoint. The scanning primitive works as follows: a caller mints a session-scoped 128-bit UUID (valid for under 45 seconds), that UUID is delivered to the Auth app over an authenticated channel, the Auth app begins advertising it over BLE, and Sentinel's scanner listens for a matching advertisement, returning the matched UUID on detection, a timeout result if nothing is seen within the configured window, or a "no BLE adapter" result if the endpoint lacks BLE hardware.

Patent Disclosure: The active proximity verification methodology described in this section is disclosed under US patents held by Affirmed Identity LLC, with priority date of August 2015. All rights reserved.

Suspend, Sleep, and Logoff Detection

Sentinel's disappearance, whether from sleep, a crash, a yanked network cable, or an ordinary logoff, looks identical to outside observers, and suspend/resume notification reliability differs fundamentally by platform: macOS and Linux can genuinely hold up sleep briefly for an acknowledgment, Windows cannot. Rather than build a detection model only as strong as its weakest platform, the architecture treats this as a matter for whatever is watching the session, most notably the Pulse PDP, to resolve: a keepalive that goes silent past its expected interval is the actual detection signal, handled identically regardless of cause.

What Sentinel does provide is a single, best-effort, fire-and-forget notification, sent over whatever connection happens to be open, when a suspend or logoff event is detected by platform-specific listeners (native power-event APIs on Windows, macOS, and Linux). There is no acknowledgment wait and no retry; if the message doesn't land, the session's own TTL closes it out regardless. This is a named, accepted tradeoff, not an oversight: an ordinary laptop-closed-for-lunch sleep cycle produces the same signal as an actual compromise or forced termination, absorbed by whatever policy sits downstream of the alarm.

Platform Support

Sentinel is distributed as a per-user background process for three platforms:

PlatformSupported VersionsLaunch Mechanism
Windows Windows 10, Windows 11 Task Scheduler, "At log on," in the user's own session
macOS Current and prior major release LaunchAgent (per-user, not a system-wide daemon)
Linux systemd-based distributions systemd --user unit

None of these run under an elevated system service account; each resolves and operates as the interactive user who logged in. BLE capability is required on the endpoint for active proximity verification; all other Sentinel functions operate without it, with active proximity simply unavailable in that configuration.

Architecture Summary

Sentinel's components interact with the broader Pulse CA framework through well-defined integration points:

ComponentRoleIntegration Point
Device Identifier Persistent device accountability Pulse API registration, once per device; local SQLite storage
Username Enrollment One-time federated identity capture Native OS dialog or headless CLI/loopback listener
CA Session Commissioner Lazy, idempotent session-start trigger First local MCP or AuthZEN reference
Headless OIDC Client Login ceremony submission and result delivery Dedicated WSS connection to the OIDC provider
Session & Agent SSDI Per-session and per-agent binding Pulse API (session only); local memory (agents)
ML-KEM Channel Security Post-quantum WSS session key establishment Pulse API key encapsulation exchange
Local MCP Server Local trust broker for agentic sessions Loopback HTTP (127.0.0.1:5285 default)
Local AuthZEN Evaluator Local, fail-closed access evaluation Loopback HTTP (127.0.0.1:5287 default)
BLE Scanner Physical presence detection primitive Auth mobile app (BLE + out-of-band channel)

Scenario Comparison

How Sentinel's architecture is designed to address attack and risk scenarios that session-layer and cloud-side controls alone cannot. Rows marked Design Target describe capability the current build's fail-closed foundation is built toward, not behavior available today; see Implementation Status for the line between the two.

ScenarioWithout SentinelWith Sentinel
No CA Session Should Exist Until Something Asks ✗ Session-layer controls typically assume a session is already established ✓ Implemented: CA session commissioning is lazy and fails closed until the first local MCP/AuthZEN reference triggers it
Local Agent Requests Cloud PDP Round-Trip for Every Check ✗ Every authorization check leaves the machine, adding latency and cloud load ✓ Implemented: local MCP server and AuthZEN evaluator answer from loopback HTTP without a cloud round trip
High-Frequency Short-Lived Agent Connections ✗ Registering every agent session externally risks overwhelming the identity API ✓ Implemented: agent SSDIs are tracked locally in memory only; nothing external to unregister
Recorded Traffic Decrypted by a Future Quantum Computer ✗ Classical key exchange alone is vulnerable to harvest-now, decrypt-later attacks ✓ Implemented: ML-KEM-768 (FIPS 203) key encapsulation establishes WSS session keys
Token Capture & Replay ✗ Captured token valid until TTL expiry; attacker maintains access ✓ Implemented: DPoP attestation and assertion over Connect OIDC channel and the Pulse API WSS session channel.
User Steps Away from Endpoint ✗ Session continues unattended; no proximity signal at all ◐ Design Target: BLE scanning primitive exists; the graduated proximity trust score and enforcement response are not yet built
Trust Degradation Mid-Session ✗ Enforcement limited to session-layer revocation; endpoint applications continue ◐ Design Target: endpoint-side policy enforcement (suspend, terminate, step-up) is planned, not yet implemented
Sentinel Disappears (Sleep, Crash, Logoff) ✗ No consistent cross-platform detection signal ✓ Implemented: best-effort notification on detected suspend/logoff, plus a documented architecture decision that downstream keepalive/TTL is the authoritative detection signal
Device Code Phishing Prevention ✗ Hijacking the OAuth 2.0 device authorization grant ✓ Implemented: DPoP attestation and assertion over Connect OIDC channel and the Pulse API WSS session channel.

Conclusion

AffirmedID Sentinel brings the Pulse CA trust framework to the endpoint as a per-user, non-elevated background service, one whose Continuous Authentication session comes into existence only when something local actually asks for it, and fails closed until it does. Its local MCP server and AuthZEN evaluator give agentic AI frameworks on the same machine a fast, loopback-only path to session and login state, without a cloud round trip for every check, and without registering every short-lived agent connection with the cloud API. Post-quantum key establishment protects its channel traffic today against tomorrow's decryption capability.

To learn more about AffirmedID Sentinel, including deployment requirements, platform-specific installation, and integration with the Pulse CA framework, contact the AffirmedID team.

Start Demo Contact Us
← Back to Documentation

US Patents Apply  •  Copyright © 2026 Affirmed Identity LLC

Pulse CA™ — AffirmedID at affirmedid.com — Copyright © June 2026