All notable changes to the d-OAuth authorization server are recorded here.
The format follows Keep a Changelog,
and the project uses Semantic Versioning.
While the version stays below 1.0.0, a minor bump may carry a breaking change.
GET /logout (a server-specific session endpoint, not an OAuth 2.1 or OIDC
feature) ends the browser session so a different user can sign in. It destroys
the session and expires the cookie, then renders a neutral page or redirects to
the flow's registered post_logout URI. It accepts no query parameters: the
redirect target is frozen in session meta when the authorization flow is bound
and used only while the owning client is active and still registers that exact
URI (exact-string match, with the RFC 8252 loopback exception). There is no
post_logout_redirect_uri parameter, no id_token_hint, and no
end_session_endpoint in metadata.redirect_uris catalog gains a kind column (authorize | post_logout);
existing rows backfill to authorize. redirect-uri create|enable|disable|delete
and client attach|detach-redirect-uri accept --kind, and config sync file
entries accept a kind field. A client may register at most one enabled
post_logout URI.GET /assets/app.css (src/ui/app.css). It
adds no JavaScript and needs no CSP change: the page policy's existing
style-src 'self' covers it, so script-src 'none' still holds.otpauth:// URI as a server-side inline SVG
QR code beside the text secret and URI, so users can scan instead of
hand-typing. The new qrcode dependency is pinned SVG-only (no image
codecs); the text secret, URI, and one-time recovery codes are unchanged.GET /.well-known/oauth-authorization-server reads the enabled scope catalog
from Postgres on every request. A scope added, enabled, or disabled via the
CLI now appears in scopes_supported immediately on every replica, instead of
only after a restart; the previous in-process cache was never invalidated by
the out-of-process CLI mutation.Cache-Control: no-store
(+ Pragma: no-cache) except /.well-known/… metadata, so authorization and
consent pages, token bodies, request handles, and errors are never cached by
a browser, the back/forward cache, or an intermediary. Token-endpoint error
responses now carry no-store, closing a documented gap against
draft-ietf-oauth-v2-1-16 §3.2.3.GET /login?request_id=… rebinds an already-authenticated session to the
fresh authorization request instead of redirecting on the session's stale
pending binding.The first release. This is an OAuth 2.1-only authorization server, not a backwards-compatible OAuth 2.0 server. The deltas are deliberate: see OAUTH.md for the exact differences.
S256; plain and missing
challenges are rejected. Implicit and resource-owner-password grants do not
exist.rotation_request_id, so a retried
request returns the same tokens instead of double-rotating.client_credentials, device-code (RFC 8628, with the user-facing /device
page), and policy-gated token-exchange (RFC 8693) grants.private_key_jwt is client authentication
only and is never treated as a sender constraint.scopes_supported served from
the enabled scopes table. The document carries no jwks_uri: the server
signs no artifact of its own.requested ∩ client-registered ∩ user-entitled ∩ enabled.migrate, serve, user,
scope, redirect-uri, client, config sync, config check,
admin bootstrap, initial-access-token issue, keygen, and healthcheck.
There is no HTTP admin API and no default credential.503 temporarily_unavailable with Retry-After on security paths, never a
fail-open success and never a 500 or panic.healthcheck subcommand that probes the plaintext health
listener without a shell or curl.{state} hash tag.#![forbid(unsafe_code)] across the crate; unwrap, expect, and panic
are denied by lint in request paths.frame-ancestors 'none', X-Content-Type-Options,
Referrer-Policy, and HSTS on the TLS listener.