diff --git a/STATUS.md b/STATUS.md index 36098da..3edc84e 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,9 +2,9 @@ -## Issues (21 open, 28 closed) +## Issues (67 open, 28 closed) -Verteilung: M1 5 · M2 13 · M4 2 · M5 1 +Verteilung: M1 16 · M2 20 · M3 4 · M4 12 · M5 15 | Issue | Status | Meilenstein | Priorität | Title | |---|---|---|---|---| @@ -29,12 +29,58 @@ Verteilung: M1 5 · M2 13 · M4 2 · M5 1 | [0051](docs/issues/0051-cve-remediation-pass.md) | open | M5 | high | CVE-Remediation-Pass: Schwachstellen-Report abarbeiten | | [0053](docs/issues/0053-historien-durchgang-nicht-kanonische-commits.md) | open | M2 | low | Historien-Durchgang: acht nicht-kanonische Commits mitziehen | | [0055](docs/issues/0055-npm-scope-aufloesung-threadnet-web.md) | open | M2 | medium | Issue-0055: `@sorb`-Scope in ThreadNet-Web ist nirgends auf rohana festgelegt | +| [0056](docs/issues/0056-gitops-9-external-postgresql-migration-cloudnativepg-o.md) | open | M1 | high | External PostgreSQL Migration: CloudNativePG or Hetzner | +| [0057](docs/issues/0057-gitops-11-element-call-vp9-codec-retry.md) | open | M4 | medium | Element Call: VP9 codec retry | +| [0058](docs/issues/0058-gitops-14-web-application-firewall-waf.md) | open | M5 | medium | Web Application Firewall (WAF) | +| [0059](docs/issues/0059-gitops-16-pod-security-admission-restricted.md) | open | M5 | medium | Pod Security Admission (Restricted) | +| [0060](docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md) | open | M1 | medium | Federation allowlist or closed federation decision | +| [0061](docs/issues/0061-gitops-20-external-secrets-operator-vs-current-sops-set.md) | open | M2 | low | External-Secrets Operator vs. current SOPS setup | +| [0062](docs/issues/0062-gitops-21-renovate-dependabot-for-chart-and-image-updat.md) | open | M5 | medium | Renovate/Dependabot for chart and image updates | +| [0063](docs/issues/0063-gitops-22-security-advisory-monitoring-ess-element.md) | open | M5 | medium | Security advisory monitoring (ESS/Element) | +| [0064](docs/issues/0064-gitops-23-disable-automountserviceaccounttoken-where-no.md) | open | M5 | medium | Disable automountServiceAccountToken where not needed | +| [0065](docs/issues/0065-gitops-25-k3s-api-security-hardening.md) | open | M5 | high | K3s API security hardening | +| [0066](docs/issues/0066-gitops-26-auditd-for-file-integrity-syscall-audit.md) | open | M5 | medium | auditd for file integrity & syscall audit | +| [0067](docs/issues/0067-gitops-27-kernel-hardening-sysctl.md) | open | M5 | medium | Kernel hardening (sysctl) | +| [0068](docs/issues/0068-gitops-28-lynis-security-baseline.md) | open | M5 | medium | Lynis security baseline | +| [0069](docs/issues/0069-gitops-29-crowdsec-integration.md) | open | M5 | medium | CrowdSec integration | +| [0070](docs/issues/0070-gitops-30-falco-runtime-monitoring.md) | open | M5 | medium | Falco runtime monitoring | +| [0071](docs/issues/0071-gitops-31-trivy-image-scanning-for-cves.md) | open | M5 | low | Trivy image scanning for CVEs | +| [0072](docs/issues/0072-gitops-34-dsgvo-datenschutz-compliance-konkretisieren.md) | open | M1 | low | DSGVO/Datenschutz-Compliance konkretisieren | +| [0073](docs/issues/0073-gitops-35-architektur-monorepo-umbau-mit-generalisierte.md) | open | M2 | medium | Architektur: Monorepo-Umbau mit generalisiertem Config-Overlay | +| [0074](docs/issues/0074-gitops-39-cleanup-checkliste-laufend.md) | open | M2 | low | Cleanup-Checkliste (laufend) | +| [0075](docs/issues/0075-gitops-40-neue-issues-erscheinen-nicht-automatisch-im-g.md) | open | M2 | low | Neue Issues erscheinen nicht automatisch im Gitea-Kanban/Projects-Board | +| [0076](docs/issues/0076-gitops-41-registry-git-traffic-zum-gitea-host-ueber-pri.md) | open | M2 | low | Registry-/Git-Traffic zum Gitea-Host ueber privates Hetzner-Netzwerk statt oeffentlichem Internet routen | +| [0077](docs/issues/0077-gitops-42-grafana-dashboard-fuer-clamav-scan-ergebnisse.md) | open | M1 | low | Grafana-Dashboard für ClamAV-Scan-Ergebnisse (Issue #19) | +| [0078](docs/issues/0078-gitops-45-cve-meldeweg-v2-metriken-grafana-dashboard-al.md) | open | M1 | medium | CVE-Meldeweg v2: Metriken, Grafana-Dashboard, Alerts in eigenen Matrix-Raum | +| [0079](docs/issues/0079-gitops-46-issue-migration-nach-gitlab-zentrale-projekt.md) | open | M2 | high | Issue-Migration nach GitLab + zentrale Projekt-Roadmap (Harmonisierung) | +| [0080](docs/issues/0080-gitops-47-raidplaner-mit-sozialer-komponente-verfuegbar.md) | open | M3 | medium | Raidplaner mit sozialer Komponente (Verfügbarkeiten, Aufgaben, Roadmap, Fotoalbum) | +| [0081](docs/issues/0081-gitops-48-gaeste-invite-workflow-per-bot-3-tage-account.md) | open | M3 | medium | Gäste-Invite-Workflow per Bot (3-Tage-Accounts, Admin-Freischaltung, begrenzte Reaktivierung) | +| [0082](docs/issues/0082-gitops-49-cve-alarme-eine-matrix-nachricht-pro-cve-flut.md) | open | M1 | high | CVE-Alarme: eine Matrix-Nachricht pro CVE flutet den Security-Raum -- Zustellung derzeit stumm | +| [0083](docs/issues/0083-gitops-50-monitoring-deploy-geaenderte-configs-greifen.md) | open | M1 | medium | Monitoring-Deploy: geaenderte Configs greifen nicht ohne --force-recreate (Inode-Falle bei Einzeldatei-Mounts) | +| [0084](docs/issues/0084-gitops-51-ci-canonize-token-fuer-die-automatische-turn.md) | next | M1 | medium | CI: CANONIZE_TOKEN für die automatische TURN-Rotation hinterlegen | +| [0085](docs/issues/0085-gitops-52-docs-traegt-zwei-altbestaende-abgeschlossener.md) | open | M2 | low | docs/ trägt zwei Altbestände abgeschlossener Umzüge: TASKS.md und oldwiki/ | +| [0086](docs/issues/0086-gitops-53-k8s-ressourcen-heissen-noch-element-web-docs.md) | open | M4 | low | k8s-Ressourcen heißen noch element-web-docs (Rest des ThreadNet-Rebrands) | +| [0087](docs/issues/0087-gitops-55-logo-fuer-die-authentik-anmeldemaske-entwerfe.md) | waiting | M4 | low | Logo für die Authentik-Anmeldemaske entwerfen (Querformat/SVG) | +| [0088](docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md) | open | M1 | medium | NetworkPolicy: ausgehender Verkehr ist unbeschränkt (13 Ingress-Regeln, 1 Egress) | +| [0089](docs/issues/0089-gitops-58-eigene-images-sind-unsigniert-beim-deploy-pru.md) | open | M5 | low | Eigene Images sind unsigniert — beim Deploy prüft nichts die Herkunft | +| [0090](docs/issues/0090-gitops-59-kein-kubernetes-audit-log-zugriffe-an-der-api.md) | open | M5 | low | Kein Kubernetes-Audit-Log — Zugriffe an der API werden nicht protokolliert | +| [0091](docs/issues/0091-gitops-61-enrollment-kollidierender-localpart-uebernimm.md) | open | M1 | high | Enrollment: kollidierender Localpart übernimmt bestehendes Konto (on_conflict: add) | +| [0092](docs/issues/0092-threadnet-web-1-default-client-einstellungen-theme-features-f.md) | waiting | M3 | low | Default-Client-Einstellungen (Theme, Features) für Neuinstallationen provisionieren | +| [0093](docs/issues/0093-threadnet-web-3-settings-normalisieren-video-audio-einstellun.md) | open | M4 | medium | Settings normalisieren: Video/Audio-Einstellungen nur im Call-Widget, nicht im Haupt-Client | +| [0094](docs/issues/0094-threadnet-web-4-direkter-link-zur-2fa-passkey-einrichtung-in.md) | open | M3 | medium | Direkter Link zur 2FA/Passkey-Einrichtung in den Account-Settings | +| [0095](docs/issues/0095-threadnet-web-6-windows-desktop-code-signing-installer-brandi.md) | open | M4 | low | Windows-Desktop: Code-Signing (+ Installer-Branding) | +| [0096](docs/issues/0096-threadnet-web-7-rebranding-element-axion1337-web-desktop-gesa.md) | waiting | M4 | medium | Rebranding: Element → aXion1337 (Web + Desktop, Gesamtklammer) | +| [0097](docs/issues/0097-threadnet-web-9-feedback-bugreport-weg-eigener-rageshake-oder.md) | open | M4 | low | Feedback-/Bugreport-Weg: eigener Rageshake oder Alternative (Zammad nachhalten) | +| [0098](docs/issues/0098-threadnet-web-11-themes-rollout-2026-08-02-web-live-linux-wind.md) | open | M4 | low | Themes-Rollout 2026-08-02: Web live, Linux + Windows gebaut, macOS lokal | +| [0099](docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md) | open | M1 | medium | Upstream-Sicherheitsfixes lassen sich nicht mergen — kein gemeinsamer Vorfahre | +| [0100](docs/issues/0100-threadnet-web-13-asset-pfade-tragen-weiterhin-element-themes-e.md) | open | M4 | low | Asset-Pfade tragen weiterhin "element" (themes/element/…) | +| [0101](docs/issues/0101-threadnet-call-4-kaputtes-paket-0-19-2-threadnet-6-in-der-regi.md) | open | M4 | low | Kaputtes Paket 0.19.2-threadnet.6 in der Registry — Herkunft ungeklärt | ## Active design docs (0) _none active_ -## ADRs (18) +## ADRs (19) | ADR | Status | Title | |---|---|---| @@ -56,6 +102,7 @@ _none active_ | [0016](docs/adr/0016-notfallhandbuch-nicht-spiegeln.md) | accepted | 0016 — Das Notfallhandbuch bleibt lab-intern und wird nicht gespiegelt | | [0017](docs/adr/0017-split-dns-cfgmon-vier-zonen.md) | accepted | 0017 — Split-DNS auf CFGMON: vier Zonen statt einer, je Zone begründet | | [0018](docs/adr/0018-ki-geraeuschunterdrueckung-clientseitig-opt-in.md) | accepted | 0018 — KI-Geräuschunterdrückung in threadnet-call: client-seitig, opt-in, selbst ausgeliefert | +| [0019](docs/adr/0019-komponenten-issues-adoptiert.md) | accepted | ADR-0019: Komponenten-Issues in docs/issues/ adoptiert — eine Nummernwelt für die Gruppe | ## Open AARs (3) diff --git a/docs/adr/0019-komponenten-issues-adoptiert.md b/docs/adr/0019-komponenten-issues-adoptiert.md new file mode 100644 index 0000000..d44a722 --- /dev/null +++ b/docs/adr/0019-komponenten-issues-adoptiert.md @@ -0,0 +1,70 @@ +--- +type: adr +id: "0019" +status: accepted +date: 2026-08-18 +supersedes: null +superseded_by: null +related: + - "docs/adr/0012-issues-im-repo-gitlab-als-spiegel.md" + - "docs/adr/0013-gruppenregeln-kanonisch-mit-pruefung.md" +--- + +# ADR-0019: Komponenten-Issues in docs/issues/ adoptiert — eine Nummernwelt für die Gruppe + +## Kontext + +ADR-0012 machte `docs/issues/` kanonisch, **beschränkt auf den +Management-Scope**, und ließ die Komponenten-Tracker (gitops, +ThreadNet-Web, threadnet-call) ausdrücklich auf GitLab als Wahrheit — +„bis die jeweilige Komponente selbst adoptiert". Der Zustand seither: +zwei Issue-Welten mit getrennten Nummernkreisen (management#20 ≠ +gitops#20), Drift zwischen Board und Repo an mehreren Stellen +(Beispiel: gitops#61 monatelang ohne Meilenstein, geschlossene +Board-Issues zu offenen Dateien), und Host-Sessions ohne Lab-Zugang +sehen die Komponenten-Backlogs gar nicht. sorb hat am 2026-08-18 die +Adoption angeordnet: ein Backlog, eindeutige Bezeichner, Drift beenden. + +## Entscheidung + +**Die offenen Issues der Komponenten-Tracker werden in `docs/issues/` +adoptiert; es gibt ab jetzt genau eine kanonische Nummernwelt.** + +- Jedes adoptierte Issue bekommt die nächste freie Datei-Nummer + (0056 ff.); die Datei-ID ist der eindeutige Bezeichner der Gruppe. + Die Herkunft steht im Frontmatter (`projekt` + `gitlab_iid`) und im + Dateinamen (`0091-gitops-61-…`); ADR-0012s Gleichung „GitLab-iid = + Datei-id" gilt nur noch für den Management-Altbestand 0001–0032 — + über mehrere Projekte ist sie nicht kollisionsfrei zu halten. +- Übernommen werden Titel, Beschreibung (wortgleich), Status + (Board-Labels `status:*`), Meilenstein, Priorität, Fälligkeit und + eine `area`; Kommentare und Verlauf bleiben auf GitLab (wie beim + Management-Import). Geschlossene GitLab-Issues bleiben Historie und + werden nicht importiert. +- Die GitLab-Projekt-Tracker werden zur **bespiegelten Ansicht** wie + zuvor schon das management-Projekt: `spiegel_issues.py` routet + jede Datei über ihr `projekt`-Feld ins Herkunftsprojekt, kann + geschlossene Issues zu offenen Dateien wieder öffnen, und + `gruppenpruefung.py` prüft die Drift über alle adoptierten Projekte. + Board-, Meilenstein- und Label-Ansichten arbeiten unverändert weiter + — der Grund, aus dem ADR-0012 Option C gewählt hat, bleibt erhalten. +- Neue Issues entstehen ab jetzt **immer** als Datei; das `projekt`-Feld + bestimmt, in welchem Tracker der Spiegel sie anlegt (fehlt es: + management). Ein GitLab-seitig neu angelegtes Issue ohne Datei ist + ein Befund der Gruppenprüfung („zweites Backlog"), kein stiller + Zustand. +- Werkzeug: `verfahren/issue-adoption/adoptiere.py` (deterministisch, + idempotent, Dry-Run-Default) hat die 46 offenen Komponenten-Issues + als 0056–0101 übernommen. + +## Konsequenzen + +- Ein Backlog, ein Nummernkreis, eine Drift-Prüfung; `STATUS.md` zeigt + erstmals die ganze Gruppe. Host-Sessions lesen alle Backlogs über den + Gitea-Mirror dieses Repos. +- Die Schwelle „Komponente adoptiert selbst" aus ADR-0012 ist damit für + gitops, ThreadNet-Web und threadnet-call genommen; thread-net-git, + threadnet-operating und notfallhandbuch hatten keine offenen Issues + und adoptieren bei Bedarf durch Aufnahme in die `projekt`-Enum. +- Querbezüge in Prosa nennen künftig die Datei-ID; alte Bezeichner wie + „gitops#61" bleiben über Frontmatter und Dateinamen auffindbar. diff --git a/docs/issues/0056-gitops-9-external-postgresql-migration-cloudnativepg-o.md b/docs/issues/0056-gitops-9-external-postgresql-migration-cloudnativepg-o.md new file mode 100644 index 0000000..35c8e5d --- /dev/null +++ b/docs/issues/0056-gitops-9-external-postgresql-migration-cloudnativepg-o.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0056" +status: open +created: 2026-05-14 +milestone: M1 +priority: high +area: database +projekt: gitops +gitlab_iid: "9" +related: [] +--- +# External PostgreSQL Migration: CloudNativePG or Hetzner + +> Adoptiert aus [gitops#9](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/9) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Migrate from ESS embedded Postgres to external database. Setup HA + Replication. Test all services. Est. Time: 1-2 days + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#9` — dort erstellt am 2026-05-14 von sorb.* + diff --git a/docs/issues/0057-gitops-11-element-call-vp9-codec-retry.md b/docs/issues/0057-gitops-11-element-call-vp9-codec-retry.md new file mode 100644 index 0000000..08f521f --- /dev/null +++ b/docs/issues/0057-gitops-11-element-call-vp9-codec-retry.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0057" +status: open +created: 2026-07-28 +milestone: M4 +priority: medium +area: element +projekt: gitops +gitlab_iid: "11" +related: [] +--- +# Element Call: VP9 codec retry + +> Adoptiert aus [gitops#11](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/11) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Retry `video_codec: vp9` for better compression efficiency than the current H.264. First attempt (2026-07-28) broke calls entirely (no audio/video transmitted). Likely cause: LiveKit uses SVC for vp9/av1 instead of classic simulcast, but the threadnet-call fork's `buildPublishOptions()` (`src/livekit/options.ts`) always builds simulcast-shaped `videoSimulcastLayers` regardless of codec. Needs a code fix (branch SVC vs simulcast config by codec) before retrying, plus a real browser-console repro if it fails again. H.264 is live and working well in the meantime (7/8 tracks native, 1 clean VP8 fallback). + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#11` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0058-gitops-14-web-application-firewall-waf.md b/docs/issues/0058-gitops-14-web-application-firewall-waf.md new file mode 100644 index 0000000..1e4d820 --- /dev/null +++ b/docs/issues/0058-gitops-14-web-application-firewall-waf.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0058" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "14" +related: [] +--- +# Web Application Firewall (WAF) + +> Adoptiert aus [gitops#14](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/14) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Application-layer (L7) request filtering in front of Traefik - inspects actual HTTP content for attack patterns (SQLi, XSS, known exploit signatures), separate from and not covered by the Hetzner Cloud Firewall (which is network-layer L3/L4 IP/port filtering only). Was counted in the original security task total but never had its own written-up task. Consider overlap with CrowdSec (separate issue) which can provide some WAF-like bouncer behavior via Traefik integration - evaluate whether a dedicated WAF (e.g. Coraza/ModSecurity-compatible) is still needed on top of that. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#14` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0059-gitops-16-pod-security-admission-restricted.md b/docs/issues/0059-gitops-16-pod-security-admission-restricted.md new file mode 100644 index 0000000..41d94ff --- /dev/null +++ b/docs/issues/0059-gitops-16-pod-security-admission-restricted.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0059" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "16" +related: [] +--- +# Pod Security Admission (Restricted) + +> Adoptiert aus [gitops#16](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/16) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Apply Restricted Pod Security Admission to the `matrix` and `authentik` namespaces: enforce non-root, no privileged containers, read-only root filesystem. Test carefully for chart breakage before enforcing. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#16` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md b/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md new file mode 100644 index 0000000..555cc36 --- /dev/null +++ b/docs/issues/0060-gitops-17-federation-allowlist-or-closed-federation-dec.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0060" +status: open +created: 2026-07-28 +milestone: M1 +priority: medium +area: security +projekt: gitops +gitlab_iid: "17" +related: [] +--- +# Federation allowlist or closed federation decision + +> Adoptiert aus [gitops#17](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/17) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Decide: open federation with all public Matrix servers (current default, larger attack surface) vs. an explicit `federation_domain_whitelist`, vs. fully closed federation (`allow_public_rooms_without_join_rules: false`). Config lives in `apps/production/custom-configs/synapse-values.yaml`. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#17` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0061-gitops-20-external-secrets-operator-vs-current-sops-set.md b/docs/issues/0061-gitops-20-external-secrets-operator-vs-current-sops-set.md new file mode 100644 index 0000000..66fcd8b --- /dev/null +++ b/docs/issues/0061-gitops-20-external-secrets-operator-vs-current-sops-set.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0061" +status: open +created: 2026-07-28 +milestone: M2 +priority: low +area: security +projekt: gitops +gitlab_iid: "20" +related: [] +--- +# External-Secrets Operator vs. current SOPS setup + +> Adoptiert aus [gitops#20](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/20) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Current SOPS+age encryption is working fine. Consider whether External-Secrets Operator (cloud-native secret sourcing, e.g. from a proper secrets manager) is worth the migration effort, or whether to just keep/improve the current SOPS rotation strategy. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#20` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0062-gitops-21-renovate-dependabot-for-chart-and-image-updat.md b/docs/issues/0062-gitops-21-renovate-dependabot-for-chart-and-image-updat.md new file mode 100644 index 0000000..2945d32 --- /dev/null +++ b/docs/issues/0062-gitops-21-renovate-dependabot-for-chart-and-image-updat.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0062" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: infrastructure +projekt: gitops +gitlab_iid: "21" +related: [] +--- +# Renovate/Dependabot for chart and image updates + +> Adoptiert aus [gitops#21](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/21) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Automate Helm chart version bumps and container image tag updates, with security patch monitoring, instead of manual version tracking. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#21` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0063-gitops-22-security-advisory-monitoring-ess-element.md b/docs/issues/0063-gitops-22-security-advisory-monitoring-ess-element.md new file mode 100644 index 0000000..8332a40 --- /dev/null +++ b/docs/issues/0063-gitops-22-security-advisory-monitoring-ess-element.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0063" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "22" +related: [] +--- +# Security advisory monitoring (ESS/Element) + +> Adoptiert aus [gitops#22](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/22) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Subscribe to element-hq security mailing list / advisories and Matrix community security channels, set up alerts for new CVEs/patches affecting the deployed components. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#22` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0064-gitops-23-disable-automountserviceaccounttoken-where-no.md b/docs/issues/0064-gitops-23-disable-automountserviceaccounttoken-where-no.md new file mode 100644 index 0000000..97407f6 --- /dev/null +++ b/docs/issues/0064-gitops-23-disable-automountserviceaccounttoken-where-no.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0064" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "23" +related: [] +--- +# Disable automountServiceAccountToken where not needed + +> Adoptiert aus [gitops#23](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/23) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Audit all Deployments/StatefulSets in `matrix` and `authentik` namespaces, add `automountServiceAccountToken: false` wherever the pod doesn't actually need Kubernetes API access (Synapse, ElementWeb, MAS, Postgres, Authentik, etc). Test for no breakage. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#23` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0065-gitops-25-k3s-api-security-hardening.md b/docs/issues/0065-gitops-25-k3s-api-security-hardening.md new file mode 100644 index 0000000..f2b13d6 --- /dev/null +++ b/docs/issues/0065-gitops-25-k3s-api-security-hardening.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0065" +status: open +created: 2026-07-28 +milestone: M5 +priority: high +area: infrastructure +projekt: gitops +gitlab_iid: "25" +related: [] +--- +# K3s API security hardening + +> Adoptiert aus [gitops#25](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/25) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +K3s API currently listens on :6443 on all interfaces (default). Options: firewall-restrict :6443 to localhost only, bind K3s to a WireGuard/internal IP via `--bind-address`/`--advertise-address`, or require a bastion/jumphost for kubectl access. The API is a high-value target. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#25` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0066-gitops-26-auditd-for-file-integrity-syscall-audit.md b/docs/issues/0066-gitops-26-auditd-for-file-integrity-syscall-audit.md new file mode 100644 index 0000000..4d9b9b3 --- /dev/null +++ b/docs/issues/0066-gitops-26-auditd-for-file-integrity-syscall-audit.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0066" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "26" +related: [] +--- +# auditd for file integrity & syscall audit + +> Adoptiert aus [gitops#26](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/26) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Monitor `/etc`, `~/.kube`, `/var/lib/rancher/k3s` for sensitive file changes via auditd rules, output to syslog/centralized logging. Low overhead, good forensics/compliance signal. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#26` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0067-gitops-27-kernel-hardening-sysctl.md b/docs/issues/0067-gitops-27-kernel-hardening-sysctl.md new file mode 100644 index 0000000..0cb70a9 --- /dev/null +++ b/docs/issues/0067-gitops-27-kernel-hardening-sysctl.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0067" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: infrastructure +projekt: gitops +gitlab_iid: "27" +related: [] +--- +# Kernel hardening (sysctl) + +> Adoptiert aus [gitops#27](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/27) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Apply Lynis-recommended sysctl hardening: `kernel.kptr_restrict=2`, `kernel.dmesg_restrict=1`, `net.ipv4.tcp_syncookies=1`, `net.ipv4.conf.all.rp_filter=1`, disable ICMP redirects, etc. Persist via `/etc/sysctl.d/99-hardening.conf`. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#27` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0068-gitops-28-lynis-security-baseline.md b/docs/issues/0068-gitops-28-lynis-security-baseline.md new file mode 100644 index 0000000..d553a19 --- /dev/null +++ b/docs/issues/0068-gitops-28-lynis-security-baseline.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0068" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "28" +related: [] +--- +# Lynis security baseline + +> Adoptiert aus [gitops#28](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/28) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Run `lynis audit system` on the host, review and implement high-priority recommendations, aim for a score >80. Re-run quarterly as a baseline check. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#28` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0069-gitops-29-crowdsec-integration.md b/docs/issues/0069-gitops-29-crowdsec-integration.md new file mode 100644 index 0000000..4c667ff --- /dev/null +++ b/docs/issues/0069-gitops-29-crowdsec-integration.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0069" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "29" +related: [] +--- +# CrowdSec integration + +> Adoptiert aus [gitops#29](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/29) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Install CrowdSec agent on the host, feed auth.log/syslog for collaborative attack detection, auto-block malicious IPs via the local firewall or Hetzner Firewall API. Also relevant to the WAF discussion (CrowdSec has Traefik bouncer integration). + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#29` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0070-gitops-30-falco-runtime-monitoring.md b/docs/issues/0070-gitops-30-falco-runtime-monitoring.md new file mode 100644 index 0000000..45a2bb8 --- /dev/null +++ b/docs/issues/0070-gitops-30-falco-runtime-monitoring.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0070" +status: open +created: 2026-07-28 +milestone: M5 +priority: medium +area: security +projekt: gitops +gitlab_iid: "30" +related: [] +--- +# Falco runtime monitoring + +> Adoptiert aus [gitops#30](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/30) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Deploy Falco as a DaemonSet in K3s to monitor for suspicious runtime behavior (shell spawning in containers, privilege escalation, anomalous syscalls), output to Loki/syslog with alerting. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#30` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0071-gitops-31-trivy-image-scanning-for-cves.md b/docs/issues/0071-gitops-31-trivy-image-scanning-for-cves.md new file mode 100644 index 0000000..a1ae8ac --- /dev/null +++ b/docs/issues/0071-gitops-31-trivy-image-scanning-for-cves.md @@ -0,0 +1,21 @@ +--- +type: issue +id: "0071" +status: open +created: 2026-07-28 +milestone: M5 +priority: low +area: infrastructure +projekt: gitops +gitlab_iid: "31" +related: [] +--- +# Trivy image scanning for CVEs + +> Adoptiert aus [gitops#31](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/31) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Scan container images referenced in Flux HelmReleases for known CVEs, block deployment if a critical CVE is found. CI/CD hook in the git workflow (though note: no Gitea Actions runner is currently active in this repo, per the milestone-release.yml findings from an earlier session - would need that resolved first, or run scanning out-of-band). + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#31` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0072-gitops-34-dsgvo-datenschutz-compliance-konkretisieren.md b/docs/issues/0072-gitops-34-dsgvo-datenschutz-compliance-konkretisieren.md new file mode 100644 index 0000000..dffadb6 --- /dev/null +++ b/docs/issues/0072-gitops-34-dsgvo-datenschutz-compliance-konkretisieren.md @@ -0,0 +1,20 @@ +--- +type: issue +id: "0072" +status: open +created: 2026-07-28 +milestone: M1 +priority: low +projekt: gitops +gitlab_iid: "34" +related: [] +--- +# DSGVO/Datenschutz-Compliance konkretisieren + +> Adoptiert aus [gitops#34](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/34) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Bisher nur als vages "M7: Enterprise-Ready - Future"-Ziel in der alten Milestone-Tabelle vermerkt, nie konkretisiert. Relevant, sobald echte Nutzer (nicht nur Testaccounts) und offene Federation im Spiel sind - fremde Server/Nutzer sehen dann ggf. Daten mit. Prio 0 laut User - erst angehen, wenn die anderen Punkte durch sind. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#34` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0073-gitops-35-architektur-monorepo-umbau-mit-generalisierte.md b/docs/issues/0073-gitops-35-architektur-monorepo-umbau-mit-generalisierte.md new file mode 100644 index 0000000..1133a7d --- /dev/null +++ b/docs/issues/0073-gitops-35-architektur-monorepo-umbau-mit-generalisierte.md @@ -0,0 +1,23 @@ +--- +type: issue +id: "0073" +status: open +created: 2026-07-28 +milestone: M2 +priority: medium +area: infrastructure +projekt: gitops +gitlab_iid: "35" +related: [] +--- +# Architektur: Monorepo-Umbau mit generalisiertem Config-Overlay + +> Adoptiert aus [gitops#35](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/35) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Aktuell drei getrennte Repos (`axion1337.chat-gitops`, `ThreadNet-Web`, `threadnet-call`). Idee: alles in ein Monorepo überführen, mit einem generalisierten Setup und einer Art Config-Overlay (z.B. Kustomize-Overlays oder Helm-Values-Layering pro Deployment-Ziel), damit der gesamte Stack reproduzierbar auch an anderer Stelle/für eine andere Domain deploybar wird - nicht fest auf axion1337.chat verdrahtet. + +**Wichtig**: Das ist ein größeres Architektur-Vorhaben und braucht erst eine gründliche, eigene Planungssession, bevor irgendwas umgesetzt wird. Nicht nebenbei anfassen. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#35` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0074-gitops-39-cleanup-checkliste-laufend.md b/docs/issues/0074-gitops-39-cleanup-checkliste-laufend.md new file mode 100644 index 0000000..3ff9593 --- /dev/null +++ b/docs/issues/0074-gitops-39-cleanup-checkliste-laufend.md @@ -0,0 +1,25 @@ +--- +type: issue +id: "0074" +status: open +created: 2026-07-28 +milestone: M2 +priority: low +projekt: gitops +gitlab_iid: "39" +related: [] +--- +# Cleanup-Checkliste (laufend) + +> Adoptiert aus [gitops#39](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/39) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Laufende Sammel-Liste kleiner Aufraeumarbeiten, kein einzelnes Projekt - hier landen zukuenftig weitere kleine Punkte. + +- [ ] Verwaistes `@bojeledoggo:axion1337.chat` (leeres Matrix-Konto ohne OIDC-Link) loeschen/deaktivieren +- [ ] `Boje`s fehlende E-Mail in Authentik ergaenzen (oder bewusst so lassen?) +- [ ] Test-Invitations/-Raeume aus der Session 2026-07-27/28 aufraeumen (`test-fix-2026-07-27*`, Call-Test-Raeume von akadmin/frank/clark/lucky) +- [ ] `clark`/`lucky` Testaccounts loeschen, sobald der Stack final abgenommen ist + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#39` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0075-gitops-40-neue-issues-erscheinen-nicht-automatisch-im-g.md b/docs/issues/0075-gitops-40-neue-issues-erscheinen-nicht-automatisch-im-g.md new file mode 100644 index 0000000..90fae5f --- /dev/null +++ b/docs/issues/0075-gitops-40-neue-issues-erscheinen-nicht-automatisch-im-g.md @@ -0,0 +1,30 @@ +--- +type: issue +id: "0075" +status: open +created: 2026-07-28 +milestone: M2 +priority: low +area: infrastructure +projekt: gitops +gitlab_iid: "40" +related: [] +--- +# Neue Issues erscheinen nicht automatisch im Gitea-Kanban/Projects-Board + +> Adoptiert aus [gitops#40](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/40) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Gitea bietet aktuell keine REST-API fuer Projects/Kanban-Boards (bestaetigt mit 4 verschiedenen Tokens, darunter ein Full-Admin-Token - durchgehend 404). Das ist keine Berechtigungsfrage auf unserer Seite, sondern eine tatsaechlich fehlende Upstream-Funktion (siehe Gitea GitHub Issue #36824, offenes Feature-Request, Stand 2026-07-28 noch nicht implementiert). + +Konkrete Auswirkung: Neu erstellte Issues (#11-#39, per Batch-Script aus dem alten TASKS.md-Backlog migriert) landen nicht automatisch im bestehenden Kanban/Projects-Board der Roadmap - muessen manuell per Drag&Drop/UI hinzugefuegt werden. + +Optionen fuer die Zukunft: +- Manuell nachpflegen (aktueller Stand) +- Auf ein Gitea-Update warten, falls die Projects-API implementiert wird +- Alternatives Board-Tool evaluieren, falls das dauerhaft zu nervig wird + +Niedrige Prioritaet, da rein organisatorisch - kein technisches Risiko. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#40` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0076-gitops-41-registry-git-traffic-zum-gitea-host-ueber-pri.md b/docs/issues/0076-gitops-41-registry-git-traffic-zum-gitea-host-ueber-pri.md new file mode 100644 index 0000000..a4402b3 --- /dev/null +++ b/docs/issues/0076-gitops-41-registry-git-traffic-zum-gitea-host-ueber-pri.md @@ -0,0 +1,29 @@ +--- +type: issue +id: "0076" +status: open +created: 2026-07-28 +milestone: M2 +priority: low +area: infrastructure +projekt: gitops +gitlab_iid: "41" +related: [] +--- +# Registry-/Git-Traffic zum Gitea-Host ueber privates Hetzner-Netzwerk statt oeffentlichem Internet routen + +> Adoptiert aus [gitops#41](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/41) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Waehrend der Backup-Implementierung (#6/#15) stellte sich heraus, dass eine Firewall-Fehlkonfiguration den K3s-Node komplett von `rohana.axion1337.de` (Gitea, Container-Registry) abschnitt - Image-Pulls schlugen mit Timeout fehl. Ursache gefunden: beide Server haengen im selben privaten Hetzner-Netzwerk (Node 10.0.0.2, Gitea-Host 10.0.0.3, <2ms Latenz), aber der Traffic lief bisher ausschliesslich ueber die oeffentliche IP/Internet. + +Als Sofortmassnahme wurde ein statischer Eintrag in `/etc/hosts` auf dem K3s-Node ergaenzt (`10.0.0.3 rohana.axion1337.de`), der Image-Pulls unabhaengig vom Zustand der oeffentlichen Firewall macht. Das ist aber unmanaged Node-Konfiguration (kein GitOps, ueberlebt einen Node-Neuaufbau nicht). + +Sauberer, dauerhafter Fix waere eine cluster-weite Loesung, z.B.: +- CoreDNS-Rewrite/Hosts-Plugin im Corefile, damit alle Pods (nicht nur der Node selbst) `rohana.axion1337.de` intern aufloesen +- Pruefen, ob auch Flux GitRepository-Sync davon profitieren kann/sollte + +Vorteil: Traffic bleibt intern, unabhaengig von oeffentlicher Firewall/Internet-Erreichbarkeit, kein Punkt mehr, an dem eine Firewall-Anpassung versehentlich Image-Pulls oder Flux-Sync brechen kann. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#41` — dort erstellt am 2026-07-28 von sorb.* + diff --git a/docs/issues/0077-gitops-42-grafana-dashboard-fuer-clamav-scan-ergebnisse.md b/docs/issues/0077-gitops-42-grafana-dashboard-fuer-clamav-scan-ergebnisse.md new file mode 100644 index 0000000..22ad8be --- /dev/null +++ b/docs/issues/0077-gitops-42-grafana-dashboard-fuer-clamav-scan-ergebnisse.md @@ -0,0 +1,32 @@ +--- +type: issue +id: "0077" +status: open +created: 2026-07-29 +milestone: M1 +priority: low +area: infrastructure +projekt: gitops +gitlab_iid: "42" +related: [] +--- +# Grafana-Dashboard für ClamAV-Scan-Ergebnisse (Issue #19) + +> Adoptiert aus [gitops#42](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/42) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Wunsch aus Issue #19-Tests: sichtbar machen, wie oft ClamAV tatsächlich etwas blockiert +(bisher nur in Synapse-Logs sichtbar: `clamav_spam_checker - WARNING - ClamAV rejected an +upload: `). + +Da Alloy bereits alle Pod-Logs nach Loki schickt (`10.0.0.3:3100`, siehe +`docs/deployment-guides/03-monitoring-integration.md`), braucht es dafür keine neue +Instrumentierung - nur ein neues Grafana-Dashboard/Panel mit einer LogQL-Query auf +`{app="synapse-main"} |= "ClamAV rejected"` (Anzahl über Zeit, evtl. Tabelle mit erkannten +Signaturen). Optional zusätzlich: ein Panel für Scanner-Ausfälle (`ClamAV scan failed` - +fail-open-Fälle, die sonst unbemerkt blieben). + +Kein Server-seitiger Code nötig, rein Grafana/Loki-Dashboard-Arbeit. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#43` — dort erstellt am 2026-07-29 von sorb.* + diff --git a/docs/issues/0078-gitops-45-cve-meldeweg-v2-metriken-grafana-dashboard-al.md b/docs/issues/0078-gitops-45-cve-meldeweg-v2-metriken-grafana-dashboard-al.md new file mode 100644 index 0000000..2b20d84 --- /dev/null +++ b/docs/issues/0078-gitops-45-cve-meldeweg-v2-metriken-grafana-dashboard-al.md @@ -0,0 +1,33 @@ +--- +type: issue +id: "0078" +status: open +created: 2026-08-01 +milestone: M1 +priority: medium +projekt: gitops +gitlab_iid: "45" +related: [] +--- +# CVE-Meldeweg v2: Metriken, Grafana-Dashboard, Alerts in eigenen Matrix-Raum + +> Adoptiert aus [gitops#45](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/45) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Entscheidung sorb (2026-08-01): Die reine Artifact-Ablage der Trivy-Funde (#31) ist **ungenügend**. Zielbild: + +1. **Eigener Matrix-Raum für CVE-/Release-Meldungen**: `!YRJvcEbVXtRlUIkNld:axion1337.chat` (angelegt), Absender bleibt der bestehende `@alerts`-Bot — kein zweiter Bot (beantwortet CFGMON-13). ⬜ **Bot einladen** (Raum ist restricted, Join wurde abgelehnt) — sorb. +2. **CVEs als Metriken** → **Grafana-Dashboard** + **Prometheus-Alertregeln** → Alertmanager → Matrix. Damit laufen CVE-Warnungen über denselben Alarmweg wie alles andere (Historie, Silences, Dashboards inklusive). + +**Architektur-Vorschlag (zur Diskussion):** +- **Scan-Ort wandert von der Lab-CI nach CFGMON**: Trivy als Compose-Service/Cron im monitoring-Stack (`--format json` → kleiner Stdlib-Konverter → Prometheus-Textfile/Pushgateway-los via Remote-Write auf localhost:9090). Begründung: Metriken, Prometheus und Grafana wohnen dort; die Lab-CI bleibt fürs schnelle „Report als Artifact" beim Release-Build. Alternativ: Lab-CI pusht Metriken — scheitert aber an CFGMON-03 (9090 wird gerade zugezogen) und koppelt Prod-Monitoring an Lab-Verfügbarkeit. +- **Metrik-Schema**: `trivy_image_vulnerabilities{image,severity}` (Gauge) + `trivy_scan_timestamp{image}`; Alertregel z. B. `trivy_image_vulnerabilities{severity="CRITICAL"} > 0` → severity=critical, `HIGH > 0` → warning mit `for: 24h` (Rauschdämpfung). +- **Raum-Routing**: matrix-alerts-Receiver bekommt Label-basiertes Routing (`room`-Label im Alert → Ziel-Raum, Default = Alerts-Raum); Alertmanager-Route setzt `room: cve` für Trivy-Alerts. Kleiner, sauberer Eingriff im bestehenden Stdlib-Receiver. +- **release-watch** (Advisory-Notizen, #22) zieht in denselben CVE-Raum um — Env dafür ist vorbereitet (`MATRIX_RELEASE_ROOM_ID`, Fallback Alerts-Raum). + +**Abgrenzung SBOM** (Frage sorb, dokumentiert auch im Script): `release-watch` lebt von einer **handgepflegten Repo-Liste** — de facto ein Mini-SBOM auf Repo-Granularität, ohne Versions-/Dependency-Wissen. **Trivy dagegen erzeugt sein SBOM selbst aus den Images** (OS-Pakete + Sprach-Dependencies) — dort ist nichts zu pflegen. Beide ergänzen sich: Trivy = „was IST verwundbar in dem, was wir ausliefern", release-watch = „Upstream hat etwas veröffentlicht, das uns betreffen könnte". + +Verweise: #31 (Scan existiert), #22 (release-watch), CFGMON-13 im Backlog (Absender-Design — durch Punkt 1 entschieden). + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#47` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0079-gitops-46-issue-migration-nach-gitlab-zentrale-projekt.md b/docs/issues/0079-gitops-46-issue-migration-nach-gitlab-zentrale-projekt.md new file mode 100644 index 0000000..b004bca --- /dev/null +++ b/docs/issues/0079-gitops-46-issue-migration-nach-gitlab-zentrale-projekt.md @@ -0,0 +1,32 @@ +--- +type: issue +id: "0079" +status: open +created: 2026-08-01 +milestone: M2 +priority: high +projekt: gitops +gitlab_iid: "46" +related: [] +--- +# Issue-Migration nach GitLab + zentrale Projekt-Roadmap (Harmonisierung) + +> Adoptiert aus [gitops#46](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/46) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +**Auftrag sorb (2026-08-01, HOHE PRIORITÄT):** Es wird zunehmend unübersichtlich — Issues liegen in vier Gitea-Repos, Host-Backlogs im Backlogs-Repo, Code seit der Migration auf git.lab. Ziel: **eine zentrale Sicht in GitLab.** + +## Umfang +1. **Issue-Migration (zwingend):** alle bestehenden Gitea-Issues (offen UND geschlossen — die Abschlussdokumentation ist wertvoll) nach GitLab überführen: gitops (47+), ThreadNet-Web (8), threadnet-call (2), thread-net-git (1). +2. **Harmonisierung/Roadmap:** zentrale Projekt-Roadmap auf Gruppen-Ebene (`axion1337.chat`), die Issues + Host-Backlogs sinnvoll zusammenführt — GitLab-Bordmittel: Gruppen-**Epics/Roadmap-Ansicht**, Milestones, Labels-Taxonomie (prio/*, area/*, host/*), Gruppen-Boards. + +## Plan-Skizze (zur Abstimmung vor Umsetzung) +- **Werkzeug:** GitLabs eingebauter Gitea-Importer übernimmt Issues+Kommentare (Autorenschaft läuft auf den Import-User — bekannter, akzeptierbarer Verlust). Da die Projekte in GitLab schon existieren, ist ggf. stattdessen ein API-Skript nötig (Issues in BESTEHENDE Projekte importieren kann der Importer nicht) — Skript-Weg: Gitea-API lesen → GitLab-API schreiben, `[Gitea #N]`-Präfix im Titel oder Migrations-Fußzeile pro Issue für die Nummern-Zuordnung (Commit-Messages referenzieren alte Nummern!). +- **Host-Backlogs:** `Backlogs`-Repo-Einträge (CFGMON-xx, MATRIX-xx, …) als GitLab-Issues in einem neuen Projekt `infrastruktur` (oder Labels `host::cfgmon` etc.) — die Markdown-Historie bleibt als Archiv erhalten. +- **Folgeänderungen (nicht vergessen):** Repo-Topologie-Doku (CLAUDE.md/README „Issues bleiben Gitea" wird obsolet), TURN-Rotations-CronJob-PR-Hinweis, alle `rohana…/issues`-Links in Doku, meine Sessions-Werkzeuge (claude-issues-Token → GitLab-Token). ⚠️ **Erreichbarkeits-Trade-off bewusst machen:** git.lab ist nur im Lab auflösbar — Issues wären unterwegs nicht mehr erreichbar. Optionen: (a) akzeptieren, (b) GitLab extern erreichbar machen (eigenes Projekt!), (c) Hybrid vermeiden — genau der räumt ja nicht auf. **Entscheidung sorb nötig, bevor migriert wird.** +- **Reihenfolge:** Labels/Epics-Gerüst zuerst, dann Testmigration EIN Repo (thread-net-git, 1 Issue), Review, dann Rest. + +Verwandt: Backlogs CFGMON-12 (wird hiervon abgelöst/erweitert). + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#48` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0080-gitops-47-raidplaner-mit-sozialer-komponente-verfuegbar.md b/docs/issues/0080-gitops-47-raidplaner-mit-sozialer-komponente-verfuegbar.md new file mode 100644 index 0000000..66915b0 --- /dev/null +++ b/docs/issues/0080-gitops-47-raidplaner-mit-sozialer-komponente-verfuegbar.md @@ -0,0 +1,34 @@ +--- +type: issue +id: "0080" +status: open +created: 2026-08-01 +milestone: M3 +priority: medium +projekt: gitops +gitlab_iid: "47" +related: [] +--- +# Raidplaner mit sozialer Komponente (Verfügbarkeiten, Aufgaben, Roadmap, Fotoalbum) + +> Adoptiert aus [gitops#47](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/47) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +**Wunsch sorb (2026-08-01):** gemeinsames Planungs-Tool mit sozialer Komponente — Verfügbarkeiten („wer hat wann Zeit"), Aufgaben-Zuweisung, gemeinsame Roadmap-Visualisierung, **integriertes Fotoalbum** (Bilder anlassbezogen an Aktivitäten/Board-/Roadmap-Einträge geknüpft, z. B. Bauphasen-Screenshots, Boss-Kämpfe). + +**Rechercheergebnis (Kurzfassung):** Die Gaming-„Raidplaner"-Szene (Raid-Helper, Raid-Planner) ist durchweg **Discord-gebunden, nicht self-hosted** — passt nicht zum Matrix-Stack. Realistische Self-Hosted-Kandidaten: + +| Kandidat | Verfügbarkeit | Aufgaben | Roadmap | Fotoalbum integriert | Einschätzung | +|---|---|---|---|---|---| +| **HumHub** | Kalender-Modul + Umfragen | Tasks-Modul | Kanban-artig | ✅ Gallery-Modul, an Spaces/Posts geknüpft | **Bester Fit für „sozial + Fotos"** — Community-Plattform mit Modulen; Achtung: manche Module Pro | +| **Nextcloud** (Deck+Calendar+Polls+Memories) | Polls/Kalender | Deck-Boards | Deck + Kalender | Memories/Photos, aber nur locker verknüpfbar | Mächtig, aber „zusammengesteckt" statt integriert | +| **Agorakit** | Termine + Umfragen | rudimentär | — | Datei-/Bildablage je Gruppe | Leichtgewichtiger Geheimtipp, kleineres Ökosystem | +| **Vikunja / Focalboard** | — | ✅ stark | ✅ | ❌ | reine Task-Tools, Sozialteil fehlt | +| **Mobilizon** | Events ✅ | ❌ | ❌ | ❌ | nur Event-Seite | + +**Empfehlung zur Evaluation:** HumHub zuerst (deckt als Einziges alle vier Anforderungen in EINEM Tool), Nextcloud als Plan B falls HumHubs Modul-Lizenzmodell stört. Deployment-Ort-Frage (CFGMON? eigener Host?) und Matrix-SSO via Authentik (beide können OIDC!) gehören in die Evaluation. + +Quellen: raid-helper.dev, raid-planner.com, alternativeto.net/software/open-event. + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#49` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0081-gitops-48-gaeste-invite-workflow-per-bot-3-tage-account.md b/docs/issues/0081-gitops-48-gaeste-invite-workflow-per-bot-3-tage-account.md new file mode 100644 index 0000000..a3d9106 --- /dev/null +++ b/docs/issues/0081-gitops-48-gaeste-invite-workflow-per-bot-3-tage-account.md @@ -0,0 +1,37 @@ +--- +type: issue +id: "0081" +status: open +created: 2026-08-01 +milestone: M3 +priority: medium +projekt: gitops +gitlab_iid: "48" +related: [] +--- +# Gäste-Invite-Workflow per Bot (3-Tage-Accounts, Admin-Freischaltung, begrenzte Reaktivierung) + +> Adoptiert aus [gitops#48](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/48) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +**Wunsch sorb (2026-08-01):** definierter Prozess für sichere, temporäre Gast-Einladungen: + +1. **Einladung:** festgelegter Nutzerkreis schreibt den Bot an → Invite-Link wird generiert +2. **Initiales Limit:** Gast-Account läuft nach **3 Tagen** automatisch ab +3. **Permanente Freischaltung:** nur durch aktive Admin-Prüfung; sonst bleibt der Account deaktiviert +4. **Fallback:** ohne greifbaren Admin kann der einladende Kreis den Account über den Bot **max. 2× um je 1 Tag** reaktivieren, danach zwingend Admin + +## Architektur-Realitätscheck (Stack-Gegebenheiten) + +- Registrierung läuft in diesem Stack **ausschließlich über Authentik** (MAS-OIDC; die `matrix-invitation`-Flow-Infrastruktur mit Invitation-Stage existiert bereits aus Issue #7!). Der natürliche Invite-Link ist also ein **Authentik-Invitation-Token** (single-use, mit Ablauf) — kein Synapse-Registration-Token. +- **Draupnir** ist ein Moderations-Bot ohne Invite-/Lifecycle-Funktion — er kann Policy-seitig flankieren (Gast-Raumrechte), aber die Link-Generierung + Ablauf-/Reaktivierungslogik braucht einen **kleinen eigenen Bot** (Machart wie @alerts/maintenance-notify: Stdlib, Matrix-API + Authentik-API + MAS/Authentik-Deaktivierung). Empfehlung: eigener `@concierge`-Bot statt Draupnir-Verbiegung; Draupnir-Integration als Stufe 2 (z. B. Gast-Label → eingeschränkte Räume). +- **Ablauf/Deaktivierung:** Authentik-User-Attribut `expires_at` + periodischer Bot-Check (deaktiviert via Authentik-API → MAS-Sessions enden); Reaktivierungszähler als User-Attribut (max 2), Admin-Freischaltung = Attribut entfernen + Gruppe `members`. +- **Berechtigter Nutzerkreis:** Matrix-Raum als ACL (wer im `#einladungen`-Raum ist, darf den Bot nutzen) — einfach und sichtbar. + +## Offene Designfragen (sorb) +- Wer ist der „festgelegte Nutzerkreis" initial? Eigener Raum ok? +- Soll die Admin-Prüfung im Matrix-Raum bestätigt werden (Reaktion/Kommando) oder in der Authentik-UI? +- Namens-/Branding-Wunsch für den Bot? + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#50` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0082-gitops-49-cve-alarme-eine-matrix-nachricht-pro-cve-flut.md b/docs/issues/0082-gitops-49-cve-alarme-eine-matrix-nachricht-pro-cve-flut.md new file mode 100644 index 0000000..e7d125e --- /dev/null +++ b/docs/issues/0082-gitops-49-cve-alarme-eine-matrix-nachricht-pro-cve-flut.md @@ -0,0 +1,55 @@ +--- +type: issue +id: "0082" +status: open +created: 2026-08-01 +milestone: M1 +priority: high +projekt: gitops +gitlab_iid: "49" +related: [] +--- +# CVE-Alarme: eine Matrix-Nachricht pro CVE flutet den Security-Raum -- Zustellung derzeit stumm + +> Adoptiert aus [gitops#49](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/49) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Aus dem Deploy von #47 (2026-08-01). Die Pipeline sammelt Daten, **die Alarm-Zustellung ist aber abgeklemmt**: in `monitoring/alertmanager/alertmanager.yml` routet `room="security"` auf einen Null-Receiver (Commit `2b715ca`). + +## Warum + +`TrivyCriticalVuln` und `TrivyHighVuln` erzeugen eine Alarm-Instanz **pro CVE pro Image**. Gemessen am ersten Scan-Durchlauf, bei 14 von 29 Images: + +| | Anzahl | +|---|---| +| CRITICAL (feuert sofort, kein `for:`) | 59 | +| HIGH (`for: 24h`) | 445 | + +Hochgerechnet auf alle 29 Images grob 120 CRITICAL / 900 HIGH. + +`group_by: [alertname, instance]` legt alle in *eine* Gruppe -> ein Webhook-POST mit ~120 Alarmen. `matrix-alerts.py` schickt daraus **eine Matrix-Nachricht pro Alarm**, sequenziell. + +## Was es zur Schleife macht + +`save_state()` steht in `do_POST` **hinter** der Sende-Schleife. Sobald ein Send fehlschlaegt -- Synapse rate-limitet `rc_message` per Default nach ~10 Nachrichten mit 429 -- fliegt die Exception, der State wird **nicht** gespeichert, der Receiver antwortet 502. Alertmanager wiederholt daraufhin die komplette Gruppe, und die Fingerprint-Deduplizierung (`if fp in state: continue`), die genau das verhindern soll, ist beim Retry noch leer. Das wiederholt sich, statt einmalig durchzulaufen. + +## Zum Scharfschalten noetig + +1. **Zustellung buendeln.** Entweder `matrix-alerts.py` auf eine Sammelnachricht pro Webhook-Batch umbauen (die fuenf Pflichtfelder je CVE als eine Zeile -- bleibt vollstaendig), oder die Regeln auf `count by (target, severity)` aggregieren und die CVE-Details im Dashboard lassen. +2. **State inkrementell speichern**, nach jedem erfolgreichen Send, plus 429-Behandlung mit `Retry-After`. + +Danach die `room="security"`-Route aus `alertmanager.yml` entfernen. + +## Kleinere Punkte aus demselben Review + +- `TrivyScanStale` kann ein Image, das **nie** erfolgreich gescannt wurde, nicht melden: ohne ersten Report gibt es keine Serie, an der `time() - trivy_last_scan_timestamp` haengen koennte. Ein dauerhaft fehlschlagendes Image bleibt still; `TargetDown` deckt nur den toten Exporter ab. +- Der Exporter prunt den First-Seen-State bei **jedem** Scrape. Ein transienter Lesefehler (`except: continue`) loescht die Erstfund-Zeitstempel des betroffenen Targets dauerhaft. +- `coturn/coturn:latest` ist als einziges Image ungepinnt (schon in #47 notiert). + +## Nicht betroffen + +Scanner, Exporter, Scrape-Job und Dashboard laufen und sind verifiziert -- Exporter-Last 0,4 s pro Scrape fuer 29 Reports, unkritisch bei 15 s Intervall. Details im `monitoring/README.md`. + + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#51` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0083-gitops-50-monitoring-deploy-geaenderte-configs-greifen.md b/docs/issues/0083-gitops-50-monitoring-deploy-geaenderte-configs-greifen.md new file mode 100644 index 0000000..168e495 --- /dev/null +++ b/docs/issues/0083-gitops-50-monitoring-deploy-geaenderte-configs-greifen.md @@ -0,0 +1,61 @@ +--- +type: issue +id: "0083" +status: open +created: 2026-08-01 +milestone: M1 +priority: medium +projekt: gitops +gitlab_iid: "50" +related: [] +--- +# Monitoring-Deploy: geaenderte Configs greifen nicht ohne --force-recreate (Inode-Falle bei Einzeldatei-Mounts) + +> Adoptiert aus [gitops#50](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/50) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Beim Deploy von #47 aufgefallen, betrifft aber **jede** Config-Aenderung am Monitoring-Stack. + +## Symptom + +`cd /opt/threadnet-operating && git pull && cd monitoring && docker compose up -d` aktiviert geaenderte Config-Dateien **nicht**. Nach dem Deploy von #47 liefen Scanner und Exporter, aber Prometheus hatte weder den neuen Scrape-Job `cve_exporter` noch die `axion-cve`-Regelgruppe geladen -- `promtool` fand 9 Regeln in der Datei, Prometheus kannte 6. + +## Ursache + +`prometheus.yml`, `alerts.yml` und `alertmanager.yml` sind als **einzelne Dateien** gemountet. Docker haengt so einen Bind-Mount am Inode auf. `git pull` schreibt eine neue Datei und benennt sie um -- neuer Inode. Der Container zeigt weiter auf die alte Datei. + +Zwei Effekte, die es schwer sichtbar machen: + +- `docker compose up -d` startet die Container nicht neu, weil die Service-Definition unveraendert ist. Es meldet `Running` und sieht erfolgreich aus. +- Ein `SIGHUP`-Reload laedt brav neu -- nur eben den **alten** Inhalt. Kein Fehler im Log. + +Auf der Platte steht also die neue Config, im Container die alte, und nichts meldet einen Fehler. + +## Nachweis + +``` +$ grep -c axion-cve monitoring/prometheus/alerts.yml # 1 +$ docker exec prometheus grep -c axion-cve /etc/prometheus/alerts.yml # 0 +``` + +## Abhilfe + +Nach jedem `git pull`, der eine dieser Dateien anfasst: + +```bash +docker compose up -d --force-recreate prometheus alertmanager +``` + +Verifikation muss **im Container** stattfinden, ein Blick auf die Platte beweist nichts. + +## Nicht betroffen + +Verzeichnis-Mounts (`grafana/provisioning/`, `grafana/dashboards/`) loesen ueber den Pfad auf und ziehen Aenderungen mit. Grafana liest **Provider-Definitionen** aber nur beim Start -- ein neuer Dashboard-Ordner braucht `docker compose restart grafana`. Dashboard-JSONs innerhalb eines bestehenden Providers werden laufend nachgezogen. + +## Moegliche Dauerloesung + +Statt Einzeldateien die Verzeichnisse mounten (`./prometheus:/etc/prometheus:ro`), dann verschwindet die Inode-Falle. Dokumentiert ist der Fallstrick vorerst in `monitoring/README.md` (Commit `2b715ca`). + + +--- +*Migriert aus Gitea `sorb/axion1337.chat-gitops#52` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0084-gitops-51-ci-canonize-token-fuer-die-automatische-turn.md b/docs/issues/0084-gitops-51-ci-canonize-token-fuer-die-automatische-turn.md new file mode 100644 index 0000000..fcaada9 --- /dev/null +++ b/docs/issues/0084-gitops-51-ci-canonize-token-fuer-die-automatische-turn.md @@ -0,0 +1,45 @@ +--- +type: issue +id: "0084" +status: next +created: 2026-08-02 +milestone: M1 +priority: medium +due: 2026-09-01 +projekt: gitops +gitlab_iid: "51" +related: [] +--- +# CI: CANONIZE_TOKEN für die automatische TURN-Rotation hinterlegen + +> Adoptiert aus [gitops#51](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/51) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Der Job `canonize_rotation` in `.gitlab-ci.yml` übernimmt die monatliche TURN-Rotation automatisch (kein Handgriff mehr, kein Kalendereintrag). Der Schedule läuft, zwei Probeläufe sind durch — **es fehlt nur noch das Push-Token.** + +## Was zu tun ist (2 Minuten, braucht deine Rechte) + +1. *Settings → Access Tokens* in diesem Projekt: Token anlegen + - Name z. B. `canonize-rotation` + - Rolle **Maintainer** (nötig, weil `main` protected ist) + - Scope **`write_repository`** — mehr nicht + - Ablauf: setzen und im Kalender vormerken, sonst steht der Job irgendwann still +2. *Settings → CI/CD → Variables*: Variable **`CANONIZE_TOKEN`** mit dem Wert, **masked** und **protected** + +Danach nichts weiter — der nächste Lauf nimmt sie von selbst. + +## Warum das nötig ist + +Der Rotations-CronJob läuft im Cluster und erreicht git.lab nicht; er pusht seinen Branch nach Gitea. Von dort muss die Rotation über git.lab zurück, sonst überschreibt sie der nächste Mirror-Push und Flux spielt still das **alte** Shared Secret wieder ein — ein Fehler, der kein Symptom erzeugt. + +## Stand + +| | | +|---|---| +| Job + Doku | ✅ `02c60cb`, CLAUDE.md in beiden Repos | +| Schedule (täglich 17:05) | ✅ angelegt | +| Probelauf | ✅ Pipeline 161 grün: „Keine offene Rotation" | +| `CANONIZE_TOKEN` | ⬜ **dieses Issue** | + +Bis dahin ist nichts kaputt: Ohne offene Rotation läuft der Job grün durch. Erst wenn am 01.09. wirklich rotiert wird und das Token fehlt, bricht er ab — laut und sichtbar, statt still das Falsche zu tun. + +Nebenbei aufgefallen: Der Branch `turn-secret-rotation-20260728-192656` liegt auf git.lab und Gitea, steckt aber längst in `main` — eine Karteileiche vom Juli. Kann weg, ist aber harmlos. diff --git a/docs/issues/0085-gitops-52-docs-traegt-zwei-altbestaende-abgeschlossener.md b/docs/issues/0085-gitops-52-docs-traegt-zwei-altbestaende-abgeschlossener.md new file mode 100644 index 0000000..b039317 --- /dev/null +++ b/docs/issues/0085-gitops-52-docs-traegt-zwei-altbestaende-abgeschlossener.md @@ -0,0 +1,14 @@ +--- +type: issue +id: "0085" +status: open +created: 2026-08-02 +milestone: M2 +priority: low +projekt: gitops +gitlab_iid: "52" +related: [] +--- +# docs/ trägt zwei Altbestände abgeschlossener Umzüge: TASKS.md und oldwiki/ + +> Adoptiert aus [gitops#52](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/52) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. diff --git a/docs/issues/0086-gitops-53-k8s-ressourcen-heissen-noch-element-web-docs.md b/docs/issues/0086-gitops-53-k8s-ressourcen-heissen-noch-element-web-docs.md new file mode 100644 index 0000000..f1e373c --- /dev/null +++ b/docs/issues/0086-gitops-53-k8s-ressourcen-heissen-noch-element-web-docs.md @@ -0,0 +1,14 @@ +--- +type: issue +id: "0086" +status: open +created: 2026-08-02 +milestone: M4 +priority: low +projekt: gitops +gitlab_iid: "53" +related: [] +--- +# k8s-Ressourcen heißen noch element-web-docs (Rest des ThreadNet-Rebrands) + +> Adoptiert aus [gitops#53](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/53) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. diff --git a/docs/issues/0087-gitops-55-logo-fuer-die-authentik-anmeldemaske-entwerfe.md b/docs/issues/0087-gitops-55-logo-fuer-die-authentik-anmeldemaske-entwerfe.md new file mode 100644 index 0000000..02be79d --- /dev/null +++ b/docs/issues/0087-gitops-55-logo-fuer-die-authentik-anmeldemaske-entwerfe.md @@ -0,0 +1,34 @@ +--- +type: issue +id: "0087" +status: waiting +created: 2026-08-06 +milestone: M4 +priority: low +wartegrund: braucht eine Querformat-Wortmarke als SVG — Design-Arbeit, kein Deployment-Schritt +projekt: gitops +gitlab_iid: "55" +related: [] +--- +# Logo für die Authentik-Anmeldemaske entwerfen (Querformat/SVG) + +> Adoptiert aus [gitops#55](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/55) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Die Anmeldemaske zeigt derzeit wieder **Authentiks eigenes Logo** (`480e281`). Unser Versuch mit `vector-icons/512.png` war unbrauchbar: Authentiks Default ist ein SVG, das sich seiner Box anpasst — ein PNG nimmt dort seine Naturgröße und rendert entsprechend riesig. + +## Was gebraucht wird + +Eine **Wortmarke im Querformat**, wie sie der Slot vorsieht. Vorhanden ist nur Quadratisches: + +- `vector-icons/*.png` im Client — reine Bildmarken, 24 bis 1024 px +- `threadnet-logo-wortmarke.png` — Bildmarke **über** Schriftzug, also gestapelt und ebenfalls quadratisch (512×512). Liegt außerdem im `wiki`-Repo in der Gruppe `homelab`, die **keine Mirrors** hat: von Hetzner aus nicht erreichbar. Sie müsste erst mit dem Client ausgeliefert werden. + +Ein SVG wäre das Richtige — dann passt es sich wie Authentiks eigenes an und die Größenfrage stellt sich nicht mehr. + +## Wo es eingetragen wird + +`branding_logo` im Brand-Blueprint, `apps/authentik/authentik-blueprints.yaml`. + +⚠️ **Nicht über die Authentik-Oberfläche.** Solange die Zeile im Blueprint steht, gewinnt sie: eine Auswahl in der UI ist bis zur nächsten Reconciliation sichtbar und danach wieder weg. Steht im Kommentar an der Stelle. + +Gehört inhaltlich zu management#29 (UI harmonisieren). diff --git a/docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md b/docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md new file mode 100644 index 0000000..8695f40 --- /dev/null +++ b/docs/issues/0088-gitops-56-networkpolicy-ausgehender-verkehr-ist-unbesch.md @@ -0,0 +1,35 @@ +--- +type: issue +id: "0088" +status: open +created: 2026-08-06 +milestone: M1 +priority: medium +projekt: gitops +gitlab_iid: "56" +related: [] +--- +# NetworkPolicy: ausgehender Verkehr ist unbeschränkt (13 Ingress-Regeln, 1 Egress) + +> Adoptiert aus [gitops#56](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/56) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +In `apps/production/networkpolicy.yaml` stehen **13 Ingress-Regeln und genau ein Egress-Vorkommen**. Eingehend ist der Cluster dicht, ausgehend ist er offen: Jeder Pod darf ins Internet, in andere Namespaces und an den Metadaten-Dienst. + +## Warum das zählt + +Die Ingress-Regeln verhindern, dass jemand *hineinkommt*. Sie verhindern nicht, dass etwas, das schon drin ist, **hinausredet** — Daten abfließen lässt, Schadcode nachlädt oder sich zu einem Command-and-Control-Server verbindet. Genau das ist der Schritt, der aus einer kompromittierten Abhängigkeit einen Vorfall macht. + +Besonders relevant hier, weil wir **fremden Code ausführen**: Synapse-Module, ClamAV, Draupnir, dazu eine große npm-Abhängigkeitskette im Client-Build. + +## Was zu tun ist + +1. Ist-Zustand aufnehmen: welche Pods brauchen wirklich ausgehende Verbindungen und wohin (Föderation, Let's Encrypt, Container-Registries, IONOS-API, Matrix-Push-Gateways). +2. `policyTypes: [Egress]` mit Default-Deny je Namespace, dann gezielt freigeben. +3. ⚠️ **DNS zuerst freigeben** (`kube-dns`/CoreDNS, UDP+TCP 53) — sonst steht alles, und der Fehler sieht aus wie ein Anwendungsproblem, nicht wie eine Firewall. +4. Föderation ist der schwierige Teil: Synapse muss zu beliebigen Matrix-Servern hinaus. Das lässt sich nicht auf eine Liste eingrenzen, solange die Föderation offen ist (gitops#17) — eher über einen Egress-Proxy oder bewusst offen lassen und dokumentieren. + +## Rollback + +NetworkPolicies sind additiv und einzeln löschbar. Der Not-Aus ist das Entfernen der Default-Deny-Regel. + +*Gefunden am 2026-08-06 bei einer Bestandsaufnahme der Sicherheitslage.* diff --git a/docs/issues/0089-gitops-58-eigene-images-sind-unsigniert-beim-deploy-pru.md b/docs/issues/0089-gitops-58-eigene-images-sind-unsigniert-beim-deploy-pru.md new file mode 100644 index 0000000..a5975b9 --- /dev/null +++ b/docs/issues/0089-gitops-58-eigene-images-sind-unsigniert-beim-deploy-pru.md @@ -0,0 +1,35 @@ +--- +type: issue +id: "0089" +status: open +created: 2026-08-06 +milestone: M5 +priority: low +projekt: gitops +gitlab_iid: "58" +related: [] +--- +# Eigene Images sind unsigniert — beim Deploy prüft nichts die Herkunft + +> Adoptiert aus [gitops#58](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/58) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Wir bauen eigene Images (`threadnet-web`, `clamav-http-scanner`, `desktop-build`) und schieben sie in die Gitea-Registry auf rohana. **Beim Deploy prüft nichts, ob das Image wirklich aus unserer CI stammt.** Kein cosign, keine Provenance, keine Admission-Prüfung. Der Tag ist die einzige Zusicherung — und ein Tag lässt sich überschreiben. + +## Warum das hier konkreter ist als in vielen Setups + +Der Weg ist lang und hat mehrere Stellen, an denen etwas eingeschleust werden könnte: git.lab baut → Push in die Gitea-Registry auf rohana → Flux zieht von dort → K3s startet es. Wer Schreibzugriff auf die Registry hat, kann einen Tag umbiegen, und im Cluster fällt es nicht auf. + +Verwandt: gitops#16 (Pod Security Admission) — beides braucht am Ende einen Admission-Controller, das lässt sich in einem Zug denken. + +## Was zu tun ist + +1. In der CI nach dem Push mit **cosign** signieren (keyless über den GitLab-OIDC-Token, oder Schlüsselpaar als CI-Variable). +2. Im Cluster verifizieren — über einen Policy-Controller (Kyverno oder die Sigstore-Policy-Controller-Variante). Das ist der Teil mit der Arbeit. +3. ⚠️ **Reihenfolge beachten:** erst signieren und eine Weile mitlaufen lassen, dann erzwingen. Wer Verifikation aktiviert, bevor alle Images signiert sind, legt den Cluster still. +4. Fremd-Images (ESS-Chart, Authentik, Traefik) können nicht mit unserem Schlüssel signiert sein — die Richtlinie muss also nach Registry/Repository unterscheiden. + +## Ehrliche Einordnung + +`priority:low`. Das Risiko ist real, aber der Aufwand ist ein Policy-Controller plus Signaturkette, und der Angreifer bräuchte bereits Schreibzugriff auf unsere Registry. Andere Lücken aus derselben Bestandsaufnahme (Egress, Admin-MFA, Restore) kosten weniger und schützen mehr. + +*Gefunden am 2026-08-06 bei einer Bestandsaufnahme der Sicherheitslage.* diff --git a/docs/issues/0090-gitops-59-kein-kubernetes-audit-log-zugriffe-an-der-api.md b/docs/issues/0090-gitops-59-kein-kubernetes-audit-log-zugriffe-an-der-api.md new file mode 100644 index 0000000..3340ad0 --- /dev/null +++ b/docs/issues/0090-gitops-59-kein-kubernetes-audit-log-zugriffe-an-der-api.md @@ -0,0 +1,34 @@ +--- +type: issue +id: "0090" +status: open +created: 2026-08-06 +milestone: M5 +priority: low +projekt: gitops +gitlab_iid: "59" +related: [] +--- +# Kein Kubernetes-Audit-Log — Zugriffe an der API werden nicht protokolliert + +> Adoptiert aus [gitops#59](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/59) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +`auditd` (gitops#26) protokolliert Dateizugriffe und Syscalls **auf dem Host**. Was jemand über die **Kubernetes-API** getan hat — Secret gelesen, Deployment geändert, in einen Pod exec-t — steht dort nicht. Dafür gibt es das Audit-Log des API-Servers, und das ist bei uns nicht konfiguriert. + +## Warum das gerade hier fehlt + +Zwei Dinge treffen zusammen: + +- **ADR-0008** hält fest, dass Agenten-Sessions auf CFGMON root-äquivalent über die docker-Gruppe laufen und dabei **keinen Eintrag in `auth.log`** hinterlassen. Die ADR nennt als Ersatz ausdrücklich Git-Historie, Issues und AARs. +- Im Cluster gibt es dieselbe Lücke eine Ebene höher: Wer `kubectl` benutzt, hinterlässt nichts. + +Solange alles über Flux und Git läuft, ist die Git-Historie tatsächlich das Protokoll. Der Punkt ist der Zugriff **daneben** — und genau der ist heute unsichtbar. + +## Was zu tun ist + +1. Audit-Policy schreiben (K3s: `--kube-apiserver-arg=audit-policy-file=…` plus `audit-log-path`). ⚠️ Das ist eine **Host-Änderung am K3s-Dienst**, kein Flux-Objekt — gehört zu `host-config/`. +2. Auf `Metadata` als Grundstufe beginnen und Secret-Zugriffe auf `RequestResponse` heben. Alles auf `RequestResponse` erzeugt riesige Logs **und schreibt Secret-Inhalte im Klartext ins Protokoll** — genau das nicht tun. +3. Über Alloy nach Loki einsammeln, damit es nicht nur auf der Platte liegt. +4. Sinnvoll zusammen mit gitops#25 (K3s API Hardening) — dieselbe Datei, derselbe Neustart. + +*Gefunden am 2026-08-06 bei einer Bestandsaufnahme der Sicherheitslage.* diff --git a/docs/issues/0091-gitops-61-enrollment-kollidierender-localpart-uebernimm.md b/docs/issues/0091-gitops-61-enrollment-kollidierender-localpart-uebernimm.md new file mode 100644 index 0000000..c709f97 --- /dev/null +++ b/docs/issues/0091-gitops-61-enrollment-kollidierender-localpart-uebernimm.md @@ -0,0 +1,78 @@ +--- +type: issue +id: "0091" +status: open +created: 2026-08-11 +milestone: M1 +priority: high +area: security +projekt: gitops +gitlab_iid: "61" +related: + - "docs/adr/0011-enrollment-localpart-kollision-verweigern.md" +--- +# Enrollment: kollidierender Localpart übernimmt bestehendes Konto (on_conflict: add) + +> Adoptiert aus [gitops#61](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/61) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. +> Bei der Adoption ergänzt: Meilenstein M1 (fehlte auf GitLab); von den zwei +> area-Labels trägt das Schema eines — `security` bleibt, `authentik` entfällt. + +## Befund + +Der MAS-Upstream-Provider für Authentik verknüpfte eine neu registrierte +Upstream-Identität mit einem **bestehenden** lokalen Konto, sobald der +abgeleitete Localpart kollidiert: + +```yaml +claims_imports: + localpart: + action: force + template: "{{ user.preferred_username }}" + on_conflict: add # <-- verknüpft statt abzubrechen +``` + +Zusammen mit Authentiks Benutzernamen-Eindeutigkeit, die **nur innerhalb von +Authentik** und **case-sensitive** greift, ergibt sich ein Übernahmeweg: + +1. Ein Inhaber eines Einladungstokens registriert in Authentik einen Namen, der + als Matrix-Konto bereits existiert (oder eine Groß-/Kleinschreibungsvariante + davon — `boje` neben `Boje` ging live durch). +2. Authentiks Eindeutigkeit meldet keine Kollision, weil das Ziel-Matrix-Konto + für Authentik unsichtbar ist bzw. sich in der Schreibweise unterscheidet. +3. Beim ersten Login verknüpft MAS die neue Identität mit dem bestehenden Konto + — inklusive Räumen und Historie. + +**Besonders exponiert:** Konten ganz ohne Upstream-Link, weil dort nichts +vorher da sein muss. Betroffen wären u. a. die Dienstkonten `draupnir`, +`alerts`, `maintenance-notify` sowie `frank`, `crank`, `shank`, `stank`, +`bojeledoggo`, `scanner-test`. + +> Der Übernahmeweg wurde **nicht** aktiv ausprobiert (das wäre eine echte +> Kontoübernahme gewesen). Die Aussage stützt sich auf MAS' dokumentierte +> Semantik für `on_conflict` und auf die live reproduzierte case-sensitive +> Dublette `boje`/`Boje`. + +## Wie es aufgefallen ist + +Beim Anlegen eines Testkontos über den Einladungsflow entstand versehentlich +ein zweites Konto `boje` neben dem bestehenden `Boje` — kein Fehler, keine +Warnung. Die Nachprüfung der MAS-Claims-Konfiguration legte `on_conflict: add` +als Ursache offen. + +## Fix (erledigt) + +`on_conflict: fail` in `apps/production/custom-configs/mas-secret.yaml` — ein +kollidierender Localpart bricht die Provisionierung ab, statt zu verknüpfen. +Bestehende Verknüpfungen bleiben unberührt. + +Commit `ef04d86`, gepusht nach git.lab. Rollt über Flux aus. + +## Rest, bewusst offen + +- **Authentiks case-sensitive Eindeutigkeit** verhindert `boje` neben `Boje` + weiterhin nicht. Der MAS-Fix fängt die Übernahme ab (Login schlägt fehl statt + zu verknüpfen), aber der Nutzer bekommt erst beim Login eine Fehlermeldung, + nicht schon bei der Registrierung. Eine Eindeutigkeitsprüfung (case-insensitive) + im Prompt-Stage des `matrix-invitation`-Flows wäre die saubere Ergänzung. +- **Verwaiste Zweitkonten** aus dieser Lücke (`apo2`, das gelöschte `boje`) + sind Altlasten, keine offene Verwundbarkeit. diff --git a/docs/issues/0092-threadnet-web-1-default-client-einstellungen-theme-features-f.md b/docs/issues/0092-threadnet-web-1-default-client-einstellungen-theme-features-f.md new file mode 100644 index 0000000..0a281cc --- /dev/null +++ b/docs/issues/0092-threadnet-web-1-default-client-einstellungen-theme-features-f.md @@ -0,0 +1,49 @@ +--- +type: issue +id: "0092" +status: waiting +created: 2026-07-29 +milestone: M3 +priority: low +wartegrund: wartet auf Entscheidung, welche Defaults verbindlich gelten sollen +projekt: threadnet-web +gitlab_iid: "1" +related: [] +--- +# Default-Client-Einstellungen (Theme, Features) für Neuinstallationen provisionieren + +> Adoptiert aus [threadnet-web#1](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/1) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Neue Nutzer (egal ob Web-Client, installierte PWA oder Electron-Desktop) sollten mit +den für axion1337.chat gedachten Standardeinstellungen starten - nicht mit den generischen +Element-Defaults. Konkret betrifft das mindestens: + +- **Theme**: `default_theme` ist im Web-Deployment bereits gesetzt (`aXion1337 Dark`, via + `element-values.yaml`) - muss für Electron-Builds ebenso gelten, ist dort aber nicht + eigenständig provisioniert. +- **Custom Features** (z.B. die Discord-Style-Raumliste): falls das ein Feature ist, das alle + Nutzer standardmäßig sehen sollen, muss geprüft werden, ob es aktuell hinter einem + Labs-Flag/einer manuellen Einstellung versteckt ist, die neue Nutzer nicht automatisch + bekommen. +- **Sonstige sinnvolle Defaults** (Benachrichtigungen, Video-Qualität, etc.) - einmal + durchgehen, was aktuell nur "zufällig" beim Entwickeln richtig eingestellt ist, statt + bewusst als Default für alle Nutzer konfiguriert. + +**Konkreter Fund, der das Problem sichtbar gemacht hat** (beim manuellen Electron-Build, +siehe Release `desktop-v1.12.17-clientscan`): es gibt in `apps/desktop` keinen eigenen +Config-Variant-Ordner für unsere Instanz (wie `element.io/release`/`element.io/nightly`) - +das produktiv genutzte `config.json` musste manuell aus dem laufenden Pod kopiert werden, um +den generischen `config.sample.json`-Platzhalter zu ersetzen. Ohne eigenen Variant-Ordner +wiederholt sich das bei jedem zukünftigen Desktop-Build. + +**Vorschlag**: +1. Eigenen Config-Variant-Ordner anlegen (z.B. `apps/desktop/element.io/axion1337/`) mit + `config.json` (Server-URL, Theme, gewünschte Default-Features) + `build.json` (Branding). +2. Web-seitige `element-values.yaml`-Config und Desktop-Variant synchron halten, damit beide + Clients dieselben Defaults haben. +3. Bewusste Entscheidung pro Feature/Setting treffen: soll es Default sein oder optional + bleiben - und das dokumentieren, statt es implizit zu lassen. + +--- +*Migriert aus Gitea `sorb/ThreadNet-Web#1` — dort erstellt am 2026-07-29 von sorb.* + diff --git a/docs/issues/0093-threadnet-web-3-settings-normalisieren-video-audio-einstellun.md b/docs/issues/0093-threadnet-web-3-settings-normalisieren-video-audio-einstellun.md new file mode 100644 index 0000000..c508f5f --- /dev/null +++ b/docs/issues/0093-threadnet-web-3-settings-normalisieren-video-audio-einstellun.md @@ -0,0 +1,51 @@ +--- +type: issue +id: "0093" +status: open +created: 2026-07-29 +milestone: M4 +priority: medium +projekt: threadnet-web +gitlab_iid: "3" +related: [] +--- +# Settings normalisieren: Video/Audio-Einstellungen nur im Call-Widget, nicht im Haupt-Client + +> Adoptiert aus [threadnet-web#3](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/3) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Beim Durchgehen der Einstellungs-Oberflächen aufgefallen: Element Web (der +Haupt-Client) und Element Call (das eingebettete Widget) haben **getrennte, sich teils +überschneidende Settings-UIs** für Audio/Video, ohne erkennbare Synchronisation. + +**Konkreter Ist-Zustand**: +- Element Web hat einen eigenen "Voice & Video"-Tab + (`apps/web/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx`) mit: + Audio-Eingabe-/Ausgabegerät, Video-Eingabegerät, sowie Echo-Cancellation/Noise-Suppression/ + Auto-Gain-Toggles. +- Element Call (unser Fork, `threadnet-call`) hat im "Video"-Tab (heute erweitert, + Issue #8/#11-Kontext) eigene `AudioProcessingSettings` (dieselben drei Audio-Toggles!) UND + die `MediaQualitySettings` (Auflösung/Framerate/Bitrate/Codec für Kamera + Screen-Share). +- **Überschneidung**: die Echo/Noise/Gain-Toggles existieren scheinbar an beiden Stellen als + getrennte Settings-Objekte (unterschiedliche `SettingLevel`/Storage-Mechanismen je nach + Codebasis) - unklar, ob sie synchron bleiben oder sich widersprechen können. +- **Lücke**: die Video-Qualitätseinstellungen (Auflösung/Framerate/Bitrate/Codec) gibt es + **nur** im Call-Widget. Ein Nutzer, der seine Präferenzen vorab einstellen will (ohne + gerade in einem Call zu sein), findet dafür nichts im Haupt-Client - müsste dafür erst + einen Call starten/das Widget öffnen. + +**Mehrwert einer Normalisierung**: konsistente, einmal auffindbare Einstellungen statt +zwei getrennter Orte mit potenziell widersprüchlichem Zustand. Nutzer erwarten +Video-Qualitätseinstellungen vermutlich eher im Haupt-Client als im Widget. + +**Zu klären/umzusetzen** (spannt vermutlich beide Repos, `ThreadNet-Web` + `threadnet-call`): +1. Bestandsaufnahme: teilen sich die Audio-Toggles bereits denselben Storage-Mechanismus + (z.B. beide über Matrix-Account-Data) oder sind das wirklich zwei unabhängige Zustände? +2. Video-Qualitätseinstellungen: entweder in Element Webs eigenen "Voice & Video"-Tab + duplizieren (mit Sync zum Widget) oder zumindest einen Link/Verweis vom Haupt-Client zum + Call-Widget-Setting ergänzen, damit sie auffindbar sind, ohne aktiv in einem Call zu sein. +3. Grundsatzentscheidung: sollen beide UIs langfristig dieselben Setting-Objekte teilen + (echte Normalisierung), oder reicht ein Verweis/Link als pragmatischere Zwischenlösung? + +--- +*Migriert aus Gitea `sorb/ThreadNet-Web#3` — dort erstellt am 2026-07-29 von sorb.* + diff --git a/docs/issues/0094-threadnet-web-4-direkter-link-zur-2fa-passkey-einrichtung-in.md b/docs/issues/0094-threadnet-web-4-direkter-link-zur-2fa-passkey-einrichtung-in.md new file mode 100644 index 0000000..9c45b18 --- /dev/null +++ b/docs/issues/0094-threadnet-web-4-direkter-link-zur-2fa-passkey-einrichtung-in.md @@ -0,0 +1,47 @@ +--- +type: issue +id: "0094" +status: open +created: 2026-07-29 +milestone: M3 +priority: medium +projekt: threadnet-web +gitlab_iid: "4" +related: [] +--- +# Direkter Link zur 2FA/Passkey-Einrichtung in den Account-Settings + +> Adoptiert aus [threadnet-web#4](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/4) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Übernommen aus gitops-Repo Issue #13 (dort geschlossen, siehe Verweis) - nach Testen +der Alternativen jetzt hier richtig verortet. + +**Ausgangsproblem**: 2FA/Passkey-Selbsteinrichtung (`default-authenticator-totp-setup`/ +`-webauthn-setup`, Authentik-Flow-Stages) ist aktuell nur über +`axion1337.chat/docs/setup/security.html` auffindbar, nicht direkt in den Account-Settings, +wo Nutzer sie erwarten würden. + +**Geprüfte und verworfene Alternative**: MAS's OIDC-`account_management_uri`-Mechanismus +(den Element Web bereits über `externalAccountManagementUrl` in +`apps/web/src/components/views/settings/tabs/user/AccountUserSettingsTab.tsx` nutzt, aktuell +für den generischen "Konto verwalten"-Link zu MAS) unterstützt **keine** 2FA/TOTP/Passkey- +Deep-Link-Action. Live geprüft via +`https://account.axion1337.chat/.well-known/openid-configuration` → +`account_management_actions_supported`: nur `profile`, `devices_list`, `device_view`, +`device_delete`, `cross_signing_reset`, `sessions_list`, `session_view`, `session_end`. +Ergibt architektonisch Sinn - MAS delegiert 2FA komplett an Authentik als Upstream-SSO und +kennt selbst kein "TOTP einrichten"-Konzept. + +Ein MAS-Template-Fork (Askama/Tera, `templates.path`) wurde ebenfalls verworfen (mehr +Aufwand/Wartungsrisiko als eine Client-Änderung, siehe ursprüngliche Diskussion in +gitops#13). + +**Vorschlag**: einfacher, direkter Link (kein OIDC-Mechanismus nötig) - ein zusätzlicher +Button/Link neben dem bestehenden "Konto verwalten"-Link in `AccountUserSettingsTab.tsx` +(oder alternativ `SecurityUserSettingsTab.tsx`), der direkt auf Authentiks eigene +Setup-Seite(n) zeigt (`default-authenticator-totp-setup`/`-webauthn-setup`). Statische URL, +über Config konfigurierbar, kein Forken von MAS-Templates nötig. + +--- +*Migriert aus Gitea `sorb/ThreadNet-Web#4` — dort erstellt am 2026-07-29 von sorb.* + diff --git a/docs/issues/0095-threadnet-web-6-windows-desktop-code-signing-installer-brandi.md b/docs/issues/0095-threadnet-web-6-windows-desktop-code-signing-installer-brandi.md new file mode 100644 index 0000000..182373c --- /dev/null +++ b/docs/issues/0095-threadnet-web-6-windows-desktop-code-signing-installer-brandi.md @@ -0,0 +1,28 @@ +--- +type: issue +id: "0095" +status: open +created: 2026-07-31 +milestone: M4 +priority: low +projekt: threadnet-web +gitlab_iid: "6" +related: [] +--- +# Windows-Desktop: Code-Signing (+ Installer-Branding) + +> Adoptiert aus [threadnet-web#6](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/6) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Der Windows-Build (Issue #5, jetzt geschlossen) liefert eine **unsignierte** NSIS-Exe — funktional, aber SmartScreen warnt beim Install. Optionen (aus #5 übernommen, Stand 2026-07-31): + +1. **Azure Trusted Signing** (~10 $/Monat) — günstigster seriöser Weg, EV-äquivalente SmartScreen-Reputation, braucht Azure-Konto + Identitätsprüfung; electron-builder unterstützt es nativ (`azureSignOptions`). +2. **Certum Open-Source-/OV-Zertifikat** (Smartcard/Token, einmalig ~70–130 €) — klassisch, Token-Handling in CI ist aber fummelig (physischer USB-Token an der Build-VM). +3. **SSL.com eSigner** (Cloud-Signing, teurer, API-freundlich). + +Start unsigniert ist für den Community-Kreis okay; Signing lohnt, sobald der Client breiter verteilt wird. + +Außerdem als Packaging-Feinschliff hier mit erledigen: **Installer-Branding** — aktuell Upstream-„Element Setup" (Default-`VARIANT_PATH` `element.io/release/build.json`); eine aXion-Variante (`apps/desktop/axion1337/`) mit eigenem appId/productName wäre der saubere Abschluss. + +--- +*Migriert aus Gitea `sorb/ThreadNet-Web#6` — dort erstellt am 2026-07-31 von sorb.* + diff --git a/docs/issues/0096-threadnet-web-7-rebranding-element-axion1337-web-desktop-gesa.md b/docs/issues/0096-threadnet-web-7-rebranding-element-axion1337-web-desktop-gesa.md new file mode 100644 index 0000000..f6e90e7 --- /dev/null +++ b/docs/issues/0096-threadnet-web-7-rebranding-element-axion1337-web-desktop-gesa.md @@ -0,0 +1,32 @@ +--- +type: issue +id: "0096" +status: waiting +created: 2026-07-31 +milestone: M4 +priority: medium +wartegrund: Gesamtklammer — appId-Wechsel (neues Profilverzeichnis) muss bewusst entschieden werden +projekt: threadnet-web +gitlab_iid: "7" +related: [] +--- +# Rebranding: Element → aXion1337 (Web + Desktop, Gesamtklammer) + +> Adoptiert aus [threadnet-web#7](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/7) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Sammel-TODO (gewünscht von sorb, 2026-07-31): die Client-Komponenten tragen an etlichen Stellen noch Upstream-Element-Branding. Ziel: konsistentes aXion1337-Branding über Web + Desktop. + +**Ist-Stand:** +- Web: `config.json` setzt bereits `brand: aXion1337.Chat` + eigenes Theme — aber Upstream-Assets (Favicons, Logos, Wortmarke im Onboarding/Auth-Flow) sind noch Element. +- Desktop: Installer heißt „Element Setup" (Default-`VARIANT_PATH` `element.io/release/build.json`), `appId: im.riot.app`, `productName: Element`, Element-Icons, Protokoll-Handler `io.element.desktop`/`element`. + +**Arbeitspakete:** +1. Desktop-Variante `apps/desktop/axion1337/build.json` (eigenes appId/productName/Icons) + `VARIANT_PATH` in den CI-Jobs `desktop_linux`/`desktop_windows` setzen. ⚠️ appId-Wechsel = neues Install-/Profilverzeichnis für Bestandsnutzer (bewusst entscheiden, Migrationsnotiz). +2. Web-Assets: Favicon/Logo/Wortmarke gegen aXion-Varianten tauschen (Upstream-Merge-freundlich: eigene Dateien + Config-Referenzen statt Upstream-Dateien überschreiben, wo möglich). +3. Prüfen, welche Stellen Upstream regelmäßig anfasst (Merge-Reibung minimieren) — Ergebnis hier dokumentieren. + +Teilaspekt Signing/Installer-Branding Windows: siehe #6 (bleibt dort für den Windows-Teil, dieses Issue ist die Gesamtklammer). + +--- +*Migriert aus Gitea `sorb/ThreadNet-Web#7` — dort erstellt am 2026-07-31 von sorb.* + diff --git a/docs/issues/0097-threadnet-web-9-feedback-bugreport-weg-eigener-rageshake-oder.md b/docs/issues/0097-threadnet-web-9-feedback-bugreport-weg-eigener-rageshake-oder.md new file mode 100644 index 0000000..05be165 --- /dev/null +++ b/docs/issues/0097-threadnet-web-9-feedback-bugreport-weg-eigener-rageshake-oder.md @@ -0,0 +1,26 @@ +--- +type: issue +id: "0097" +status: open +created: 2026-08-01 +milestone: M4 +priority: low +projekt: threadnet-web +gitlab_iid: "9" +related: [] +--- +# Feedback-/Bugreport-Weg: eigener Rageshake oder Alternative (Zammad nachhalten) + +> Adoptiert aus [threadnet-web#9](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/9) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Entscheidung sorb (2026-08-01): Der element.io-Rageshake-Endpoint ist aus der Desktop-Config **entfernt** (Commit `697e167`) — greift ab dem nächsten Desktop-Build. Bug-Melden-Knopf entfällt damit vorerst; Feedback läuft direkt über Matrix. + +**Dieses Issue hält den künftigen eigenen Weg nach:** +- **Option 1: eigener Rageshake-Server** (element-hq/rageshake, klein, genau fürs Client-Log-Sammeln gebaut) — Client-Konfig zeigt dann auf uns. +- **Option 2 (sorb ins Spiel gebracht): [Zammad](https://zammad.org)** — vollwertiges Open-Source-Helpdesk/Ticketing. Deutlich mehr als Bug-Reports (Support-Postfach, Wissensbasis, könnte perspektivisch auch den Gäste-/Community-Support tragen), dafür ein ausgewachsener Dienst (Ruby/ES/Redis) mit Pflegeaufwand. Kein direkter Rageshake-Ersatz (nimmt keine automatischen Client-Log-Pakete an), eher eine strategische Ergänzung — ggf. beides: Rageshake für Logs, Zammad für menschliches Feedback. + +Bewertung/Entscheidung bei Gelegenheit; bis dahin bewusst ohne Bug-Reporting. + +--- +*Migriert aus Gitea `sorb/ThreadNet-Web#9` — dort erstellt am 2026-08-01 von sorb.* + diff --git a/docs/issues/0098-threadnet-web-11-themes-rollout-2026-08-02-web-live-linux-wind.md b/docs/issues/0098-threadnet-web-11-themes-rollout-2026-08-02-web-live-linux-wind.md new file mode 100644 index 0000000..41402a2 --- /dev/null +++ b/docs/issues/0098-threadnet-web-11-themes-rollout-2026-08-02-web-live-linux-wind.md @@ -0,0 +1,38 @@ +--- +type: issue +id: "0098" +status: open +created: 2026-08-02 +milestone: M4 +priority: low +projekt: threadnet-web +gitlab_iid: "11" +related: [] +--- +# Themes-Rollout 2026-08-02: Web live, Linux + Windows gebaut, macOS lokal + +> Adoptiert aus [threadnet-web#11](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/11) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Protokoll zum Ausrollen der elf neuen Themes (aXion1337 Light + zehn Paletten, gitops `a2438e1`). + +## Web ✅ live +Flux reconciled auf `a2438e1`; **`https://axion1337.chat/config.json` liefert 17 Themes** — verifiziert, nicht abgeleitet. Keine Pod-Rotation nötig, kein Checksum-Problem (der Fallstrick vom 2026-08-01 trat nicht auf, weil sich nur ConfigMap-Inhalt änderte, den Element beim Laden liest). + +## Desktop-Config `2a2bb37` +Die Desktop-Apps laden ihre **eigene** `config.json` (`apps/desktop/axion1337/config.json`) — ohne diesen Commit hätten sie die neuen Themes nicht. Chirurgisch eingefügt: 0 entfernte / 427 neue Zeilen, JSON validiert. + +## Builds (Pipeline 144) + +| Job | Ergebnis | +|---|---| +| `web` | ✅ 75 s | +| `desktop_linux` | ✅ 428 s — `.deb` + `.tar.gz`, 287 MB Artefakt | +| `desktop_windows` | ✅ 461 s — 135 MB Artefakt | +| `stop_windows_vm` | ausgelöst (8 GB wieder frei) | + +**Verifikation der Linux-Artefakte:** Die Themes stecken in `resources/webapp.asar`, **nicht** in `app.asar` — dort hatte ich zuerst gesucht und fälschlich „fehlt" gemeldet. `webapp.asar` enthält die eingebettete `config.json` mit allen 17 Themes. + +⚠️ `start_windows_vm` scheiterte zunächst (`No such container: windows-runner`), sorb hat den Container manuell neu gestartet — Ursache und Optionen als [management#21](https://git.lab/axion1337.chat/management/-/issues/21) festgehalten. + +## macOS +Wird lokal auf sorbs Mac gebaut (arm64, unsigniert) — kein macOS-Runner im Lab. Ergebnis folgt als Kommentar. diff --git a/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md b/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md new file mode 100644 index 0000000..0b1f101 --- /dev/null +++ b/docs/issues/0099-threadnet-web-12-upstream-sicherheitsfixes-lassen-sich-nicht-m.md @@ -0,0 +1,37 @@ +--- +type: issue +id: "0099" +status: open +created: 2026-08-06 +milestone: M1 +priority: medium +projekt: threadnet-web +gitlab_iid: "12" +related: [] +--- +# Upstream-Sicherheitsfixes lassen sich nicht mergen — kein gemeinsamer Vorfahre + +> Adoptiert aus [threadnet-web#12](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/12) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Am 2026-08-06 gemessen (`docs/axion1337-fork.md`, Abschnitt 4): **Dieses Repo hat keine Upstream-Historie.** Element Web 1.12.17 kam am 2026-05-10 als kompletter Baum herein — in `3da3635`, im selben Commit wie das erste eigene Feature. + +Damit gibt es **keinen gemeinsamen Vorfahren mit `element-hq/element-web`**. `git merge upstream/develop` ist nicht möglich; erzwungen kollidiert praktisch jede Datei. + +## Warum das ein Sicherheitsthema ist, kein Build-Thema + +Element veröffentlicht Sicherheitsfixes als neue Version. Bei einem normalen Fork zieht man sie mit einem Merge. Bei uns bedeutet dasselbe: neuen Upstream-Stand beschaffen und **unsere 12 Patches von Hand neu auftragen** — davon sieben in der Medien-Pipeline, wo Element gerade auf MVVM umbaut. + +Das ergibt eine unangenehme Kette mit gitops#22 (Advisory-Monitoring): Wir würden von einer Lücke erfahren und wären trotzdem langsam. Die Zeitspanne zwischen „bekannt" und „gepatcht" ist das, was zählt — und sie ist hier strukturell zu lang. + +⚠️ Verschärfend: Verschiebt Element beim MVVM-Umbau eine der `viewmodels/`-Dateien, entsteht **kein Konflikt** — unsere Zeilen sind schlicht weg, und Git meldet nichts. + +## Was zu tun ist + +1. **Zuerst messen, nicht bauen:** Auf welchem Stand ist Upstream inzwischen, und sind seit 1.12.17 Sicherheitsfixes für Element Web erschienen? Das beantwortet, ob das dringend ist oder Vorsorge. +2. `element-hq/element-web` als zweiten Remote aufnehmen und den Tag von 1.12.17 holen. Damit lässt sich ein Update wenigstens **als Diff** betrachten, statt blind zu kopieren. +3. Prüfen, ob sich ein gemeinsamer Vorfahre nachträglich herstellen lässt — ein Graft/Replace des Import-Commits auf den passenden Upstream-Tag. Wenn das trägt, sind künftige Updates wieder ein Merge. +4. Falls nicht: einen Ablauf schreiben, wie unsere 12 Patches auf einen neuen Stand aufgetragen werden — mit dem Funktionstest für ClamAV als Abnahme (verschlüsselte Datei senden, abgelehnte empfangen). + +Zusammenhang: gitops#22 (Advisory-Monitoring) ist die Erkennung, dieses Issue die Reaktionsfähigkeit. Das eine nützt wenig ohne das andere. + +*Gefunden am 2026-08-06 beim Vermessen der Merge-Reibung (Arbeitspaket 3 aus #7).* diff --git a/docs/issues/0100-threadnet-web-13-asset-pfade-tragen-weiterhin-element-themes-e.md b/docs/issues/0100-threadnet-web-13-asset-pfade-tragen-weiterhin-element-themes-e.md new file mode 100644 index 0000000..04554b1 --- /dev/null +++ b/docs/issues/0100-threadnet-web-13-asset-pfade-tragen-weiterhin-element-themes-e.md @@ -0,0 +1,57 @@ +--- +type: issue +id: "0100" +status: open +created: 2026-08-07 +milestone: M4 +priority: low +projekt: threadnet-web +gitlab_iid: "13" +related: [] +--- +# Asset-Pfade tragen weiterhin "element" (themes/element/…) + +> Adoptiert aus [threadnet-web#13](https://git.lab/axion1337.chat/ThreadNet-Web/-/issues/13) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +Aufgefallen beim Titelbild-Tausch (sorb, 2026-08-07): Das neue Hintergrundbild liegt unter + +``` +themes/element/img/backgrounds/alpenglow.jpg +``` + +Im Browser sieht man also weiterhin `element` im Pfad, obwohl der Client ThreadNet heißt. + +## Wie weit das reicht + +Betroffene Verzeichnisse im Fork: + +- `apps/web/res/themes/element/` — das Theme-Verzeichnis +- `apps/web/res/img/element-icons/` +- `apps/desktop/element.io/` — Upstreams Varianten-Verzeichnis (unsere liegt daneben in `axion1337/`) + +Verweise darauf im Quelltext: **8 Stellen**, unter anderem + +| Datei | wofür | +|---|---| +| `SdkConfig.ts` | `auth_header_logo_url`, `welcome_background_url` | +| `AuthHeaderLogo.tsx`, `HomePage.tsx` | Fallback-Logo | +| `ErrorView.tsx` | drei Store-Badges | +| `HelpUserSettingsTab.tsx` | Link in der Danksagung | + +⚠️ **Und außerhalb des Repos:** Authentiks Brand zeigt auf +`https://axion1337.chat/themes/element/img/backgrounds/alpenglow.jpg` +(`apps/authentik/authentik-blueprints.yaml`). Eine Umbenennung macht die +**Anmeldeseite grau**, wenn sie nicht in derselben Runde mitgezogen wird — und zwar in dieser Reihenfolge: erst Client bauen und ausrollen, dann Authentik. + +## Warum das mehr kostet, als es aussieht + +1. **`element` ist nicht nur ein Ordnername, sondern der Theme-Bezeichner.** Element Web löst Themes über diesen Pfad auf. Ein Umbenennen ohne vollständiges Nachziehen bricht die Theme-Auflösung — und das fällt erst im Browser auf, nicht im Build. +2. **Merge-Reibung.** `res/themes/element/` ist Upstreams Verzeichnis. Ein umbenanntes Verzeichnis kollidiert bei **jedem** Upstream-Update, das Theme-Assets anfasst — und wir haben ohnehin keinen gemeinsamen Vorfahren (ThreadNet-Web#12). Das verlagert Aufwand in jede künftige Aktualisierung. + +## Ehrliche Einordnung + +`priority:low`. Sichtbar ist es nur in URLs — Rechtsklick auf das Bild, Entwicklerwerkzeuge, geteilte Links. Kein Nutzer stolpert im normalen Betrieb darüber. Es ist Politur, und sie hat laufende Kosten. + +**Naheliegender Zuschnitt, falls angegangen:** ein *zusätzliches* Verzeichnis `themes/threadnet/` für unsere eigenen Assets anlegen und nur die dorthin zeigen, die wir selbst mitbringen (Titelbild, Logos). Upstreams `themes/element/` bleibt unangetastet — dann entsteht keine Merge-Reibung, und der sichtbare Pfad stimmt für alles, was wirklich von uns ist. + +Gehört inhaltlich zu ThreadNet-Web#7 (Rebranding-Gesamtklammer). diff --git a/docs/issues/0101-threadnet-call-4-kaputtes-paket-0-19-2-threadnet-6-in-der-regi.md b/docs/issues/0101-threadnet-call-4-kaputtes-paket-0-19-2-threadnet-6-in-der-regi.md new file mode 100644 index 0000000..7749a15 --- /dev/null +++ b/docs/issues/0101-threadnet-call-4-kaputtes-paket-0-19-2-threadnet-6-in-der-regi.md @@ -0,0 +1,44 @@ +--- +type: issue +id: "0101" +status: open +created: 2026-08-06 +milestone: M4 +priority: low +projekt: threadnet-call +gitlab_iid: "4" +related: [] +--- +# Kaputtes Paket 0.19.2-threadnet.6 in der Registry — Herkunft ungeklärt + +> Adoptiert aus [threadnet-call#4](https://git.lab/axion1337.chat/threadnet-call/-/issues/4) (2026-08-18, ADR-0019). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei. + +`0.19.2-threadnet.6` liegt mit **12.553 Bytes statt 12,8 MB** in der Gitea-npm-Registry: `package.json`, `README.md` und die beiden Lizenzdateien — **kein `dist/`**. Wer die Version installiert, bekommt ein leeres Paket. + +Zusätzlich zeigt `dist-tags.latest` auf genau diese kaputte Version. + +## Woher der Upload kam, ist offen + +Beide `publish_npm`-Läufe vom 2026-08-06 sind **fehlgeschlagen**: + +| Job | Pipeline | Fehler | +|---|---|---| +| 697 | 195 | `You must specify a tag using --tag when publishing a prerelease version` — Abbruch **vor** dem Upload | +| 699 | 196 | `409 Conflict — package version already exists` — die Version war da also schon | + +In beiden Pipelines lief `build_embedded` erfolgreich, das Artefakt war da (Job 699 meldete selbst „package size: 12.8 MB"). Zwischen 16:12:27 und 16:13:45 hat niemand sonst publiziert, den ich in der GitLab-API sehe. Die Gitea-Packages-API antwortet mit meinem Token nicht, sonst stünde dort `created_at` und der Uploader. + +**Ich habe keine belastbare Erklärung** — deshalb steht hier keine. + +## Was bereits getan ist + +- Veröffentlicht wurde stattdessen `0.19.2-threadnet.7` (geprüft: 12,8 MB, 151 Dateien unter `dist/`, Produktname enthalten). +- `publish_npm` bricht jetzt ab, wenn `embedded/web/dist` weniger als 50 Dateien hat (`8a38224`). Damit kann diese Fehlerklasse keine Versionsnummer mehr verbrennen. +- `--tag threadnet` gesetzt, weil npm Prereleases ohne dist-tag ablehnt (`760c6af`). + +## Offen + +1. **`.6` aus der Registry löschen** und prüfen, ob `dist-tags.latest` danach sinnvoll steht — braucht sorb (Gitea-Rechte). +2. Falls die Ursache doch noch auffindbar ist: Gitea-Log zum Zeitpunkt 16:12–16:14 UTC ansehen. + +Nicht dringend: `.5` (bis heute produktiv) und `.7` sind beide intakt, die kaputte `.6` wird von niemandem referenziert. diff --git a/schema.yaml b/schema.yaml index 7405797..91aac50 100644 --- a/schema.yaml +++ b/schema.yaml @@ -10,6 +10,9 @@ # next/waiting erweitert; due/host/area/wartegrund/gitlab_iid; # Regel waiting_requires_reason; globale Regel wip_limit (max. 2 # in-progress) in validate.py. +# * issue.projekt (ADR-0019): Herkunfts-Projekt adoptierter +# Komponenten-Issues; zusammen mit gitlab_iid die Spiegel-Adresse. +# Fehlt das Feld, ist management gemeint. # * component: neuer Typ unter docs/components/ (Dateiname = Slug). # * wiki-page: Area-Enum um "vision" erweitert. @@ -97,6 +100,7 @@ types: host: { enum: [cfgmon, overmind, matrix, game], nullable: true } area: { enum: [security, infrastructure, database, element], nullable: true } wartegrund: { kind: str, nullable: true } + projekt: { enum: [gitops, threadnet-web, threadnet-call], nullable: true } gitlab_iid: { pattern: "^\\d+$", nullable: true } related: { kind: links } rules: diff --git a/scripts/gruppenpruefung.py b/scripts/gruppenpruefung.py index a8d2161..b03e0e0 100644 --- a/scripts/gruppenpruefung.py +++ b/scripts/gruppenpruefung.py @@ -14,8 +14,10 @@ zu überspringen, und jede Prüfung bildet einen real passierten Fall ab 3. Meilenstein- und Prioritätspflicht über ALLE offenen Gruppen-Issues. (realer Fall: gitops#61, entstanden 2026-08-11, ohne Meilenstein) - 4. Issue-Drift management ↔ docs/issues/ — Titel, Zustand, - Meilenstein, Priorität, Status-Label. (F-001/F-017-Klasse) + 4. Issue-Drift GitLab ↔ docs/issues/ — Titel, Zustand, Meilenstein, + Priorität, Status-Label; seit ADR-0019 über management UND die + adoptierten Komponenten-Tracker (Feld `projekt`). + (F-001/F-017-Klasse) 5. Git-Hygiene seit 2026-08-07 — Autor- und Committer-Zeit 12:00:00 UTC, kanonische Identität; ausgenommen sind maschinelle Absender (MASCHINEN, per Adresse — ADR-0009). (F-002/F-003) @@ -188,29 +190,39 @@ def main() -> int: if len(prios) != 1: befunde.append(f"{ref}: {len(prios)} priority-Labels statt 1") - # 4) Issue-Drift management ↔ docs/issues/ - gl = {i["iid"]: i for i in - api(f"projects/{urllib.parse.quote(GRUPPE + '/management', safe='')}" - f"/issues?state=opened", token)} + # 4) Issue-Drift GitLab ↔ docs/issues/ (management + adoptierte + # Komponenten-Tracker, ADR-0019) + spiegel_projekte = { + "management": "axion1337.chat/management", + "gitops": "axion1337.chat/axion1337.chat-gitops", + "threadnet-web": "axion1337.chat/ThreadNet-Web", + "threadnet-call": "axion1337.chat/threadnet-call", + } + gl = {} + for kurz, pfad in spiegel_projekte.items(): + for i in api(f"projects/{urllib.parse.quote(pfad, safe='')}" + f"/issues?state=opened", token): + gl[(kurz, i["iid"])] = i dateien = {} for f in sorted((root / "docs/issues").glob("[0-9]*.md")): meta = frontmatter(f) + proj = meta.get("projekt") or "management" if meta.get("gitlab_iid"): - dateien[int(meta["gitlab_iid"])] = (f, meta) + dateien[(proj, int(meta["gitlab_iid"]))] = (f, meta) elif meta.get("status") not in ("done", "rejected"): hinweise.append(f"{f.name}: noch nicht gespiegelt " f"(gitlab_iid fehlt — erwartet bis zum " f"ersten Spiegel-Lauf)") - for iid in sorted(set(gl) - set(dateien)): - befunde.append(f"management#{iid} ist offen auf GitLab, hat aber " + for proj, iid in sorted(set(gl) - set(dateien)): + befunde.append(f"{proj}#{iid} ist offen auf GitLab, hat aber " f"keine kanonische Datei (zweites Backlog!)") - for iid, (f, meta) in sorted(dateien.items()): - if iid not in gl: + for (proj, iid), (f, meta) in sorted(dateien.items()): + if (proj, iid) not in gl: if meta.get("status") not in ("done", "rejected"): befunde.append(f"{f.name}: offen im Repo, aber auf GitLab " f"geschlossen/fehlend — nachziehen") continue - i = gl[iid] + i = gl[(proj, iid)] if titel(f) != i["title"].strip(): befunde.append(f"{f.name}: Titel weicht von GitLab ab") ms = (i.get("milestone") or {}).get("title", "") diff --git a/scripts/spiegel_issues.py b/scripts/spiegel_issues.py index 2992860..f2f98d2 100644 --- a/scripts/spiegel_issues.py +++ b/scripts/spiegel_issues.py @@ -1,12 +1,15 @@ #!/usr/bin/env python3 """spiegel_issues.py — Repo → GitLab, ein deterministischer Spiegel. -docs/issues/ ist kanonisch (ADR-0012); dieses Skript bespielt die +docs/issues/ ist kanonisch (ADR-0012, seit ADR-0019 auch für die +adoptierten Komponenten-Tracker); dieses Skript bespielt die GitLab-Ansicht, damit Board, Meilensteine und Labels weiterarbeiten. -Gespiegelt werden **nur** Titel, Zustand, Meilenstein, Priorität, -Fälligkeit und Status-Label — nie Beschreibungen (der Migrations- -Fußtext und die Kommentare auf GitLab bleiben unangetastet), und nie -in Gegenrichtung. +Das Zielprojekt bestimmt das Frontmatter-Feld `projekt` (fehlt es: +management). Gespiegelt werden **nur** Titel, Zustand, Meilenstein, +Priorität, Fälligkeit und Status-Label — nie Beschreibungen (der +Migrations-Fußtext und die Kommentare auf GitLab bleiben +unangetastet), und nie in Gegenrichtung. Eine offene Datei, deren +GitLab-Issue geschlossen wurde, wird wieder geöffnet. Default ist **Dry-Run**: druckt jeden geplanten API-Aufruf und ändert nichts. `--ausfuehren` schreibt wirklich — das stößt nur sorb an. @@ -27,8 +30,13 @@ import urllib.request from pathlib import Path API = "https://git.lab/api/v4" -PROJEKT = urllib.parse.quote("axion1337.chat/management", safe="") GRUPPE = "axion1337.chat" +PROJEKTE = { # Frontmatter `projekt` -> GitLab-Projektpfad (ADR-0019) + "management": "axion1337.chat/management", + "gitops": "axion1337.chat/axion1337.chat-gitops", + "threadnet-web": "axion1337.chat/ThreadNet-Web", + "threadnet-call": "axion1337.chat/threadnet-call", +} STATUS_LABEL = {"open": None, "next": "status:next", "in-progress": "status:doing", "waiting": "status:wartet"} @@ -84,13 +92,17 @@ def main() -> int: meilensteine = {re.match(r"^(M\d)\b", m["title"]).group(1): m["id"] for m in alle(f"groups/{GRUPPE}/milestones", token) if re.match(r"^M\d\b", m["title"])} - gitlab = {i["iid"]: i for i in - alle(f"projects/{PROJEKT}/issues?state=opened", token)} + pfade = {kurz: urllib.parse.quote(pfad, safe="") + for kurz, pfad in PROJEKTE.items()} + gitlab = {kurz: {i["iid"]: i for i in + alle(f"projects/{pfade[kurz]}/issues?state=all", token)} + for kurz in PROJEKTE} - plan: list[tuple[str, str, dict]] = [] - gespiegelt: set[int] = set() + plan: list[tuple[str, str, dict, str]] = [] + gespiegelt: set[tuple[str, int]] = set() for f in sorted((root / "docs/issues").glob("[0-9]*.md")): meta, titel = frontmatter_und_titel(f) + proj = meta.get("projekt") or "management" offen = meta.get("status") not in ("done", "rejected") labels = [f"priority:{meta['priority']}"] if STATUS_LABEL.get(meta.get("status")): @@ -100,24 +112,27 @@ def main() -> int: labels.append(f"{feld}:{meta[feld]}") soll = {"title": titel, "labels": sorted(labels), "milestone_id": meilensteine.get(meta.get("milestone")), - "due_date": meta.get("due") or None, - "state_event": None if offen else "close"} + "due_date": meta.get("due") or None} iid = int(meta["gitlab_iid"]) if meta.get("gitlab_iid") else None if iid is None: if offen: plan.append(("ANLEGEN", f.name, - {k: v for k, v in soll.items() - if k != "state_event" and v is not None})) + {k: v for k, v in soll.items() if v is not None}, + proj)) continue - gespiegelt.add(iid) - ist = gitlab.get(iid) + gespiegelt.add((proj, iid)) + ist = gitlab[proj].get(iid) if ist is None: if offen: plan.append(("MELDEN", f.name, - {"grund": f"#{iid} auf GitLab nicht offen, " - f"Datei aber {meta.get('status')}"})) + {"grund": f"{proj}#{iid} auf GitLab nicht " + f"gefunden, Datei aber {meta.get('status')}"}, + proj)) continue + ist_offen = ist["state"] == "opened" + if not offen and not ist_offen: + continue # beidseitig zu — Historie nicht anfassen delta = {} if ist["title"].strip() != titel: delta["title"] = titel @@ -130,26 +145,39 @@ def main() -> int: delta["milestone_id"] = soll["milestone_id"] if (ist.get("due_date") or None) != soll["due_date"]: delta["due_date"] = soll["due_date"] - if not offen: - delta["state_event"] = "close" + if offen and not ist_offen: + delta["state_event"] = "reopen" + elif not offen and ist_offen: + delta = {"state_event": "close"} if delta: - plan.append(("ÄNDERN", f"{f.name} (#{iid})", delta)) + plan.append(("ÄNDERN", f"{f.name} (#{iid})", delta, proj)) - for iid in sorted(set(gitlab) - gespiegelt): - plan.append(("MELDEN", f"management#{iid}", - {"grund": "offen auf GitLab ohne kanonische Datei — " - "wird NICHT automatisch geschlossen"})) + for kurz in PROJEKTE: + for iid in sorted(iid for iid, i in gitlab[kurz].items() + if i["state"] == "opened" + and (kurz, iid) not in gespiegelt): + plan.append(("MELDEN", f"{kurz}#{iid}", + {"grund": "offen auf GitLab ohne kanonische Datei — " + "wird NICHT automatisch geschlossen"}, kurz)) modus = "AUSFÜHREN" if scharf else "DRY-RUN" - for aktion, wer, daten in plan: + for aktion, wer, daten, proj in plan: print(f"[{modus}] {aktion} {wer}: {json.dumps(daten, ensure_ascii=False)}") if scharf and aktion == "ANLEGEN": - api(f"projects/{PROJEKT}/issues", token, "POST", daten) + neu = api(f"projects/{pfade[proj]}/issues", token, "POST", daten) + # Spiegel-Adresse zurückschreiben, sonst legt der nächste + # Lauf ein Duplikat an. + datei = root / "docs/issues" / wer + text = datei.read_text(encoding="utf-8") + datei.write_text(text.replace( + "\n---\n", f'\ngitlab_iid: "{neu["iid"]}"\n---\n', 1), + encoding="utf-8") + print(f" -> {proj}#{neu['iid']} angelegt, gitlab_iid in {wer}") elif scharf and aktion == "ÄNDERN": iid = int(wer.rsplit("#", 1)[1].rstrip(")")) - api(f"projects/{PROJEKT}/issues/{iid}", token, "PUT", daten) + api(f"projects/{pfade[proj]}/issues/{iid}", token, "PUT", daten) print(f"spiegel_issues [{modus}]: {len(plan)} Aktionen " - f"({sum(1 for a, _, _ in plan if a == 'MELDEN')} Meldungen)") + f"({sum(1 for a, *_ in plan if a == 'MELDEN')} Meldungen)") return 0 diff --git a/verfahren/issue-adoption/adoptiere.py b/verfahren/issue-adoption/adoptiere.py new file mode 100644 index 0000000..eaaba79 --- /dev/null +++ b/verfahren/issue-adoption/adoptiere.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +"""adoptiere.py — Komponenten-Issues in docs/issues/ übernehmen (ADR-0019). + +Liest die offenen Issues der adoptierten GitLab-Projekte und legt für +jedes eine kanonische Datei an: fortlaufende Nummer hinter der höchsten +vorhandenen, Herkunft als `projekt` + `gitlab_iid` im Frontmatter, die +GitLab-Beschreibung wortgleich als Rumpf. Kommentare und Verlauf bleiben +auf GitLab (wie beim Management-Import 2026-08-11, ADR-0012). + +Deterministisch und idempotent: existiert bereits eine Datei mit +demselben (projekt, gitlab_iid), wird das Issue übersprungen. +Default ist Dry-Run; --execute schreibt die Dateien. Stdlib-only. + +Usage: python3 verfahren/issue-adoption/adoptiere.py [repo-root] [--execute] + (Token: ~/.config/gitlab-lab/token oder $GITLAB_TOKEN) +""" +from __future__ import annotations + +import json +import os +import re +import sys +import urllib.parse +import urllib.request +from pathlib import Path + +API = "https://git.lab/api/v4" +# Reihenfolge = Nummernvergabe: erst gitops, dann die Clients. +PROJEKTE = [ + ("gitops", "axion1337.chat/axion1337.chat-gitops"), + ("threadnet-web", "axion1337.chat/ThreadNet-Web"), + ("threadnet-call", "axion1337.chat/threadnet-call"), +] +STATUS_AUS_LABEL = {"status:next": "next", "status:doing": "in-progress", + "status:wartet": "waiting"} +AREAS = ("security", "infrastructure", "database", "element") + + +def token_lesen() -> str: + if os.environ.get("GITLAB_TOKEN"): + return os.environ["GITLAB_TOKEN"] + return (Path.home() / ".config/gitlab-lab/token").read_text( + encoding="utf-8").strip() + + +def alle(pfad: str, token: str): + daten, seite = [], 1 + while True: + trenner = "&" if "?" in pfad else "?" + req = urllib.request.Request( + f"{API}/{pfad}{trenner}per_page=100&page={seite}", + headers={"PRIVATE-TOKEN": token}) + with urllib.request.urlopen(req) as antwort: + batch = json.load(antwort) + daten += batch + if len(batch) < 100: + return daten + seite += 1 + + +def slug(text: str, maxlen: int = 45) -> str: + text = text.lower() + for a, b in (("ä", "ae"), ("ö", "oe"), ("ü", "ue"), ("ß", "ss")): + text = text.replace(a, b) + text = re.sub(r"[^a-z0-9]+", "-", text).strip("-") + return text[:maxlen].rstrip("-") + + +def vorhandene(root: Path) -> tuple[int, set[tuple[str, str]]]: + hoechste, belegt = 0, set() + for f in (root / "docs/issues").glob("[0-9]*.md"): + meta = {} + for z in f.read_text(encoding="utf-8").splitlines()[1:]: + if z == "---": + break + m = re.match(r"^(\w+):\s*(.*)$", z) + if m: + meta[m.group(1)] = m.group(2).strip().strip('"') + hoechste = max(hoechste, int(meta.get("id", 0))) + if meta.get("gitlab_iid"): + belegt.add((meta.get("projekt") or "management", + meta["gitlab_iid"])) + return hoechste, belegt + + +def main() -> int: + argv = [a for a in sys.argv[1:] if a != "--execute"] + scharf = "--execute" in sys.argv + root = Path(argv[0]) if argv else Path.cwd() + token = token_lesen() + nr, belegt = vorhandene(root) + modus = "EXECUTE" if scharf else "DRY-RUN" + + for kurz, pfad in PROJEKTE: + issues = alle(f"projects/{urllib.parse.quote(pfad, safe='')}" + f"/issues?state=opened", token) + for i in sorted(issues, key=lambda x: x["iid"]): + if (kurz, str(i["iid"])) in belegt: + print(f"[{modus}] {kurz}#{i['iid']} bereits adoptiert — übersprungen") + continue + nr += 1 + ms = (i.get("milestone") or {}).get("title", "") + ms = ms[:2] if re.match(r"^M[1-5]\b", ms) else "" + prio = next((l.split(":")[1] for l in i["labels"] + if l.startswith("priority:")), "") + status = next((STATUS_AUS_LABEL[l] for l in i["labels"] + if l in STATUS_AUS_LABEL), "open") + area = next((a for a in AREAS if f"area:{a}" in i["labels"]), None) + name = f"{nr:04d}-{kurz}-{i['iid']}-{slug(i['title'])}.md" + zeilen = ["---", "type: issue", f'id: "{nr:04d}"', + f"status: {status}", f"created: {i['created_at'][:10]}", + f"milestone: {ms or 'FEHLT'}", f"priority: {prio}"] + if i.get("due_date"): + zeilen.append(f"due: {i['due_date']}") + if area: + zeilen.append(f"area: {area}") + if status == "waiting": + zeilen.append("wartegrund: WARTEGRUND-NACHTRAGEN") + zeilen += [f"projekt: {kurz}", f'gitlab_iid: "{i["iid"]}"', + "related: []", "---", f"# {i['title'].strip()}", "", + f"> Adoptiert aus [{kurz}#{i['iid']}]" + f"(https://git.lab/{pfad}/-/issues/{i['iid']}) " + f"(2026-08-18, ADR-0019). Kommentare und Verlauf " + f"bleiben dort; kanonisch ist ab jetzt diese Datei.", + ""] + rumpf = (i.get("description") or "").strip() + if rumpf: + zeilen += [rumpf, ""] + print(f"[{modus}] {kurz}#{i['iid']} -> {name}" + + (" (MEILENSTEIN FEHLT)" if not ms else "") + + (" (wartegrund nachtragen)" if status == "waiting" else "")) + if scharf: + (root / "docs/issues" / name).write_text( + "\n".join(zeilen), encoding="utf-8") + return 0 + + +if __name__ == "__main__": + sys.exit(main())