Commit Graph
90 Commits
Author SHA1 Message Date
claude-botandClaude Opus 5.5 13d5495899 feat(encyclopedia): state v2 with per-batch and keep memory
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:07:19 +01:00
claude-botandClaude Opus 5.5 996ff182c0 feat(encyclopedia): plan v2 model with assignments and redirects
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:04:49 +01:00
claude-botandClaude Opus 5.5 fa45a96a81 docs: bounded encyclopedia planning implementation plan
ci/woodpecker/push/test Pipeline was successful
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:00:17 +01:00
claude-botandClaude Opus 5.5 8d51f1958d docs: bounded encyclopedia planning design
ci/woodpecker/push/test Pipeline was successful
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 08:55:20 +01:00
k.renner e66e2ad250 Merge pull request 'feat: schedules move to cluster CronJobs' (#18) from feat/external-schedules into main
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/release Pipeline was successful
Reviewed-on: #18
2026-10-26 06:42:51 +00:00
claude-botandClaude Opus 5.5 61c424aac6 feat: schedules move to cluster CronJobs
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
The service no longer schedules work itself. POST /api/v1/encyclopedia/run
syncs and runs the encyclopedia; it answers 502 when the run fails or the
text model stopped it, so a CronJob shows a failed run as a failed Job.
The sync loop keeps its startup sync and the webhook trigger; the 30-min
interval is a CronJob calling POST /api/v1/sync.

Removed: EncyclopediaBackgroundService, Encyclopedia RunAt/TimeZone,
Wiki:Sync IntervalSeconds/RetrySeconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 07:35:24 +01:00
k.renner da0f813fed Merge pull request 'feat: house encyclopedia (Wikipedia-style articles at /house)' (#17) from feat/house-encyclopedia into main
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/release Pipeline was successful
Reviewed-on: #17
2026-10-25 14:48:35 +00:00
k.renner bd6dfa7e51 Merge pull request 'docs: house encyclopedia design' (#16) from docs/house-encyclopedia-design into main
ci/woodpecker/push/release Pipeline is pending
ci/woodpecker/push/test Pipeline was canceled
Reviewed-on: #16
2026-10-25 14:48:28 +00:00
claude-botandClaude Opus 5.5 ca12438ebb fix(encyclopedia): leak-check slugs and titles, keep planned titles stable
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
A scanner hit in the slug or titles, or the German leak check flagging them, makes the article private in both languages. The plan prompt forbids concrete identifiers in titles and slugs and keeps existing titles; prompt version 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:10:09 +01:00
claude-botandClaude Opus 5.5 3f5c41a075 fix(host): answer an anonymous request for a private article with the missing-article 404
The 404 offers anonymous readers the login back to the requested path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:08:34 +01:00
claude-botandClaude Opus 5.5 6a9d8204a0 fix(anthropic): fail a stalled response stream after an idle timeout
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:06:32 +01:00
claude-botandClaude Opus 5.5 4e6fa1c4cc fix(host): show a model-unavailable error on the facts page instead of dropping the circuit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:05:08 +01:00
claude-botandClaude Opus 5.5 8314424f8b fix(core): detect IPv4 network prefixes written as .x, .*, .0/NN or a trailing dot
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:04:43 +01:00
claude-botandClaude Opus 5.5 82d70e4c60 feat(host): house encyclopedia pages with anonymous public view
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:27:40 +01:00
claude-botandClaude Opus 5.5 cf75cef563 fix(host): mark wiki links outside Markdig's own code spans, reject link-like targets
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:07:35 +01:00
claude-botandClaude Opus 5.5 4d94c9ef9a fix(host): allowlist article link targets, resolve wiki links before parsing, lock on leftovers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:59:41 +01:00
claude-botandClaude Opus 5.5 87f88a0fb6 feat(host): article markdown rendering with redaction, infobox, TOC, mermaid
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:47:58 +01:00
claude-botandClaude Sonnet 5.5 5b625a241f fix(host): make encyclopedia schedule tests deterministic and harden the loop
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 21:24:07 +02:00
claude-botandClaude Sonnet 5.5 a99b8c9f06 feat(host): run the encyclopedia nightly after a sync
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 21:20:22 +02:00
claude-botandClaude Opus 5.5 dad8c4bb63 fix(encyclopedia): symmetric frontmatter quoting, trimmed plan titles, commit before unexpected writer failure
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 21:16:02 +02:00
claude-botandClaude Opus 5.5 ff0c07ec76 feat(encyclopedia): incremental reconciler with single-commit writes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 21:08:30 +02:00
claude-botandClaude Opus 5.5 8532e0e0c5 fix(encyclopedia): renumbered leak check, escaped notes, images private, fenced replies
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 21:00:12 +02:00
claude-botandClaude Opus 5.5 9d95ae17b0 feat(encyclopedia): write, leak-check and translate pipeline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 20:53:16 +02:00
claude-botandClaude Opus 5.5 469cbf6bd2 fix(encyclopedia): compact plan JSON, sanitized note lines, robust state read
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:43:29 +02:00
claude-botandClaude Opus 5.5 13de42b838 feat(encyclopedia): article-set planning and attempt memory
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:40:49 +02:00
claude-botandClaude Opus 5.5 1ac1495a4d feat(anthropic): long-form text model port with typed unavailability
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:37:25 +02:00
claude-botandClaude Opus 5.5 572d38ef31 fix(store): map missing binary to FileNotFound, harden text read and fakes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:34:05 +02:00
claude-botandClaude Opus 5.5 d6953db0e9 feat(store): multi-file commit, text and binary read by path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:31:46 +02:00
claude-botandClaude Opus 5.5 2a80cb20af fix(core): leak scanner covers renner.uno forms, normalized addresses, more paths and entity domains
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:27:28 +02:00
claude-botandClaude Opus 5.5 ab41ef8088 feat(core): deterministic leak scanner for public article text
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 14:00:41 +02:00
claude-botandClaude Opus 5.5 013e6cd1e2 fix(core): only ASCII space and tab count as structural whitespace
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:56:27 +02:00
claude-botandClaude Opus 5.5 8c25e93cfb fix(core): container lines in any fence and stray closers redact the rest
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:52:12 +02:00
claude-botandClaude Opus 5.5 b8e48b7d16 fix(core): fail closed where the body scanner and CommonMark disagree
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:45:33 +02:00
claude-botandClaude Opus 5.5 23db9e9240 feat(core): article body format and private-block redaction
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:33:25 +02:00
claude-botandClaude Opus 5.5 c2cffcb291 feat(core): Article document kind under articles/<lang>/
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:26:53 +02:00
claude-botandClaude Opus 5.5 e93da3990c docs(encyclopedia): nightly run, fold in concept review
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Nightly schedule (RunAt 06:00, after the 04:30 distill) instead of a
run after every sync. Reconciler never stops the host; catalog
freshness gate; failure memory in articles/_state.json; a missing or
shrunken plan never deletes; translation unit by unit with structure
reassembled by the service; links and listings to private articles
dropped for anonymous readers; media paths validated; in-page 404;
PilotSlugs; Cache-Control no-store; mermaid strict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:42:55 +02:00
claude-botandClaude Opus 5.5 206c4629aa docs(encyclopedia): drop credential handling
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
Credentials in the wiki are an upstream failure, not a case the
encyclopedia handles: no credential scanner rule, no writer instruction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:20:48 +02:00
claude-botandClaude Opus 5.5 a42c978a99 docs(encyclopedia): no netbird public label; generic examples stay public
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
The wiki Ingress carries neither dns.renner.uno/public nor
netbird.renner.uno/public; either publishes the host via
netbird-service-sync.

The deterministic leak filter only counts this house's identifiers:
values found in the article's source notes, names under renner.uno, and
credentials. Reserved example values (RFC 5737, RFC 3849, RFC 2606)
never count. Writer and leak-check prompts keep generic examples public.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 11:38:02 +02:00
claude-botandClaude Opus 5.5 1d5df07ad0 docs: house encyclopedia implementation plan
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 08:35:53 +00:00
claude-botandClaude Opus 5.5 e240bea5b1 docs: encyclopedia on one host, gated by the app's own OIDC
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
wiki.renner.uno has been plain Traefik with in-app OIDC since homelab
2026-10-19; the gate-based two-hostname split no longer applies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 08:30:12 +00:00
claude-botandClaude Opus 5.5 e560fd13a7 docs: house encyclopedia design
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Wikipedia-style, bilingual (de/en) articles generated from the wiki,
with public/private split via Authentik group, LAN/NetBird only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 08:26:45 +00:00
k.renner fbd5a2529a Merge pull request 'fix(auth): the wiki-index BasicAuth credentials read the API again' (#15) from feat/basic-auth-machines into main
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/release Pipeline was successful
Reviewed-on: #15
2026-10-19 14:13:52 +00:00
hermes-bot 50fb31b950 fix(auth): the wiki-index BasicAuth credentials read the API again
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
#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
k.renner 311f59d82a Merge pull request 'feat(auth): humans sign in with OIDC; no header names a user' (#14) from feat/oidc-login into main
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/release Pipeline was successful
Reviewed-on: #14
2026-10-19 10:13:28 +00:00
hermes-bot 4820bc9f6d fix(auth): redirect URI from the request host, no PublicOrigin setting
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Auth:Oidc:PublicOrigin was a hand copy of the Ingress host. Traefik routes on
the Host header and Authentik matches redirect URIs strictly, so the URI is
https://<request host>/signin-oidc; https because TLS ends at Traefik and
browsers only reach the wiki over https.
2026-10-19 09:45:56 +00:00
hermes-bot 0ecf1aaac5 feat(auth): humans sign in with OIDC; no header names a user
ci/woodpecker/push/test Pipeline was successful
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
k.renner 53c03a8e53 Merge pull request 'feat(facts): pictures as part of a statement, kept next to the raw source' (#13) from feat/fact-images into main
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/release Pipeline was successful
ci/woodpecker/manual/test Pipeline was successful
Reviewed-on: #13
2026-09-25 07:55:43 +00:00
claude-botandClaude Fable 5.1 c94afb004c feat(facts): pictures as part of a statement, kept next to the raw source
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
A statement may carry images (a type label, for instance). The drafter
sees them as image blocks and transcribes what is printed; the deposit
stores each picture beside the note as raw/<stem>-<n>.<ext>, lists it in
the frontmatter and embeds it in the body. INoteStore gains a binary
create and a browse URL, so the raw page can link to the pictures. The
page takes pictures from a file picker (camera on phones) or from paste,
resized in the browser to 1600px.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 09:52:16 +02:00
k.renner 125911a4e6 Merge pull request 'feat(facts): one text box; the drafter turns a statement into a raw source' (#12) from feat/fact-from-statement into main
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/release Pipeline was successful
Reviewed-on: #12
2026-09-25 06:57:04 +00:00
claude-botandClaude Fable 5.1 8b8e56d1b2 feat(facts): one text box; the drafter turns a statement into a raw source
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
IFactDrafter port: a statement in, title/content/tags out. Anthropic
implements it over the transport the answer model already uses (extracted
into MessagesTransport). RecordStatementUseCase drafts, sets the person as
source, keeps the statement verbatim in the body and deposits through the
existing use case. The Facts page is the text box and the receipt; the API
shape for machines is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-25 08:55:45 +02:00