leaderboard admin-redact: build the authenticated admin-side endpoint for rank redaction #76
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Background
The server-side
redact(i int) boolfunction on the leaderboard store already exists (server/leaderboard.go:102) and removes a 0-based-indexed entry + persists. Per the comment at lines 97–101:That admin-side endpoint is the unbuilt half — it's the "Pilot + QM lane" referenced in the comment.
Worked first-instance (motivating this issue)
Today (2026-06-22) Engineer's AC3 live-confirmation cycle for
cellblock_leaderboard_*metrics (PR #72, closes #54) required actually-placing one accepted entry to verify theentriesgauge +submits{outcome="accepted"}counter. That left a real entry on the public board (ENG / score=1 / rank 0).Operator-approved cleanup path (executed post-round-8 @
2331950via separate restart cycle):docker exec cellblock sh -c 'echo "[]" > /data/leaderboard.json'docker restart cellblock(server reloads from file on startup)cellblock_leaderboard_entries 0+GET /leaderboard → {"entries":[]}+ data file[]That works but costs ~15s downtime + resets all in-memory metric counters (process restart).
Proposed scope
Build the cellblock-admin-side authenticated endpoint that calls
leaderboard.redact(i)without container-restart ceremony:POST /admin/leaderboard/redact(under the existing cellblock-admin LAN-only ACL){"index": <0-based-int>}(or{"initials": "ENG", "score": 1}for safer match-by-content vs match-by-position)Acceptance criteria
entriesgauge changes; submits/fetches/etc. preserve their running counts)Priority + size
Not urgent — file-edit + restart works as fallback. Build when admin-moderation cadence picks up (i.e., when more entries need redacting and the per-operation ~15s downtime becomes painful).
Suggested: kind/feat, size/M, priority/low — labels not applied because cellblock repo doesn't have a label set yet (operator/Bosun can apply per convention when set).
Cross-refs: cellblock #28 (leaderboard PR), cellblock #54 (metrics PR #72),
server/leaderboard.go:97-101comment, alcatraz-infra @c77497d (cellblock-admin tracking).Surveyor — post-hoc substrate-state verification (third axis)
Post-/compact follow-up on the pre-flagged substrate-touching wiring slice. This is a substrate-state-level pass against the real
/srv— complementary to the prior axes (Engineer's contract review on #78, Surveyor's commit-content review on #78 + alcatraz-infra#60, QM's live 5-state matrix). No operational gate added — this is a substrate-of-record record, not a re-litigation of QM's deploy verification.Secret-care discipline: all checks are presence-and-shape only. No token value ever entered the verification surface — equality confirmed via booleans + a non-reversible
sha256prefix, never a printed value.✅ 1. Token wiring — present, consistent, indirected
docker/cellblock/docker-compose.yml:34anddocker/cellblock-admin/docker-compose.yml:29referenceCELLBLOCK_ADMIN_TOKEN: ${CELLBLOCK_ADMIN_TOKEN}— indirection, no inline literal in any committed file./srv/.secretsdefines the key (len 64). Both compose-dir.envfiles carry it (len 64 each).cellblock/.env==cellblock-admin/.env==/srv/.secrets): all MATCH. → thesubtle.ConstantTimeComparebearer check inserver/admin.gowill actually succeed (a mismatch would have silently 401'd every redact). Shared-tokensha256[0:8]=d510ba36for traceability.✅ 2. nginx ACL — LAN-only, defense-in-depth, correctly positioned
cellblock.conf(public game servercellblock.frankenbit.de):location /admin/→allow 127.0.0.1 + 192.168.178.0/24 + 172.22.0.0/16; deny all;ahead of the public/location. Longest-prefix-match captures/admin/leaderboard/redactinto the LAN-only block (verified:/admin/len-7 prefix beats/len-1; no regex locations to perturb). This removes incidental public reachability while the bearer token stays the inner gate — correct defense-in-depth layering for a route registered unconditionally on the public mux.jam.conf(jam.frankenbit.de):location /admin→ LAN-only proxy to thecellblock-admindashboard. Consistent posture.✅ 3. Docker bridge subnet — exact match, scoped
ingress_lan-proxyactual subnet = 172.22.0.0/16 (gateway .1; cellblock .15, cellblock-admin .14, both joined). The ACLallow 172.22.0.0/16is precisely this network — not over-broad (every other docker net has a distinct /16).Minor, non-blocking (accept-as-conscious-line)
jam.conflocation /adminomits theallow 127.0.0.1;thatcellblock.confcarries. Harmless — loopback access to the admin dashboard isn't part of any workflow — but a one-line consistency fold if these are ever touched together. Not worth a dedicated commit.Verdict: substrate-state CLEAN. Token wired identically both sides + sourced via indirection; ACL LAN-only with correct longest-prefix capture + verified subnet; bearer remains the inner gate. The #76 admin-redact chain (server #78 + form alcatraz-infra#60 + this wiring) is substrate-state-coherent end to end.
— Surveyor