Long-running authentication-agent services currently use the native public OAuth client. Public-client sessions have a limited overall lifetime, so an unattended CI service eventually requires interactive sign-in even when refresh tokens are rotated regularly.
The original proposal was to store a client signing key beside the local authentication agent and use private_key_jwt directly. That is not interoperable with the current Bluesky OAuth Provider or the tngl.sh PDS. Both use the Bluesky PDS OAuth implementation, which requires native clients to authenticate with token_endpoint_auth_method: none. Keeping a key in a local LaunchAgent does not turn that native client into a confidential client.
Replace that proposal with opt-in support for a user-managed OAuth Token-Mediating Backend (TMB). The TMB is the confidential web client: it hosts stable HTTPS client metadata and JWKS, owns the client signing key, receives the HTTPS OAuth callback, and performs the PAR, authorization-code exchange, and token-refresh portions that require client authentication. The existing native public-client login remains the default for interactive CLI use.
This is technically feasible but substantially more complex than adding private_key_jwt to the local agent. AT Protocol does not currently provide a standard TMB API or a deployable reference service for this CLI use case. The integration must define the trust boundary, backend API, DPoP-key ownership, token storage and rotation, device authorization, revocation, availability, and recovery behavior. The Client Assertion Backend proposal is not currently accepted by the Bluesky OAuth Provider and must not be used as the compatibility basis.
Compatibility context:
- Bluesky-hosted accounts and
tngl.shaccounts enforce the same native-client restriction. - A confidential client must be represented as
application_type: web, use an HTTPS redirect URI, and authenticate with a signing key published through its metadata or JWKS. tangled.orgitself demonstrates this supported server-side pattern, but a local authentication-agent service is not equivalent to that web backend.
Performance requirements:
- Keep the TMB on the OAuth control plane only. Normal authenticated XRPC calls and artifact blob transfers must continue directly between the authentication agent and the user's PDS.
- A valid access token must not cause an additional TMB request on each XRPC call.
- Do not implement a full BFF data proxy. Proxying every XRPC call would add an extra network round trip, make the backend a throughput and availability bottleneck, and double the network path for large artifact uploads and downloads.
- Coalesce concurrent refresh attempts for the same session so that only one TMB/authorization-server refresh is in flight, then persist the rotated refresh token atomically.
- If the TMB is temporarily unavailable, direct PDS requests should continue while the current access token remains valid. Operations requiring refresh must fail with a distinct, actionable diagnostic.
Feasibility gate before full implementation:
- Build a minimal TMB proof of concept and verify login, PAR, authorization-code exchange, and refresh with both a Bluesky-hosted account and a
tngl.shaccount. - Specify the TMB API and the ownership and storage boundaries for the client signing key, DPoP session key, access token, and refresh token.
- Measure additional p50 and p95 latency for login and refresh, the number of TMB and authorization-server requests under concurrent CLI activity, and whether refresh requests are correctly coalesced.
- Compare normal XRPC latency and artifact upload/download throughput with the existing public-client path. The expected result is no extra backend hop on either data path.
- Verify behavior during TMB unavailability, token revocation, signing-key rotation, authorization-server rejection, and network timeouts.
- Record operational requirements for HTTPS, metadata and JWKS hosting, persistent storage, backups, monitoring, rate limiting, key rotation, and disaster recovery.
Acceptance criteria:
- A named authentication-agent service instance can be configured to use a user-managed TMB without placing client signing keys in the local LaunchAgent property list, command arguments, logs, JSON output, or tracked configuration.
- The flow uses a confidential web client with an HTTPS callback and
private_key_jwt; the local agent is not presented as a confidential native client. - Login and token refresh work against both the Bluesky and
tngl.shauthorization servers, and rotated refresh state is stored atomically. - The design documents and enforces the ownership of client signing, DPoP, access-token, and refresh-token material.
- Concurrent refresh is single-flight per session.
- Status and verification commands distinguish an expired or revoked OAuth session, TMB unavailability, unavailable signing material, invalid client metadata, authorization-server incompatibility, and required interactive reauthentication.
- Existing public-client sessions and foreground authentication-agent operation continue to work unchanged.
- Documentation covers deployment, configuration, security, performance expectations, key rotation, revocation, recovery, and migration through a new authorization flow.
- Focused tests cover configuration validation, TMB protocol handling, persistence, concurrent refresh, failure diagnostics, and preservation of the direct XRPC and artifact data paths.
Out of scope:
- Treating a local-only LaunchAgent as a confidential OAuth client.
- Depending on the proposed Client Assertion Backend behavior before it is supported by the target authorization servers.
- Sending ordinary XRPC requests or artifact bytes through the TMB.
- Providing a tng-hosted shared TMB, metadata, JWKS, DNS, HTTPS, or signing-key provisioning service.
- Migrating an existing public-client session without a new authorization flow.
https://tangled.org/nnabeyang.tngl.sh/swift-tangled/pulls/93