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.
Three docs still referenced the old docker-compose.yml path. Replace
with compose.yml so a future reader cloning at this hash finds the
file at the documented path.
- CHANGELOG.md:31 — backend skeleton recap line.
- docs/architecture.md:28 — deployment artifacts note (D-010 scope).
- tasks/todo.md:9 — B0.1 task description.
Also adds a "CI follow-ups (sprint 1+)" section to tasks/todo.md
capturing the 3 MINOR + 6 NIT deferred from code-reviewer's review
of chore/podman-and-ci, plus a FERNET-KEY tracker for the secret
provisioning before c2_credential.config_fernet (D-004) is wired.
- `tasks/todo.md`: B0.5 description updated (re2 hard dep, no fallback);
add a "Backend follow-ups (sprint 1+)" section with M1-M7 + N1-N6 from
the code-review verdict.
- `CHANGELOG.md`: backend skeleton bullets refreshed (no re fallback,
streaming blob store, audit + scope on CRUD, 56 unit tests); new
"Code-review remediation" subsection lists B1 / MA1-MA6 / N4 / N6 / M8
with one-line rationale each.
- `tests/integration/conftest.py`: leave `db.create_all()` in place but
add an inline TODO (N6) pointing at the Alembic switchover that will
exercise the F11 seed + audit-log role grants in CI.
M1 — Single SessionProvider via nested router.
The previous router had two route entries with `path: '/'`
(Navigate, AppShell) plus a separate `/login` entry, each wrapped in
its own RootLayout. That instantiated SessionProvider three times,
forking state the moment session writes diverged across siblings.
Replaced by one Root route with SessionProvider + <Outlet />, and
index/login/AppShell-children nested underneath. RootLayout (the
per-tree wrapper) is now obsolete and deleted; the new Root component
lives in src/routing/Root.tsx (addresses NIT N4 as a side effect).
M2 — Typo: "pollign" → "polling" in LiveCockpitPage masthead.
M3 — Replace asymmetric `?? 'rt_operator'` / `?? 'soc_analyst'`
fallbacks in LiveCockpitPage with an explicit `if (!user) return null;`
guard placed after all hooks (rules-of-hooks). AppShell already
redirects unauthenticated visitors to /login, so the guard documents
the invariant rather than introducing one.
NITs N1-N3, N5-N7 recorded in tasks/todo.md as sprint 1+ follow-ups.