hermes-bot 0ecf1aaac5
ci/woodpecker/push/test Pipeline was successful
feat(auth): humans sign in with OIDC; no header names a user
The ProxyHeader scheme took the username from X-Authentik-Username for any
peer inside Auth:ReverseProxy:TrustedProxies. The deployment set that to
the whole pod CIDR (a hand copy of the Talos podSubnets), so every pod the
network policies let reach :8080 (Hermes, Gitea, Traefik, all of ai and
monitoring) could claim any human's name on the Facts page and on saved
answers. Authentik's proxy provider sends no signed identity header, so the
header cannot be verified at all.

Humans now sign in with OpenID Connect against Authentik: a public client
with PKCE, the username is preferred_username from the ID token, whose
signature is checked against the provider's JWKS. Nothing about the
network path or the request headers names a user any more.

- Auth:Oidc:Authority, ClientId and PublicOrigin are required; the host
  refuses to start without them. PublicOrigin builds the redirect URI,
  because TLS ends at Traefik and the request scheme is http.
- UI pages, static assets and the Blazor hub need a session (fallback
  policy); an anonymous browser is redirected to the provider.
- The read API (/api/v1 reads, /ask, /questions, /rank, /status) needs a
  session or an API key (policy "read") and answers 401, never a redirect.
  Before, it was anonymous and relied on the gate, BasicAuth or network
  policy in front.
- Writes still need an API key (policy "write").
- /health, /ready and the HMAC-signed /webhook stay anonymous.
- ProxyHeaderAuthenticationHandler and Auth:ReverseProxy are removed.

Tests: an in-process OpenID provider issues RS256 ID tokens. They cover
the PKCE challenge and redirect URI, the full code flow ending in a
session named after the token's user, rejection of a token signed by a
foreign key, the Authentik header signing in nobody, and 401s for
credential-less API calls.
2026-10-19 09:44:58 +00:00

Wiki

Web interface and agent API for the Notes vault (k.renner/notes), running in the homelab cluster. Design: kubernetes/PROPOSAL-wiki-web-api.md in the homelab repository.

Layout

src/Wiki.Core          domain types, ports, vault parsing — references nothing
src/Wiki.Application   use cases (sync, rank, status, …) — depends on Core only
src/Wiki.Adapters.*    one project per external thing, each references Core only
src/Wiki.Host          ASP.NET Core API + MudBlazor UI, composition root
test/Wiki.Contracts    one abstract suite per port; every adapter passes its suite

Adapters are selected in appsettings.json under Wiki:; secrets come from environment variables (Wiki__NoteStore__Gitea__Token, Wiki__Webhook__Secret, Auth__ApiKeys__<name>, Wiki__Judges__Models__<name>__ApiKey, Wiki__AnswerModels__Models__<name>__ApiKey). Each answer-model entry also provides the fact drafter of the same name (/facts).

Humans sign in with OpenID Connect (public client, PKCE): Auth__Oidc__Authority, Auth__Oidc__ClientId and Auth__Oidc__PublicOrigin (the external origin, for the redirect URI) are required. Machines send X-Api-Key. Only /health, /ready and the HMAC-signed /webhook answer without either.

Run

dotnet test Wiki.slnx
dotnet run --project src/Wiki.Host

Endpoints: /health (liveness), /ready (readiness), /api/v1/status, POST /rank, POST /webhook, POST /api/v1/ask (rank + judge), POST /api/v1/questions (ask + answer model, save: true writes output/), POST /api/v1/facts (raw source, API key), GET /api/v1/{notes,tags,raw,reports}, POST /api/v1/lab/eval (rank evaluation over labelled output/ questions, API key).

S
Description
No description provided
Readme
443 KiB
Languages
C# 86.6%
HTML 10.6%
CSS 1.7%
JavaScript 0.8%
Dockerfile 0.3%