fix(platformctl): fix hyphenated actor token resolution bug + de-duplicate forgejo helpers #761

Closed
opened 2026-06-08 23:08:40 +02:00 by ollama · 1 comment
Collaborator

Spec sources (whitelist)

  • control-plane/platformctl/cli.py line ~1387 — actor.upper().replace('-','_') pattern (correct)
  • control-plane/platformctl/tools/run_review.py line ~1055 — actor.upper().replace('-','_') pattern (correct)
  • control-plane/platformctl/tools/run_review.py line ~976 — bare .upper() (BUG)
  • control-plane/platformctl/tools/pr_sanity.py lines ~606 and ~612 — bare .upper() (BUG)
  • control-plane/platformctl/tools/run_review.py line ~525 — _verify_actor implementation A
  • control-plane/platformctl/tools/pr_sanity.py line ~585 — _verify_actor implementation B (duplicate)
  • control-plane/platformctl/tests/test_glm_comment_hook.py lines ~374 and ~412 — test cases (verify they use non-hyphenated actors)

Extracted context

Latent bug: Forgejo token-env idiom is reimplemented ~6× in two inconsistent forms:

  • cli.py:1387 + run_review.py:1055: use .upper().replace('-','_') → resolves FORGEJO_TOKEN_PLATFORM_ORCHESTRATOR
  • run_review.py:976 + pr_sanity.py:606,612: use bare .upper() → resolves FORGEJO_TOKEN_PLATFORM-ORCHESTRATOR (note the hyphen!)

For hyphenated actors like platform-orchestrator, these resolve DIFFERENT env var names — the bare-form sites silently fail to find the token.

Tests use non-hyphenated actors so won't catch this.

Also: _verify_actor is implemented twice — run_review.py:525 (timeout + granular except) and pr_sanity.py:585 (bare except).

Scope

  1. Create new file control-plane/platformctl/identity/forgejo.py (or similar shared module) with:
    • forgejo_token_env_name(actor) = f"FORGEJO_TOKEN_{actor.upper().replace('-','_')}"
    • resolve_forgejo_actor_token(actor, generic_env=None) that looks up the env var
    • verify_forgejo_actor(host, token, expected_actor, *, timeout_s=15) — keep stricter run_review error-handling as canonical
  2. Route the 4 bare-.upper() sites through the helpers: run_review.py:976, pr_sanity.py:606,612
  3. Route the 2 correct sites through the same helpers (deduplication): cli.py:1387, run_review.py:1055
  4. Replace both _verify_actor implementations with calls to the shared version
  5. Remove now-duplicated token-env code from the old locations

Acceptance criteria

  • 715+ tests still green
  • No hyphenated actor can resolve a different env var name across sites
  • One shared forgejo-helper module (token-env + verify_actor)
  • Error handling follows the stricter run_review pattern (timeout + granular except)

Do NOT read

  • Full repo — only the files listed above
  • Do NOT modify test files (they already use non-hyphenated actors)

Agent notes

  • Recommended executor: Gemini 3.1 Pro (real bug fix, needs careful refactoring)
  • Size: Medium (~80 LOC + new file)
  • Review tier: tier/medium (touches production token resolution paths)
  • Audit ref: state/audit/deepseek-2026-06-08-multiperspective.md §E1-E2
  • This is a subset of #726 item 1-2 (claude's deslop issue)
## Spec sources (whitelist) - `control-plane/platformctl/cli.py` line ~1387 — `actor.upper().replace('-','_')` pattern (correct) - `control-plane/platformctl/tools/run_review.py` line ~1055 — `actor.upper().replace('-','_')` pattern (correct) - `control-plane/platformctl/tools/run_review.py` line ~976 — **bare `.upper()`** (BUG) - `control-plane/platformctl/tools/pr_sanity.py` lines ~606 and ~612 — **bare `.upper()`** (BUG) - `control-plane/platformctl/tools/run_review.py` line ~525 — `_verify_actor` implementation A - `control-plane/platformctl/tools/pr_sanity.py` line ~585 — `_verify_actor` implementation B (duplicate) - `control-plane/platformctl/tests/test_glm_comment_hook.py` lines ~374 and ~412 — test cases (verify they use non-hyphenated actors) ## Extracted context **Latent bug**: Forgejo token-env idiom is reimplemented ~6× in two inconsistent forms: - `cli.py:1387` + `run_review.py:1055`: use `.upper().replace('-','_')` → resolves `FORGEJO_TOKEN_PLATFORM_ORCHESTRATOR` - `run_review.py:976` + `pr_sanity.py:606,612`: use **bare `.upper()`** → resolves `FORGEJO_TOKEN_PLATFORM-ORCHESTRATOR` (note the hyphen!) For hyphenated actors like `platform-orchestrator`, these resolve DIFFERENT env var names — the bare-form sites silently fail to find the token. Tests use non-hyphenated actors so won't catch this. Also: `_verify_actor` is implemented twice — `run_review.py:525` (timeout + granular except) and `pr_sanity.py:585` (bare except). ## Scope 1. Create new file `control-plane/platformctl/identity/forgejo.py` (or similar shared module) with: - `forgejo_token_env_name(actor) = f"FORGEJO_TOKEN_{actor.upper().replace('-','_')}"` - `resolve_forgejo_actor_token(actor, generic_env=None)` that looks up the env var - `verify_forgejo_actor(host, token, expected_actor, *, timeout_s=15)` — keep stricter run_review error-handling as canonical 2. Route the 4 bare-`.upper()` sites through the helpers: `run_review.py:976`, `pr_sanity.py:606,612` 3. Route the 2 correct sites through the same helpers (deduplication): `cli.py:1387`, `run_review.py:1055` 4. Replace both `_verify_actor` implementations with calls to the shared version 5. Remove now-duplicated token-env code from the old locations ## Acceptance criteria - [ ] 715+ tests still green - [ ] No hyphenated actor can resolve a different env var name across sites - [ ] One shared forgejo-helper module (token-env + verify_actor) - [ ] Error handling follows the stricter run_review pattern (timeout + granular except) ## Do NOT read - Full repo — only the files listed above - Do NOT modify test files (they already use non-hyphenated actors) ## Agent notes - Recommended executor: Gemini 3.1 Pro (real bug fix, needs careful refactoring) - Size: Medium (~80 LOC + new file) - Review tier: tier/medium (touches production token resolution paths) - Audit ref: state/audit/deepseek-2026-06-08-multiperspective.md §E1-E2 - This is a subset of #726 item 1-2 (claude's deslop issue)
Owner

Closing as already implemented on current main.

Evidence checked before close:

  • control-plane/platformctl/tools/forgejo_helpers.py now owns forgejo_token_env_name(), resolve_forgejo_actor_token(), and verify_forgejo_actor().
  • control-plane/platformctl/tools/run_review.py and control-plane/platformctl/ci/pr_sanity.py import/use those helpers instead of local bare actor env logic.
  • Hyphenated actor regression exists in control-plane/platformctl/tests/test_forgejo_helpers.py for platform-orchestrator -> FORGEJO_TOKEN_PLATFORM_ORCHESTRATOR.
  • Verification: UV_CACHE_DIR=/tmp/platform-uv-cache PYTHONPATH=control-plane uv run --project control-plane --extra dev pytest control-plane/platformctl/tests/test_forgejo_helpers.py control-plane/platformctl/tests/test_glm_comment_hook.py control-plane/platformctl/tests/test_pr_sanity.py -q -> 75 passed.

No PR opened because the implementation is already present; leaving this issue open was queue noise.

Closing as already implemented on current `main`. Evidence checked before close: - `control-plane/platformctl/tools/forgejo_helpers.py` now owns `forgejo_token_env_name()`, `resolve_forgejo_actor_token()`, and `verify_forgejo_actor()`. - `control-plane/platformctl/tools/run_review.py` and `control-plane/platformctl/ci/pr_sanity.py` import/use those helpers instead of local bare actor env logic. - Hyphenated actor regression exists in `control-plane/platformctl/tests/test_forgejo_helpers.py` for `platform-orchestrator` -> `FORGEJO_TOKEN_PLATFORM_ORCHESTRATOR`. - Verification: `UV_CACHE_DIR=/tmp/platform-uv-cache PYTHONPATH=control-plane uv run --project control-plane --extra dev pytest control-plane/platformctl/tests/test_forgejo_helpers.py control-plane/platformctl/tests/test_glm_comment_hook.py control-plane/platformctl/tests/test_pr_sanity.py -q` -> `75 passed`. No PR opened because the implementation is already present; leaving this issue open was queue noise.
Sign in to join this conversation.
No labels
W6d-automerge-calibration
agent/claude-code
agent/codex
agent/hermes
agent/iskra
agent/ollama
agent/patchwarden
automerge-candidate
class/security-sensitive
cutover-gate
dependency/blocked
dependency/blocks-others
dependency/cross-repo
dependency/needs-confirmation
domain:agents
domain:ci
domain:docs
domain:forgejo
domain:infra
domain:memory
domain:runtime
domain:signal
domain:ux
flow/architecture
flow/blocked
flow/deployed
flow/done
flow/implementation
flow/intake
flow/maintained
flow/observed
flow/ready
flow/refining
flow/retired
flow/review
iterating
judge/codex-candidate
judge/hermes-candidate
judge/low-confidence
judge/needs-refinement
judge/operator-needed
judge/p0
judge/p1
judge/p2
judge/p3
judge/park
judge/patchwarden-candidate
judge/stale-priority
kind/adr
kind/bug
kind/chore
kind/feature
kind/infra
kind/ops
kind/refactor
kind/research
large-impact
merge/auto
merge/manual
merge/manual-dependency-conflict
merge/manual-failing-tests
merge/manual-merge-conflict
merge/manual-missing-review
merge/manual-operator-preference
merge/manual-red-zone
merge/manual-security-sensitive
merge/manual-unclear-scope
merge/manual-unknown
meta
mode:operator-only
mode:patchwarden-iskra-approved
mode:safe-auto
needs-operator-decision
needs-triage
not-ready
observed/erroring
observed/needs-followup
observed/pending
observed/retire-candidate
observed/unused
observed/used
operator-emotional
owner-attention
phase/02
phase/03
priority:p0
priority:p1
priority:p2
priority:p3
proposed
ready-for-agent
ready-for-operator
recovery
review:claude-reviewed
review:codex-reviewed
review:dziadek-reviewed
review:needs-human
risk/exposure
risk/process
risk/product
risk/runtime
safety:external-write
safety:no-prod-mutation
safety:prod-impact
safety:secret-touch
size/large
size/medium
size/small
size/tiny
size/unknown
source/adr
source/agent-generated
source/manual
source/operator-chat
source/voice-note
status:blocked
status:codex-ready
status:merged:pending-evidence
status:needs-evidence
status:operator-needed
status:parked
tier/full
tier/lite
tier/stacked
tier:0-platform-substrate
tier:1-iskra-value-layer
tier:2-tools-products-modules
type:bug
type:chore
type:docs
type:feat
type:policy
type:research
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pdurlej/platform#761
No description provided.