Technology · Framework

FastAPI

The OAuth authorization server and the earlier Python dispatch layer are FastAPI.

Auth and access planeOAuth authorization serverFAFO Core prototype
Assistants ask · a person grants · tokens follow
NGINX: TLS and per-endpoint rate limits · a locked-down systemd unit
The FastAPI authorization server
authorize · PKCEconsenttokenrevokekey setdiscovery
a person approves each request and sets its lifetimes
Redis: codes and refresh tokens · the signing key survives restarts
  • 4Uvicorn workers on uvloop behind NGINX
  • 3vendors' assistants authenticating against one server
  • 2FastAPI apps: the authorization server and the operator console

An OAuth server for AI assistants

Auth and access plane exists because I wanted commercial AI assistants to reach my private tool estate through standard OAuth, with a person approving every grant. I built the authorization server as a FastAPI application. Access tokens are RS256-signed JWTs.

I put TLS, rate limits and process sandboxing in NGINX and systemd, so the front end protects the application independently of the application's own code.

In front
NGINXterminates TLS, rate-limits per endpoint
systemda locked-down unit for the Uvicorn workers
The FastAPI app
Authorize, with PKCE
Consent screenapprove or deny; set access and refresh lifetimes
Tokenauthorization-code, client-credentials and refresh-token grants
Revocation, key set, discoverythe documents MCP clients look for
State
Redisauthorization codes and refresh tokens
Signing keypersisted, so a restart leaves issued tokens valid

Most of the effort went into interoperability, which is where the real work in OAuth for AI assistants lies. Each vendor reads discovery documents its own way, orders consent differently and caches its client identity differently, and it took a long series of fixes before every vendor's assistant authenticated against one server.

The consent screen also sets token lifetimes per grant, because a desktop assistant and an unattended machine client need different terms.

Access-token lifetime, set per grant
an houra year
A desktop assistant a person is using
An unattended machine client

I made the consent screen the control point, because it is the one place a person sees exactly which client is asking for exactly what.

A hardened operator console

A second FastAPI app with server-side templates is the operator console: single sign-on with an allow-list, minting tokens for machine clients, revoking them, and approving or deleting pending dynamically registered clients.

In the hardening pass I turned off the console's generated API documentation pages, since an admin surface has no reason to describe itself to whoever finds it, and cut the server's health endpoint down to a bare status. The registration lock I added in that pass, and reverted the next day when it broke every client, is the story The hardening fix that locked everyone out.

Beforedocs pages, full healthAftera bare status
a lock on client registration, reverted

Bar lengths are illustrative: the exposed surface, not a measured size.

A prototype rebuilt in Rust

FAFO Core and Function Forge started as a FastAPI dispatch service. I wanted to prove that embedding, local-LLM and cluster-health jobs could be pushed to spawned workers over Redis and offered to AI clients, and Python was the quickest way to prove it. Once the idea held, I rebuilt it in Rust as the control plane, admission controller and gateway that make up the substrate, because the prototype was never going to carry the load or the correctness guarantees I wanted.

The proof · FastAPI
dispatch to spawned workers over Redis
The substrate · Rust
gateway
admission controller
control plane

Layer thickness is illustrative.