AAuth Person Server · self-hosted

Decide which agents may act as you.

A Person Server is the part of AAuth that speaks for the human. It says which AI agents may act for you, at which services, on what terms — and it keeps the record. psd is one you run yourself: a single Rust binary, passkeys, SQLite.

Passkeys, no passwords Ed25519-signed, key-bound tokens One binary, one SQLite file

Pairs with an Agent Provider such as agentprovider.dev — the two halves of “this agent, acting for this person”.

What a Person Server is

Three parties. One question: may this agent act as you here?

AAuth separates who vouches for the software from who vouches for the human. Resources verify both — against published keys, never a callback.

agent provider

Vouches for the software

“This is agent X, and here is its key.”

Issues short-lived aa-agent+jwt identities bound to a key the agent holds. Run one, or use agentprovider.dev.

person server you are here

Vouches for the human

“Agent X acts for this person at this service, and here is what they allow.”

Holds the agent ↔ person binding, runs consent, issues aa-person+jwt and aa-auth+jwt, keeps the record, and revokes.

resource

Verifies and serves

“Signed by a key I can check; the person said yes.”

An API, an MCP server, a calendar. It checks the agent's signature and the Person Server's token against their published JWKS.

psd never issues agent identities. That is the Agent Provider's job; psd only verifies them.
psd never sees your data. It says who may act; the resource still decides what and holds the content.
psd never hands out a name resources can share. Each service gets its own pairwise sub; two of them cannot correlate you.
The flow

An agent asks. You decide. The service checks.

Everything on the wire is signed. Nothing long-lived is issued. Every step is recorded where you can read it.

step 1

The agent asks

It signs POST /person with the key its Agent Provider vouched for and names the service. Unknown or unconsented → 202, and the person is asked.

step 2

The person decides

A consent screen shows the agent, its provider, the service and its terms. Passkey, approve or deny — once, or per scope, or for a mission with a lifetime.

step 3

The service verifies

The agent receives a person token (≤ 1 h) bound to its own key and presents it, signed, to the service — which checks it against psd's published JWKS. Revoke any time.

Hosted sandbox

Try it without running anything.

Build and test agents, providers and resources against a live Person Server — no local setup. Pairs with the Agent Provider sandbox for the full “this agent, acting for this person” flow.

bash
# the live Person Server — discovery document relying parties fetch
$ curl -s https://sandbox.personserver.dev/.well-known/aauth-person.json

# the keys every verifier checks person and auth tokens against
$ curl -s https://sandbox.personserver.dev/.well-known/jwks.json

Development only. Sandbox tokens have no production value. Test people are issued on request (passkeys, no passwords); state may be reset on redeploy. No SLA.

Quickstart

Run it in a few minutes.

One binary, one keys file, one SQLite database. The issuer is permanent — pick the hostname before first run.

bash
# build (Rust 1.85+; no C toolchain beyond what SQLite needs)
$ git clone https://github.com/PersonServer/source-code psd && cd psd
$ cargo build --release

# signing keys + the pairwise secret, once — back this file up
$ ./target/release/psd keygen --keys psd-keys.json

# a config to edit: issuer, keys_file, storage.path
$ ./target/release/psd example-config > psd.json

# serve, then add the first person — prints a one-time enrolment link
$ ./target/release/psd serve --config psd.json
$ ./target/release/psd person add --name "Alice" --config psd.json

Tracks a draft. AAuth is an IETF Internet-Draft, not yet a released standard. psd follows draft-hardt-oauth-aauth-protocol-11 and announces this at startup; pin a commit and expect wire changes as the specification matures.

Why psd

Small, load-bearing, yours.

The Person Server is where the human's authority enters the system. psd keeps that surface small and does the parts the specification makes hard.

Passkeys first

No passwords anywhere. Enrol from a one-time link, log in with a discoverable credential, add more passkeys from the dashboard. Pure-Rust WebAuthn.

Consent that says what it means

The screen names the agent, its provider (verified), the device it claims (marked unverified), and the service's own name and terms — fetched at request time, rendered through a whitelist.

Key-bound tokens

Every person and auth token carries cnf for the agent's Ed25519 key. A leaked token is inert without the private key; every request is signed (RFC 9421).

Pairwise identifiers

The sub a service sees is derived per (person, service). Two services cannot join their records to learn it is the same person.

Revocation that reaches

Revoke an agent on the dashboard and its auth tokens are revoked at every service that received one — signed by psd as itself. Agent Providers can revoke into psd the same way.

Missions

An agent proposes a task with its tools and services; the person approves it once, with a lifetime. Every token under it is capped by that lifetime; ending it revokes them.

A record you can read

Every issuance, denial, revocation and mission event is an audit line (stderr + optional file) and a row the dashboard shows the person under Activity.

Hardened egress

psd fetches metadata from URLs an attacker chose. HTTPS only, no redirects, no private addresses, pinned IPs, size and time caps — on every outbound request.

Your branding, your pages

Every screen is a server-rendered template embedded in the binary. Point ui.templates_dir at a directory to override any of them by file name.