- devserver bootstraps via one-shot 'paskia init' when no database
exists (multi --rp-id, --rp-name/--auth-host/--origin apply to the
default realm), then runs plain 'paskia' serve which reads all realm
configuration from the database; legacy *.paskiadb is adopted by
serve without init.
- Caddy origins iterate all bootstrap rp-ids.
- vite.config.js accepts a comma-separated PASKIA_AUTH_HOST list and
proxies /.well-known/webauthn to the backend so ROR works in dev.
- caddy/auth/setup forwards /.well-known/openid-configuration and
/.well-known/webauthn to paskia (they must not be swallowed by a
static /.well-known/* file handler); Caddyfile.dev updated to match
the generated dev config.
- Admin: replace Server Options dialog with per-realm management —
realms table on the overview, add/edit/delete realm dialog backed by
/auth/api/admin/realms/. Origins may be any well-formed origin;
non-subdomain ones are related origins (ROR, max 5) and the dialog
points at the .well-known/webauthn URL that must list them.
Connectivity checks compare against the edited realm's rp-id and
degrade to warnings instead of blocking saves.
- Host mode (limited profile) now keys off own_auth_host so realms
sharing another realm's auth host serve the full profile locally.
- Credential list shows a realm badge on passkeys registered for a
different rp-id than the current realm.
- Profile shows an enrollment prompt when the user has no passkey for
the current realm (e.g. after a cross-realm remote login).
- Remote auth permit shows the requesting realm when it differs from
the approver's own.
- settings cache can be force-refreshed after realm changes.
- conftest: bootstrap seeds a localhost realm Config; realm_registry
fixture builds the runtime registry; avatar storage redirected to a
per-test tmp dir; credentials/sessions stamped with the test realm.
- test_cli rewritten for the init/serve split, incl. legacy adoption.
- TestServerConfig replaced by TestRealms covering the realm CRUD API,
cross-realm validation, delete guards and effective-auth-host fallback.
- Avatar/OIDC tests updated for per-realm providers and realm-derived
URLs; obsolete PASKIA_DB path tests removed.
- DispatchMiddleware (outermost app middleware) resolves Host to a realm:
HTTP 421 for unknown hosts, WS closed pre-accept (1008); cross-realm WS
only via the origin realm's effective auth host. Current realm exposed
via request.state.realm and the current_realm() contextvar.
- Credentials and sessions are scoped by realm rp_id: authentication only
matches credentials of the dispatched realm; sessions record rp_id.
- Auth codes (OIDC and cookie exchange) are stamped with the issuing
realm and verified at redemption; remote-auth permits mint the exchange
code for the *requesting* device's realm.
- OIDC provider state (clients, signing keys) is per realm; token,
userinfo, keys and backchannel-logout endpoints use the dispatched
realm; refresh re-stamps the session issuer.
- /.well-known/webauthn serves the realm's related origins (ROR).
- Admin /server-config replaced by /realms CRUD (validated cross-realm,
registry rebuilt on change); permission domains may reference any
realm's hosts or clients; /settings reports the realm's own vs
effective auth host.
- paskia.globals and the runtime-backed hostutil helpers are gone.
- Config is now a realm list (first = default); DB.oidc keyed by rp-id
- Database at fixed paskia.kantadb; user files under paskia.data/users/
- Legacy <rp-id>.paskiadb reader/converter in db/legacy.py (to be deleted eventually)
- paskia init / paskia serve CLI split; serve adopts a lone legacy database
- Realm registry (paskia/realms.py) with cross-realm validation
- Per-realm OIDC keys in oidjwt; backchannel logout uses Session.rp_id/issuer
- Schema migrations discarded; on-disk legacy format assumed current
/auth/api/forward?public=1 passes requests through with a Remote-Public
header (anonymous/forbidden/authenticated) instead of 401/403, so routes
can allow anonymous visitors while still identifying logged-in users.
Reauth (max_age) still requires the auth flow. Documented in Headers.md,
api/forward.md, Integration.md and all proxy guides.
perm=a|b+c now means (a or b) and c; repeated perm args remain ANDed.
Out-of-spec values (empty alternatives, chars outside the scope charset,
stray %2B) are rejected with 400 instead of being silently misparsed;
extra spaces between groups are tolerated. Forward endpoint 400/500
details name /auth/api/forward as origin without echoing query args.
Wildcards are now filename-like: * stays within a :- or /-separated
segment, ** spans segments, partial segments allowed. Slash added to
allowed scope characters for path-based permissions.
The vendored db/logging module duplicated what kanta now provides:
diff formatting, UUID-to-label resolution via logfmt callbacks, unsafe
character filtering and value truncation. Censoring of oidc.key material
moves into the format_log_uuid logfmt callback in db.lifecycle, taking
care to hide only the value, not the 'key' path component itself.
- Make use of its new features and cleanup our interfacing and init/shutdown processes and migrations
- Clean up circular deps, simplify app init
- Add specific pytest for CLI main to cover the changes
Checks permissions for a user given by ?user=<UUID> query arg without
requiring a session cookie. No cookie is read or written, no DB writes.
- perm= query arg supported (same wildcard semantics as validate/forward)
- Returns valid bool + minimal ctx (user/org/role/permissions)
- Permissions are host-scoped via domain filtering, same as session_ctx
- 404 if UUID not found; valid=false if perm check fails (no 403)
- Add ApiCheckUserResponse struct to apistructs
- Add has_all_scopes() helper to permutil for scope-set-based checks