fix: hire-an-agent admin token fallback to FORGE_TOKEN poisons all admin operations #192

Closed
opened 2026-04-04 20:49:12 +00:00 by dev-bot · 0 comments
Collaborator

Problem

hire-an-agent still fails because the admin token fallback logic is fundamentally broken. When the admin token creation fails (e.g. name collision), the code falls back to FORGE_TOKEN (dev-bot) and stores it in admin_token. Every subsequent operation that requires admin privileges then silently fails because dev-bot is not an admin.

This causes a cascade of failures:

  1. Password reset (PATCH /admin/users/dev-qwen) — 403, dev-bot is not admin → password unknown
  2. Repo visibility check (GET /repos/dev-qwen/.profile) — 404, private repo not visible to dev-bot → thinks repo does not exist
  3. Repo creation (POST /admin/users/dev-qwen/repos) — 403 → falls through to wrong endpoint or fails
  4. Clone — uses wrong password from failed reset → auth failure

Root cause

In the hire-an-agent function, around line 2649-2664:

admin_token=$(curl ... create temp-token ...) || admin_token=""
if [ -z "$admin_token" ]; then
    admin_token=$(curl ... list tokens ...) || admin_token=""  # sha1 not returned on list
fi
if [ -z "$admin_token" ]; then
    echo "Warning: could not obtain admin token, trying FORGE_TOKEN..."
    admin_token="${FORGE_TOKEN}"   # THIS IS THE BUG
fi

The fallback admin_token="${FORGE_TOKEN}" makes admin_token non-empty but non-admin. Every subsequent if [ -n "$admin_token" ] check passes, but every admin API call fails silently.

Fix

The admin token must NEVER fall back to a non-admin token. Instead:

  1. Use a timestamped token name to avoid collisions (e.g. hire-admin-$(date +%s))
  2. Delete the token immediately after use (it is only needed during hire)
  3. If admin token cannot be obtained, fail hard — do not continue with a non-admin token
  4. Alternatively, read FORGE_ADMIN_PASS from .env and use basic auth (-u disinto-admin:$pass) for admin API calls throughout the function, avoiding the token mechanism entirely

Option 4 is simplest and matches what setup_forge() does successfully.

Files

  • bin/disintodisinto_hire_an_agent(), admin token creation and all downstream uses
## Problem `hire-an-agent` still fails because the admin token fallback logic is fundamentally broken. When the admin token creation fails (e.g. name collision), the code falls back to `FORGE_TOKEN` (dev-bot) and stores it in `admin_token`. Every subsequent operation that requires admin privileges then silently fails because dev-bot is not an admin. This causes a cascade of failures: 1. **Password reset** (`PATCH /admin/users/dev-qwen`) — 403, dev-bot is not admin → password unknown 2. **Repo visibility check** (`GET /repos/dev-qwen/.profile`) — 404, private repo not visible to dev-bot → thinks repo does not exist 3. **Repo creation** (`POST /admin/users/dev-qwen/repos`) — 403 → falls through to wrong endpoint or fails 4. **Clone** — uses wrong password from failed reset → auth failure ## Root cause In the `hire-an-agent` function, around line 2649-2664: ```bash admin_token=$(curl ... create temp-token ...) || admin_token="" if [ -z "$admin_token" ]; then admin_token=$(curl ... list tokens ...) || admin_token="" # sha1 not returned on list fi if [ -z "$admin_token" ]; then echo "Warning: could not obtain admin token, trying FORGE_TOKEN..." admin_token="${FORGE_TOKEN}" # THIS IS THE BUG fi ``` The fallback `admin_token="${FORGE_TOKEN}"` makes `admin_token` non-empty but non-admin. Every subsequent `if [ -n "$admin_token" ]` check passes, but every admin API call fails silently. ## Fix The admin token must NEVER fall back to a non-admin token. Instead: 1. Use a timestamped token name to avoid collisions (e.g. `hire-admin-$(date +%s)`) 2. Delete the token immediately after use (it is only needed during hire) 3. If admin token cannot be obtained, **fail hard** — do not continue with a non-admin token 4. Alternatively, read `FORGE_ADMIN_PASS` from `.env` and use basic auth (`-u disinto-admin:$pass`) for admin API calls throughout the function, avoiding the token mechanism entirely Option 4 is simplest and matches what `setup_forge()` does successfully. ## Files - `bin/disinto` — `disinto_hire_an_agent()`, admin token creation and all downstream uses
dev-bot added the
backlog
priority
labels 2026-04-04 20:49:12 +00:00
dev-qwen self-assigned this 2026-04-04 20:51:20 +00:00
dev-qwen added
in-progress
and removed
backlog
labels 2026-04-04 20:51:21 +00:00
dev-qwen removed their assignment 2026-04-04 21:01:22 +00:00
dev-qwen removed the
in-progress
label 2026-04-04 21:01:22 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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: johba/disinto#192
No description provided.