docs: archive Podman runner setup runbook + track F-D1..F-D5
Some checks failed
ci / backend (lint + typecheck + unit tests) (push) Failing after 1s
ci / frontend (lint + typecheck + build + unit tests) (push) Failing after 0s

Two changes scoped together since both stem from the post-PR2 wrap-up.

docs/podman-runner-setup.md (new, ~190 LOC):

Operational runbook for the gitea-runner host that drives CI. The first
attempt at install hit four traps that this archived version documents
so we don't lose the lesson:

 1. `act_runner register` performs a sanity ping against the container
    daemon before writing the credential. Without the Podman socket
    mounted on the *register one-shot*, register fails silently and no
    .runner file is produced. The runbook mounts the socket on both
    register and daemon containers.
 2. SELinux blocks rootless socket access by default. Quadlet
    SecurityLabelDisable=true (or --security-opt label=disable for the
    legacy CLI form) is the documented bypass. No-op on Debian, required
    on RHEL/Fedora hosts.
 3. The runner user UID is not 1000 on every host (gitea = 1005 here).
    Quadlet `%U` substitution makes the unit portable; hardcoded UIDs
    are explicitly called out as a sprint 0 mistake.
 4. `podman generate systemd` is officially deprecated. Quadlet is the
    only supported pattern going forward and is what this runbook ships;
    legacy alternative is omitted on purpose.

Also captures: token placeholder convention (<TOKEN_FROM_GITEA_UI>,
never the real value in archived docs), single-use semantics, the
"secrets via file, not chat" convention, the `:X.Y.Z` pin policy versus
`:latest` in prod (ties into follow-up F-D1), and a decommissioning
section that cleans up state without nuking the user-level Podman socket.

tasks/todo.md:

New section "Frontend follow-ups (sprint 1+)" with F-D1..F-D5 from
code-reviewer on `chore/frontend-dockerfile` (649194b). All deferred,
none blocking. F-D1 (digest pinning) is project-wide and explicitly
references the backend image and the runner image alongside the
frontend ones for a single chore commit.
This commit is contained in:
knacky
2026-05-23 03:08:03 +02:00
parent 649194b174
commit c44f8b90ad
2 changed files with 286 additions and 0 deletions

View File

@@ -139,6 +139,30 @@ None blocking, all deferred to sprint 1+.
wires `c2_credential.config_fernet` (D-004). `config.py:32` accepts an empty
default at boot but `Fernet(b"")` raises `ValueError` at first use.
## Frontend follow-ups (sprint 1+) (`devops`)
Raised by `code-reviewer` during review of `chore/frontend-dockerfile`
(`649194b`). None blocking, all deferred to sprint 1+. Some have a project-
wide reach (F-D1 also covers the backend image and the runner image).
- [ ] F-D1 — Pin container images by minor + digest, not by tag alone. Scope :
`frontend/Dockerfile` (node:22-alpine, nginxinc/nginx-unprivileged:alpine),
`backend/Dockerfile` (python:3.12-slim-bookworm), and the runner image
referenced in `docs/podman-runner-setup.md` (gitea/act_runner:X.Y.Z).
Harmonise the policy in a single chore commit.
- [ ] F-D2 — Decide image-level `HEALTHCHECK` directives vs delegating health
probing to Caddy upstream. Document the choice in `docs/deploy.md`.
- [ ] F-D3 — Security response headers (`X-Content-Type-Options: nosniff`,
`Referrer-Policy: strict-origin-when-cross-origin`, `Content-Security-Policy`).
Arbitrate ownership between `frontend/nginx.conf` and the Caddy outer
layer to avoid duplication / conflict.
- [ ] F-D4 — Enable response compression. Either `gzip on` + `gzip_types` in
`frontend/nginx.conf` (runtime), or `vite-plugin-compression` (precompute
.br / .gz at build time, served via `gzip_static`). Pick one.
- [ ] F-D5 — OCI image labels (`org.opencontainers.image.source`,
`image.title`, `image.licenses`, `image.revision`) on every Dockerfile.
Useful for registry metadata and supply-chain attestation tooling.
## Conventions
- Branches: `feature/<scope>`, `fix/<scope>`, `docs/<scope>`, `chore/<scope>`. Long-lived: `main`.