Commit a0f4014
feat(worker): audit-only orphan-customer-DB / redis-namespace sweep (flag-gated OFF) (#102)
* feat(worker): audit-only orphan-customer-DB / redis-namespace sweep (flag-gated OFF)
New River periodic job orphan_db_sweep (hourly, reconcile queue, UniqueOpts)
that addresses the ~25 orphaned customer DB / redis namespace drain-backlog —
in DETECTION / DRY-RUN mode only. It lists instant-customer-* namespaces, flags
the ones whose token has NO non-terminal (pending/active/paused/suspended)
resources row and is past the provisioning grace window, then LOGS each
candidate (token masked via logsafe.Token) and emits the candidate metrics.
It DROPS NOTHING in audit-only mode.
truehomie-2026-06-03 safety: there is NO manual / raw DROP anywhere in this
job. The destructive teardown sits behind a SECOND flag and, when (and only
when) enabled, routes through the AUDITED provisioner DeprovisionResource
chokepoint — the same path the TTL reaper (expire.go) uses. For this PR that
path is intentionally unreachable-by-default.
Two flag gates, BOTH default OFF / fail-closed:
ORPHAN_DB_SWEEP_ENABLED — master flag; off → Work is a DEBUG no-op
(no namespace List, no DB read, no metric).
ORPHAN_DB_SWEEP_DESTRUCTIVE_ENABLED — destructive flag; meaningless unless the
master is also on AND a provisioner is
wired. Routes through the audited
chokepoint only.
Fail-safe / fail-open: a namespace-List error or a live-token DB-read error
degrades to ZERO candidates (never an empty-set that a destructive caller could
read as "drop everything"); a candidate whose token reappears live at the
destructive re-confirm is SKIPPED; a generic (unmapped-kind) orphan is SKIPPED
(no proven backing type → no guessed DROP). When in doubt, skip + log.
Metrics (lazy *Vec, both labels primed in metrics_test):
instant_orphan_db_sweep_candidates_total{kind} — counter, kind in
{customer_namespace, redis_namespace}
instant_orphan_db_sweep_candidates_current{kind} — gauge, current backlog
Alert + dashboard + catalog live in the infra repo (not owned here) — see PR
body for the exact metric names + suggested alerts (rule 25 follow-up).
Tests: candidate detection (orphan vs live vs pending vs within-grace), kind
classification, both flag gates (off → no-op), masking, fail-open paths, and
that the destructive deprovisioner is NEVER called in audit-only mode. New file
at 100% statement coverage. make gate green (build + vet + go test -short).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(worker): 100% patch coverage — extract typed-nil-safe deprovisioner helper
diff-cover flagged the `if provClient != nil` branch in the StartWorkers wiring
(integration-only, not unit-reachable). Extract the typed-nil-safe conversion
into orphanDBSweepDeprovisionerFor (mirrors NewExpireAnonymousWorker's handling)
and unit-test both arms directly, so the wiring call site is a single
non-branching expression covered by TestStartWorkers_FullBoot and the branch
logic is covered by the new unit test. New code back to 100% patch coverage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 4eb1207 commit a0f4014
7 files changed
Lines changed: 1350 additions & 0 deletions
File tree
- internal
- config
- jobs
- metrics
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
206 | 206 | | |
207 | 207 | | |
208 | 208 | | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
209 | 234 | | |
210 | 235 | | |
211 | 236 | | |
| |||
340 | 365 | | |
341 | 366 | | |
342 | 367 | | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
343 | 375 | | |
344 | 376 | | |
345 | 377 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
124 | 124 | | |
125 | 125 | | |
126 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
127 | 165 | | |
128 | 166 | | |
129 | 167 | | |
| |||
0 commit comments