Control Plane Access¶
Pynchy exposes operational status, capability snapshots, canary evidence, and deployment actions through one HTTP control plane. Use this guide to inspect a local or remote service without exposing those operations to unauthenticated clients.
Local access¶
The default server starts two listeners:
data/pynchy.sock, a Unix socket with mode0600; and127.0.0.1:8484, a loopback TCP fallback for platforms and clients that cannot use Unix sockets.
uv run pynchy doctor prefers the Unix socket when it exists, then falls back to loopback TCP. Pass --socket <path> to select a custom socket.
The Unix socket relies on filesystem permissions and accepts local control requests without a bearer token. Loopback TCP also accepts local requests without a token until either remote-access option gets enabled.
Readiness and operational status¶
GET /health returns only {"status": "ok"}. It stays unauthenticated so a local service manager or external load balancer can perform a readiness probe without receiving repository, channel, capability, or credential details.
Use the authenticated /status, /capabilities, /actions, /work-items, and /canaries/* routes for operational details. /actions exposes external-write state without draft payloads; see Action coverage for its lifecycle. A remote posture requires authentication for every TCP route except /health and exact plugin-registered webhook POST paths, including unknown paths.
Bootstrap a bearer token¶
Create a random token without printing it:
Pynchy writes data/control-plane.token with mode 0600 by default. The command refuses to overwrite an existing token. Rotate it explicitly when every remote client can receive the replacement:
The server reads PYNCHY_CONTROL_TOKEN first, then the configured token file. Keep the token out of pynchy.toml, shell history, URLs, and query strings. A client can read a copied mode-0600 token with --token-file; otherwise it reads PYNCHY_CONTROL_TOKEN and then data/control-plane.token.
Enable remote diagnostic access¶
Remote access needs both an explicit public bind and the bearer token:
Pynchy refuses a non-loopback bind unless allow_public_bind = true. It also refuses either remote-access option when no bearer token exists or when the token contains fewer than 32 bytes. Network ACLs and firewalls remain useful defense in depth, but they do not replace application authentication.
Transfer the token to diagnostic clients through an authenticated secret-sharing channel and store it in a mode-0600 file. The pynchy doctor command accepts --token-file and --host; HTTP clients send the same value in the Authorization: Bearer <token> header.
Pynchy compares bearer tokens without timing-sensitive string equality. It applies a per-client fixed-window request limit before authentication so invalid tokens also consume the request budget. Tune the defaults only when the client workload needs it:
Policy decisions produce structured logs and durable security_audit rows without recording the bearer token.
Provider-authenticated webhooks¶
Plugin webhook routes use exact paths shaped as POST /webhooks/<provider>/<route>. Those POST requests do not carry the Pynchy control-plane bearer token because an external provider cannot know it. The route plugin must authenticate the provider request from its raw body and headers before parsing it. All other methods on the same path, unknown paths, and every normal control-plane endpoint retain the bearer-token policy.
The host applies the global unauthenticated-client rate limit first, then a route-specific body-size and rate limit. It accepts a configured route only when its secret environment variable exists and every fixed or provider-derived workspace target passes startup validation. Fixed routes cannot target admin workspaces. A provider-derived route may opt into declared admin candidates only when their source-trust policy satisfies the admin clean room. Schema-valid authenticated deliveries are deduplicated and durably admitted before the provider receives 200. Routes declare whether authenticated provider context remains a public source. Public-source routes fence it and start the agent invocation corruption-tainted; trusted routes retain provenance without that taint. Routes can also emit deterministic host notifications without an agent run. Provider input cannot bypass a subsystem's explicit authorization gates.
See Linear for agent-task callbacks and GitHub for direct PR notifications.
Enable remote deployment separately¶
A public bind does not grant remote deployment. TCP callers receive 403 unless allow_remote_deploy = true, even when the TCP peer appears to come from loopback; that rule prevents an SSH tunnel or reverse proxy from silently turning a remote request into a trusted local deployment. Keep this stronger posture unless remote deployment provides concrete operational value:
allow_remote_deploy = true also requires bearer authentication, even with a loopback bind. Local callers can use the permission-restricted Unix socket without enabling remote deployment.
To call /deploy from a remote automation client, send the token in the Authorization: Bearer <token> header. Never put it in the URL. The client must handle 401, 403, and 429 as terminal policy responses rather than retrying without correction.
Configuration reference¶
| Key | Default | Purpose |
|---|---|---|
host | 127.0.0.1 | TCP bind address |
port | 8484 | TCP fallback port |
unix_socket | data/pynchy.sock | Preferred local control socket path |
allow_public_bind | false | Permit a non-loopback TCP listener |
allow_remote_deploy | false | Permit /deploy over TCP |
auth_token_env | PYNCHY_CONTROL_TOKEN | Server environment variable that carries the bearer token |
auth_token_file | data/control-plane.token | Server-side fallback token file |
rate_limit_requests | 120 | Requests allowed per client and window |
rate_limit_window_seconds | 60 | Fixed-window duration |