ADR-025: Access Tokens for Machine Access

Date: 2026-07-20 Status: Accepted Target: v0.30.0

Context

Auth is passkey-only. Handler.Middleware in server/auth/auth.go gates the API on the qntx_session cookie, which is HttpOnly and lives in an in-memory sync.Map. Scripts, plugins, and CI cannot authenticate.

Decision

Add a second auth path: access tokens, presented as Authorization: Bearer <token>.

What a token is

"the token route will be the way things get to access qntx publicly"

Its own did:key. The 32 bytes are an ed25519 seed rather than only a secret, so the token has a public half and its holder can sign as it.

minted_by — the auth.root_identities entry whose session issued it. "speaking on behalf of a user who minted them". Revoking the account revokes what it minted.

namespace — where it may act, chosen at mint time.

What a token may read and write is not on the token: the roles its DID holds say, through their WRITE and READ lines (ADR-034).

Lookup returns that grant instead of a bool. A bool could carry none of it, which is why the middleware could only ever say "someone authenticated".

Consequences