railiance-platform/docs/forgejo-package-prune.md
codex da42f764c0
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Add failure-safe cluster image capture hook
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a06ecb-456a-71c2-b41e-0755d336e883
2026-09-05 10:04:38 +02:00

133 lines
5.4 KiB
Markdown

# Forgejo package prune (retention)
Workplan: `ACTIVITY-WP-0020` · complements `docs/forgejo-backup.md`
## Policy
| Rule | Value |
| --- | --- |
| Versions kept per package | **3** (newest by `created_at`) |
| Package types (phase 1) | `container`, `pypi`, `npm`, `generic` |
| Org scope | `coulomb` |
| Protected versions | Image tags referenced in `railiance-apps` production Helm values / chart defaults |
| Default mode | dry-run (no deletes) |
| Schedule | Weekly Sunday 03:30 UTC via `activity-core` (`weekly-forgejo-package-prune`) |
OCI container layers dominate `forgejo dump` size (~80% of blob zip). Pruning old
tags slows backup growth and shortens chunked-copy duration.
## Operator commands
### 1. Authenticate to the approved token lane
The steady-state credential path is `CCR-2026-0006`: OpenBao lane
`platform/workloads/forgejo/forgejo-admin`, field `API_TOKEN`.
1. Confirm the sanctioned route first:
```bash
warden plan "forgejo admin api token" --json
```
2. Login with an identity allowed to read the lane:
```bash
bao login -method=oidc -path=netkingdom role=forgejo-admin-workload-kv-read
```
3. Run prune normally. If `FORGEJO_TOKEN`, `FORGEJO_ADMIN_TOKEN`,
`FORGEJO_TOKEN_FILE`, and `FORGEJO_ADMIN_TOKEN_FILE` are unset, the loader
now resolves the PAT directly from OpenBao.
Do not commit the token or paste it into workplans, State Hub, chat, or shell
history.
### 2. Break-glass overrides
Short-lived overrides are still supported when the lane is unavailable or when
an attended operator session needs an explicit handoff:
```bash
# Option A — token env for one shell session
export FORGEJO_TOKEN='<pat>'
# alias: export FORGEJO_ADMIN_TOKEN='<pat>'
# Option B — explicit file path for one invocation
warden access forgejo-admin-api-token --out "$XDG_RUNTIME_DIR/forgejo-admin.token" --field API_TOKEN
FORGEJO_TOKEN_FILE="$XDG_RUNTIME_DIR/forgejo-admin.token" make forgejo-package-prune-dry-run
rm -f "$XDG_RUNTIME_DIR/forgejo-admin.token"
```
The retired `/tmp/forgejo-tegwick-api-token` drop is no longer the default. Use
it only while unwinding legacy local state:
```bash
FORGEJO_ALLOW_LEGACY_FILE_FALLBACK=1 make forgejo-package-prune-dry-run
```
### 3. Run prune
```bash
cd ~/railiance-platform
make forgejo-package-prune-dry-run # list would-delete candidates
make forgejo-package-prune # delete beyond retention depth
```
## Durable multi-cluster image inventory
The inventory belongs outside the platform checkout. On the production worker
host, use `/home/tegwick/.local/state/railiance-platform/live-images/all.txt`.
`make live-images-refresh LIVE_IMAGES_SOURCES="/path/railiance01.txt /path/coulombcore.txt"`
merges complete, nonempty exports with the prior inventory under a writer lock,
then atomically publishes sorted image references and a count/hash receipt.
Set `LIVE_IMAGES_OUTPUT` when publishing for a different host user.
Missing, empty, or malformed input fails without replacing the previous file.
The prune CLI also refuses `--apply` before credential retrieval if any
explicit `--live-images-file` is missing, unreadable, empty, or comment-only.
Dry-run keeps reporting those files as warnings. This guard supplements the
activity-core worker guard; it does not require exports for callers that have
not configured any.
Refresh only adds protection: removal of obsolete tags requires a separate
review of every production cluster and rollback requirement.
Migration and rollout sequence:
1. Seed from the restored `docs/evidence/live-images-all.txt` plus fresh exports
from railiance01 and coulombcore; retain the restored multi-cluster entries.
2. Project the durable **directory** read-only into the activity-core worker
and configure its inventory argument to `all.txt` in that directory. Do not
mount the single file: atomic replacement must be visible to the worker.
3. Verify the worker reads a nonempty inventory and retains the existing hard
refusal of apply when that file is missing or empty. Use only its dry-run
verification; do not manually trigger prune.
4. After each cluster image rollout, export pod regular, init, and ephemeral
container images to a temporary file. Require successful kubectl exit and
nonempty output, then invoke this refresh target with that export. Keep
other clusters' prior entries during outages. Run the hook on the durable
host, or transfer the complete export there before invoking it.
`tools/cmd/refresh-live-images` captures regular, init and ephemeral container
images with a bounded kubectl call and publishes only after all requested
contexts succeed. `CONTEXTS` selects contexts; `EXTRA_LIVE_FILES` supplies saved
exports. Bare image names are accepted. Failed captures preserve the inventory.
The host installation exposes `~/.local/bin/railiance-live-images-refresh`;
invoke it after cluster image rollouts. Activity-core's `make refresh-live-images`
delegates to the same implementation. Live installation evidence is tracked in
`RPF-WP-0028`.
## Rollback procedure
If a needed tag was removed, restore from the latest Nextcloud `forgejo-dump-*.zip.age`
(`make forgejo-backup` evidence) using `railiance-infra/tools/forgejo-restore-drill.sh`,
or re-push the image from CI.
## Evidence
activity-core posts `forgejo_package_prune` progress to State Hub with non-secret
counts (`deleted_count`, `candidate_count`, `skipped_protected_count`, `errors`).
## Related
- `railiance-apps/docs/forgejo-package-registry.md`
- `docs/forgejo-backup.md`
- `docs/workload-kv-access-lanes.md`