Files
felhom.eu/documentation/backlog
admin e467785fd3
gates / gates (push) Successful in 5m23s
security: rotate the published secrets and de-git felhom.secret.yaml (R-925, P1)
WHY .gitignore "was not working": it was working. git never consults
.gitignore for a file it ALREADY TRACKS. The rule `*secret*` matched fine --
proved by dropping an untracked copy in and watching check-ignore name
`.gitignore:3:*secret*`. The file had been tracked since feea0606, which is
ironically the commit that de-gitted the Resend key.

WHAT THE EXPOSED VALUE ACTUALLY WAS. Not an analytics password: the GITEA
ADMIN ACCOUNT PASSWORD (is_admin true; /api/v1/admin/users answered 200), in
a repo gitea.dooplex.hu serves anonymously to the internet. That is push
access to every repo -- including the one whose website/ is git-synced live
and whose scripts/ is published by tag to every new box installer (R-110).
Re-ranked P2 -> P1 on that measurement; my first ranking had only measured
the analytics blast radius.

Every committed value was still live. Nothing had ever been rotated.

ROTATED (values never echoed; written to a 0600 file on DooPlex):
  umami-config        APP_SECRET + POSTGRES_PASSWORD. The password was
                      changed INSIDE postgres (ALTER USER) as well as in the
                      Secret -- the env var is only read at first init, so
                      patching the Secret alone would have changed nothing.
  healthchecks-config SECRET_KEY + SUPERUSER_PASSWORD (nothing consumes them,
                      there is no healthchecks Deployment).
  gitea-creds         no longer holds the admin password at all: a SCOPED
                      token (read:package + read:repository).
  gitea admin         new random password; gitea-system/gitea-admin updated.

VERIFIED, not assumed:
  - new admin password -> 200, OLD PUBLISHED PASSWORD -> 401 (the leak is dead)
  - umami: a real beacon returns 200 (so the app authenticates to postgres and
    writes) while a bogus site id still returns 400 (so the 200 means something)
  - hub: "Registry version check: latest = 0.304.0" AND "Template fetched
    (5881 bytes)", no auth failures
  - BOTH token scopes are load-bearing, and the second was found by breaking
    it: a package-only token made the hub log "Template fetch: unexpected
    status 403", because the template fetcher reads a raw file out of the
    felhom-controller repo, not the registry.

AN INCIDENT CAUSED BY THE FIX, recorded because it is the useful part: the
rollout restart needed to pick up the new umami secret put umami into
CrashLoopBackOff and took stats.felhom.eu down (503) for ~4 minutes. Not the
rotation -- at memory 512Mi that pod runs for months but CANNOT RESTART:
startup (Prisma + Next.js) peaks over the limit and is OOMKilled (exit 137).
Raised to 1Gi IN THE MANIFEST, not just live, per .claude/rules/manifests.md
("never bare kubectl set -- the next sync reverts it and the fix silently
disappears").

THE GATE: KNOWN_BACKLOG is removed from manifest_bearer_gate.py, as its own
comment instructed. Red-proofed with a decoy: exit 1 with it, exit 0 without.
An exemption kept this visible for three months and changed nothing.

WHAT REMAINS (operator, and it is bigger than what was fixed): the same
password is still the admin password in ~12 other namespaces -- nextcloud,
paperless, bookstack (a DATABASE ROOT password), tandoor, calibre,
adventurelog, gokapi, qbittorrent, servarr, homepage. Rotating Gitea does not
touch them. Also owed: a kisfenyo Gitea token sits in plaintext in the local
homelab-manifests remote URL and was printed to a session transcript during
this investigation, so it should be replaced regardless (R-580's shape).

NOT a finding: homelab-manifests is private (404 anonymously) and does not
contain the password; ArgoCD's repo credential is a separate token and was
untouched by the rotation.
2026-10-09 13:21:18 +02:00
..
…

documentation/backlog/

OPEN-ITEMS.md is the register of open work and the file to read first — it holds only what is open, one row per item, every row with a category, a severity, a state and an owner (the layout is at its top). CLOSED-ITEMS.md holds every finished row, compressed, with the commit that keeps its full text; a row moves there in the same commit that closes it (scripts/closed_register_gate.py RULE 3). ROADMAP.md holds intentions — features and spikes that do not exist yet — and ROADMAP-HISTORY.md the shipped and killed ones. An R-n id is minted once and never reused.

The other files in this folder — verdict per file (2026-10-03 triage)

File Verdict
SPEC-app-data-placement-2026-08-21.md KEEP — still referenced by open rows R-352 (placement still open) and R-368.
SPEC-r85-phase4-5-2026-07-26.md KEEP as history — a spec of shipped work (R-85, agent v0.104.0). CONTEXT.md and architecture/00-capability-map.md link here.
FOLLOWUP-nas-automount-guest-reboot-reassert.md FINISHED, kept in place — shipped in agent v0.84/v0.85 (CAMPAIGN-3). Not moved because CONTEXT.md, controller/network-storage-nas.md and felhom-controller/CONTEXT.md link to this path.

Moved to documentation/archive/ on 2026-10-03 (finished; nothing open refers to them):

  • FIX-M18-NOTES.md — dump re-validation every 5 min. FIXED in controller v0.62.0 @ f8afe5c (2026-06-14).
  • FIX-M19-NOTES.md — deriveStackName misattribution edge. FIXED in controller v0.62.0 @ 6bab68b (2026-06-14).
  • FOLLOWUP-golden-default-controller-tag.md — the golden baked a stale controller. FIXED in felhom-agent @ ceca355 (2026-07-03): build-golden.sh v2.0.0 makes the controller tag a mandatory argument. Evidence: ../audits/DRILL-golden-098-2026-07-03.md.
  • DIAGNOSIS-f9-storage-registration-gap-2026-06-14.md — a read-only diagnosis of June 2026, superseded by the shipped F9 fixes (controller CHANGELOG.md cites it as history).

The archive also holds OPEN-ITEMS-narratives-2026-10-03.md: the campaign write-ups, rulings and ranking paragraphs that sat between the register's tables until the triage, word for word.