Admin-credentials help text is wrong: forget does not use admin creds, and blank does not fall back for prune #34

Closed
opened 2026-08-21 21:01:23 +01:00 by steve · 0 comments
Owner

Summary

The admin-credentials help text on the host repo page says admin creds are used for
prune / forget. Forget never uses them. Following this text while debugging a
403 Forbidden on forget leads to configuring admin creds, seeing no change, and
looking in the wrong place.

Found while diagnosing a real fleet-wide forget failure (rest-server running
--append-only, so every DELETE returned 403).

Current text — web/templates/pages/host_repo.html:85-88:

Only needed for rest-server repos that distinguish an append-only
user (everyday backups) from a delete-capable user (prune /
forget). For S3 / B2 / SFTP / local, leave this blank — the
everyday repo credentials handle prune too.

Two inaccuracies

1. Forget does not use admin credentials

cmd/agent/main.go: case api.JobForget runs on r, the everyday runner bound to the
normal repo credentials. case api.JobPrune is the only kind that builds a separate
runner from d.secrets.LoadAdmin(), gated on p.RequiresAdminCreds.

The code already states this — cmd/agent/main.go:517-524:

r is the everyday runner — bound to the host's repo (append-only) credentials.
Reused by every kind except JobPrune ... admin creds are not loaded for any other
kind
, so they're not on r. If you find yourself adding a new JobKind that needs
delete authority, mirror the JobPrune pattern below.

Corroborating:

  • internal/store/host_credentials.go:17 — "CredKindAdmin is the delete-capable credential used for prune."
  • The only dispatch-path consumer of CredKindAdmin is internal/server/http/maintenance_dispatch.go:52, inside case "prune". Every other reference is CRUD on the credential itself.

Practical consequence: the append-only/delete-capable split the text describes cannot
work for forget. An operator who sets up exactly what it suggests — append-only everyday
creds, delete-capable admin creds — gets working prune and forget still failing with 403.
Forget requires the everyday credentials to have delete authority.

2. "leave this blank — the everyday repo credentials handle prune too"

There is no fallback. When admin creds are unset, maintenance_dispatch.go:52-56 logs
maintenance: prune skipped — no admin creds and continues, on any backend. Prune is
skipped entirely rather than run with everyday creds.

This is also silent: no job row, no alert. In our deployment scheduled prune had never once
run across 5 hosts and nothing surfaced it — it only came to light from reading the source.

Suggested wording

Only needed for rest-server repos that distinguish an append-only user (everyday backups)
from a delete-capable user (prune). Note that forget always runs with the everyday
repo credentials, so those must have delete authority. For S3 / B2 / SFTP / local, leave
this blank — but note that prune is skipped entirely when this is unset, on any backend.

Possibly worth a look beyond the docs

Forget needing delete authority on the everyday credentials undercuts the append-only-everyday-user
story the UI is describing. If that split is intended to be supported, forget would need to
mirror the JobPrune pattern (main.go:622-645) — which is precisely what the comment at
main.go:523-524 anticipates. Happy to leave that out of scope; flagging since the doc fix
alone leaves the underlying limitation in place.

Separately, the silent skip on missing admin creds might warrant surfacing in the UI or as an
alert, given "prune has silently never run" is hard to notice.

Verified against main @ 6c6b962.

## Summary The admin-credentials help text on the host repo page says admin creds are used for `prune / forget`. **Forget never uses them.** Following this text while debugging a `403 Forbidden` on forget leads to configuring admin creds, seeing no change, and looking in the wrong place. Found while diagnosing a real fleet-wide forget failure (rest-server running `--append-only`, so every `DELETE` returned 403). Current text — `web/templates/pages/host_repo.html:85-88`: > Only needed for rest-server repos that distinguish an append-only > user (everyday backups) from a delete-capable user (prune / > forget). For S3 / B2 / SFTP / local, leave this blank — the > everyday repo credentials handle prune too. ## Two inaccuracies ### 1. Forget does not use admin credentials `cmd/agent/main.go`: `case api.JobForget` runs on `r`, the everyday runner bound to the normal repo credentials. `case api.JobPrune` is the only kind that builds a separate runner from `d.secrets.LoadAdmin()`, gated on `p.RequiresAdminCreds`. The code already states this — `cmd/agent/main.go:517-524`: > `r` is the everyday runner — bound to the host's repo (append-only) credentials. > Reused by every kind except `JobPrune` ... **admin creds are not loaded for any other > kind**, so they're not on `r`. If you find yourself adding a new `JobKind` that needs > delete authority, mirror the `JobPrune` pattern below. Corroborating: - `internal/store/host_credentials.go:17` — "CredKindAdmin is the delete-capable credential used for **prune**." - The only dispatch-path consumer of `CredKindAdmin` is `internal/server/http/maintenance_dispatch.go:52`, inside `case "prune"`. Every other reference is CRUD on the credential itself. **Practical consequence:** the append-only/delete-capable split the text describes cannot work for forget. An operator who sets up exactly what it suggests — append-only everyday creds, delete-capable admin creds — gets working prune and **forget still failing with 403**. Forget requires the *everyday* credentials to have delete authority. ### 2. "leave this blank — the everyday repo credentials handle prune too" There is no fallback. When admin creds are unset, `maintenance_dispatch.go:52-56` logs `maintenance: prune skipped — no admin creds` and `continue`s, on **any** backend. Prune is skipped entirely rather than run with everyday creds. This is also silent: no job row, no alert. In our deployment scheduled prune had never once run across 5 hosts and nothing surfaced it — it only came to light from reading the source. ## Suggested wording > Only needed for rest-server repos that distinguish an append-only user (everyday backups) > from a delete-capable user (**prune**). Note that **forget** always runs with the everyday > repo credentials, so those must have delete authority. For S3 / B2 / SFTP / local, leave > this blank — but note that **prune is skipped entirely when this is unset**, on any backend. ## Possibly worth a look beyond the docs Forget needing delete authority on the everyday credentials undercuts the append-only-everyday-user story the UI is describing. If that split is intended to be supported, forget would need to mirror the `JobPrune` pattern (`main.go:622-645`) — which is precisely what the comment at `main.go:523-524` anticipates. Happy to leave that out of scope; flagging since the doc fix alone leaves the underlying limitation in place. Separately, the silent skip on missing admin creds might warrant surfacing in the UI or as an alert, given "prune has silently never run" is hard to notice. Verified against `main` @ `6c6b962`.
steve closed this issue 2026-08-21 22:39:04 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/restic-manager#34