Files
Wiki/README.md
T
hermes-bot 50fb31b950
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
fix(auth): the wiki-index BasicAuth credentials read the API again
#14 put the read API behind a session or an API key. External agents
reach the wiki through wiki-index.renner.uno with BasicAuth only, and
since #14 they got 401: a regression.

The service now checks `Authorization: Basic` itself against the same
htpasswd lines Traefik's wiki-api-basic-auth middleware uses
(Auth:Basic:UsersPath: a file, or a mounted Secret directory where every
visible key is read, as Traefik reads every key of an Opaque Secret).
This is a credential check in the service, not trust in a proxy: the
header proves nothing unless the password matches the hash.

- Hash formats Traefik accepts: bcrypt ($2a$/$2b$/$2y$, BCrypt.Net-Next
  4.2.1), Apache MD5 ($apr1$, implemented here and checked against the
  Traefik docs example and `openssl passwd -apr1`), SHA1 ({SHA}). Any
  other format authenticates nobody.
- The identity is a machine named after the BasicAuth user.
- Policy "read" accepts it; "write" stays API-key only, and the UI stays
  OIDC only.
- A verified (user, password, hash) triple is cached in memory, so bcrypt
  costs once per process.
- With no UsersPath configured the scheme authenticates nobody, so this
  image is safe before the deployment mounts the Secret.

Tests: all three hash formats read the API; a wrong password, an unknown
user, an empty password and a user found only in a hidden Secret entry
are 401; BasicAuth cannot write and does not open the UI.
2026-10-19 14:06:55 +00:00

1.8 KiB

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 and Auth__Oidc__ClientId are required; the redirect URI is https://<request host>/signin-oidc. Machines send X-Api-Key, or BasicAuth checked against the htpasswd lines in Auth__Basic__UsersPath, a file or a mounted Secret directory (bcrypt, apr1 or SHA1; read API only). 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).