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>
This commit is contained in:
2026-10-24 12:20:48 +02:00
co-authored by Claude Opus 5.5
parent a42c978a99
commit 206c4629aa
2 changed files with 1 additions and 8 deletions
@@ -26,7 +26,6 @@
- `wiki.renner.uno` stays off the internet: its Ingress carries neither `dns.renner.uno/public` nor `netbird.renner.uno/public`.
- Generic examples that name nothing concrete in this house stay public.
- When in doubt, content is private. This covers an unterminated private block, a failed leak check, unparseable model output, and a failed filter.
- Credentials and secret values never appear in any article, private sections included.
- Public article pages send `<meta name="robots" content="noindex">` and the response header `X-Robots-Tag: noindex`.
- No CDN at runtime: Mermaid is vendored under `wwwroot/lib/mermaid/`.
- Article generation reuses the Anthropic key at `Wiki:AnswerModels:Models:claude-sonnet:ApiKey`. No new secret is added.
@@ -167,7 +166,6 @@ Add a `SyncUseCaseTests` case named `Sync_IndexesArticles_ButDoesNotEmbedThem`.
- Only this house's identifiers count, so generic examples stay public (spec: "Generic examples stay public"):
- a candidate counts as a match when its value occurs, case-insensitively, in any of `sources` (the full texts of the article's source notes);
- a name ending in `renner.uno` always counts, sources or not;
- `credential` always counts;
- reserved example values never count, even when they occur in sources: `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`, `2001:db8::/32`, and `example.com`, `example.org`, `example.net` or any name under `.example`.
- Rules (rule names are used in the tests):
- `ipv4`
@@ -177,7 +175,6 @@ Add a `SyncUseCaseTests` case named `Sync_IndexesArticles_ButDoesNotEmbedThem`.
- `entity-id`: `(light|switch|sensor|binary_sensor|cover|climate|script|automation|scene|input_\w+|button|number|select|fan|media_player|person|device_tracker|lock|alarm_control_panel|camera|vacuum|water_heater|update)\.[a-z0-9_]+`
- `path`: tokens starting with `/`, `~/` or `./`, containing a further `/`
- `secret-path`: `apps/<x>/<y>`, `secret/…`, `kv/…`, `vault_[a-z_]+`
- `credential`: the words `password`, `passwort`, `token`, `api key`, `apikey` or `secret`, followed by `:` or `=` and a value
- [ ] **Step 1: Write failing tests.** Use a `[Theory]` with one `InlineData` per rule:
- `ipv4`: `"Der Server 10.2.40.1 antwortet"`
@@ -187,7 +184,6 @@ Add a `SyncUseCaseTests` case named `Sync_IndexesArticles_ButDoesNotEmbedThem`.
- `entity-id`: `"light.eg_kuche_ambiente"`
- `path`: `"/var/run/secrets/x"`
- `secret-path`: `"apps/ai/wiki-anthropic"`
- `credential`: `"Passwort: hunter2"`
Each case passes its value in `sources` and yields that rule name. Then:
- `Scan_IgnoresPrivateBlocks`: the same string inside `::: private` yields no match.
@@ -195,7 +191,6 @@ Add a `SyncUseCaseTests` case named `Sync_IndexesArticles_ButDoesNotEmbedThem`.
- `Scan_MatchIsCaseInsensitive`: body `LIGHT.EG_KUCHE_AMBIENTE`, source `light.eg_kuche_ambiente`, yields `entity-id`.
- `Scan_ReservedExample_NoMatch`: `"192.0.2.10"`, `"2001:db8::1"` and `"nas.example.com"` yield no match, even when present in sources.
- `Scan_RennerUno_AlwaysMatches`: `"gitea.renner.uno"` with empty sources yields `fqdn`.
- `Scan_Credential_AlwaysMatches`: `"Passwort: hunter2"` with empty sources yields `credential`.
- `Scan_NoFalsePositive_OnPlainProse`: `"Die Wärmepumpe heizt den Estrich. Version 2.5 ist aktuell."` yields no match, so a version number is not an IPv4 address.
- `PrivatizeLeaks_MovesOnlyLeakingBlock`.
- [ ] **Step 2: Run them.** Expected: FAIL.
@@ -382,7 +377,6 @@ Add a `SyncUseCaseTests` case named `Sync_IndexesArticles_ButDoesNotEmbedThem`.
- that the newest confirmed fact is used and disputed claims are omitted;
- the private rule: hostnames, IPs, device IDs, network and security layout, restart and server procedures, and attacker-useful detail are private, and private is the choice when unsure;
- that generic examples explaining a principle stay public, and that formats are illustrated with reserved example values (`192.0.2.x`, `2001:db8::`, `example.com`), never with this house's real ones;
- that credentials and secret values are never written at all;
- that no PR numbers, incident logs or entity IDs appear in public text;
- that interior photos of equipment are private unless clearly harmless;
- which images are available: the `attachments` frontmatter of the sources.
@@ -90,10 +90,9 @@ Readers range from non-technical to expert, so every article opens plainly and g
- The host stays LAN- and NetBird-only, as it is today: the `wiki` Ingress carries neither the `dns.renner.uno/public` nor the `netbird.renner.uno/public` label. Either one makes `netbird-service-sync` publish the host.
- **Articles go live without human approval**, as the owner decided. The service commits generated articles directly to the notes repo, the same way it already commits raw deposits. Leak protection is therefore entirely automatic and has three layers:
- the writer marks content private;
- a deterministic filter on the public text catches IP addresses (v4 and v6), hostnames and FQDNs, HA entity IDs, MACs, file paths, and OpenBao or secret paths. It only catches this house's own identifiers: a match counts when the value appears in the article's source notes or is a name under `renner.uno`. A match moves the paragraph into a private section. Credential patterns always count;
- a deterministic filter on the public text catches IP addresses (v4 and v6), hostnames and FQDNs, HA entity IDs, MACs, file paths, and OpenBao or secret paths. It only catches this house's own identifiers: a match counts when the value appears in the article's source notes or is a name under `renner.uno`. A match moves the paragraph into a private section;
- the independent LLM check described in the next item.
- **Generic examples stay public.** An example that explains a principle without naming anything concrete in this house, e.g. what an entity ID or an IP address looks like, belongs in the public text. The writer illustrates formats with reserved example values (`192.0.2.x`, `2001:db8::`, `example.com`), and those never count as leaks. "Private when unsure" applies to facts about this house, not to generic examples.
- **Credentials and secret values never appear in any article**, private sections included. The wiki should not hold them in the first place; if it does, the writer drops them.
- **When notes disagree or are out of date**, the article states the newest confirmed fact and leaves out anything that stays in dispute. It never asserts a disputed claim confidently to a non-technical reader.
- **Group membership covers the whole wiki.** Binding the group to the `wiki` application restricts the whole existing wiki UI, including raw notes and search, to that group. That matches "accounts in the matching wiki group". It also means a helper added to the group can browse the raw notes, not just the private sections.
- **Public pages send `noindex`**, as a precaution even on the LAN.