Skip to content

Daemon Authentication

Polytoken runs a local HTTP daemon to manage sessions, tools, and model interaction. Every request to that daemon carries a bearer token, and the daemon rejects any request that does not present the token. Only your user account can read the credential file that stores the token, so other user accounts on the machine cannot read the token or command the daemon. A process already running as your user account can read the credential file; the daemon verifies possession of the token, not the identity of the calling process.

When you start a session with polytoken new or resume one with polytoken continue, Polytoken generates a random bearer token, writes it to a credential file, and passes the file to the daemon. The daemon loads the token at startup and requires it on every request. The CLI and TUI read the same credential file and include the token in the Authorization header of each request they make.

Requests without a valid token receive HTTP 401 before the handler runs.

The daemon synchronization routes use the same bearer-token boundary: GET /sync returns a checkpoint and GET /events?after=<cursor> returns ordered replay. See Client Protocol for the epoch and cursor rules, operation correlation, and the polytoken print sync-event-schema export.

For a new session, Polytoken creates a file called credential.json in the session directory. When Polytoken resumes a session, it writes the credential file to a separate private directory outside the session directory instead. The file contains the bearer token. Polytoken creates the file with 0600 permissions, so only your user account can read or write it. The directory holding the credential file uses 0700 permissions.

External tooling should not assume a fixed location for the credential file. The record.json file in the session directory records the credential path of the running daemon; read the path from there.

Advanced users or external tooling can supply a pre-existing credential file through the --credential-file flag or the POLYTOKEN_DAEMON_CREDENTIAL_FILE environment variable. A daemon requires a credential file at startup.

A supplied credential file must pass the same startup validation as a generated one. The file holds JSON with version set to 1, kind set to polytoken-daemon-credential, and a token field set to a base64url-encoded value that decodes to at least 32 bytes. Generate the token from cryptographically random data: the daemon verifies the decoded length, not the randomness of the bytes. The file must not be a symlink, must have mode 0600, and must belong to the user account running the daemon. The directory containing the file must not give group or other users any access. If the file fails any of these checks, the daemon does not start.

Polytoken generates a high-entropy random token each time it automatically starts or resumes a session. A daemon launched with a pre-existing credential file uses the token in that file. Polytoken compares incoming tokens against the expected value using a constant-time comparison to prevent timing attacks.

If the credential file is missing or invalid at startup, the daemon fails to start rather than serving requests. A daemon that runs without a configured token rejects every request.

The authentication layer never writes the token to a log or an error message, and Polytoken’s HTTP client redacts the token from its debug output.

The Model Context Protocol (MCP) OAuth flow uses a loopback callback by default. The browser redirect carries no token, so the daemon runs that callback listener on a separate ephemeral port without bearer authentication. When a server has a fixed redirect URI, Polytoken opens no local listener. You paste the completed callback URL into the CLI or TUI, which submits the URL to the main daemon’s POST /mcp/{server_name}/oauth/callback route. That route requires the token because the CLI or TUI calls it programmatically with the token already in hand. See MCP Servers for the OAuth sign-in flow.

The daemon serves two authenticated routes for the /feedback form: GET /feedback/artifacts returns the immutable diagnostic-artifact catalog, and GET /feedback/artifacts/{id} retrieves one catalog entry. Retrieval requires the opaque version token returned by the catalog and accepts one of three modes:

  • mode=snapshot (the default) returns the captured prefix of the artifact and tolerates growth after the catalog capture.
  • mode=full returns the whole catalog-time file and requires the file’s size to be unchanged since the catalog captured it.
  • mode=zstd returns the complete catalog-time artifact as application/zstd regardless of the artifact kind, tolerates appended bytes, and includes the X-Polytoken-Raw-Source-Bytes header.

Polytoken redacts session and subagent logs in every retrieval mode, so those logs arrive as a redacted export rather than the raw file. Zstd responses carry an X-Polytoken-Raw-Source-Bytes header reporting the catalog-time raw source size, which for those logs can differ from the redacted export’s decompressed length. The daemon returns HTTP 413 when an artifact exceeds the bound for the requested mode; the full-mode bound is smaller than the zstd-mode bound. Unknown modes or missing/empty version tokens return HTTP 400; a stale version token or an artifact that no longer matches its catalog entry returns HTTP 409.

Direct daemon access and Outpost proxy access

Section titled “Direct daemon access and Outpost proxy access”

A direct request to a daemon always uses that daemon’s bearer token. The daemon token carries no Outpost scopes and never authorizes an Outpost route.

An Outpost proxy request uses the Outpost bearer token at the public boundary. Outpost authenticates that token, checks the route scope, and injects the selected daemon’s internal bearer token when it forwards the request. The client never sends the daemon token through the Outpost proxy.

Request surfaceRequired authorityTarget rule
Direct daemon routeDaemon bearer tokenThe token authenticates that one daemon.
Outpost session proxy from a daemon principalImplicit current_session authorityThe principal may target only its own session.
Outpost session proxy from a machine clientRegistered machine scopeThe client may target any session.
Outpost session proxy from a human principalHuman authentication plus the route’s scope checkA human operator may manage sessions; delegated device-flow tokens remain limited to their approved scopes.
Outpost fleet catalog, fleet events, stopped history, and attachmentsmachine scopeMachine scope authorizes fleet-wide reads; daemon principals cannot call these routes.

Scope authorization and object authorization are separate checks. A scope can permit a class of action, while the target-session check prevents a daemon principal from targeting a different session. See Client Protocol for the retry, epoch, cursor, and stopped-history rules that apply after authentication succeeds.