---
title: Repair the Auction End-to-End Driver After the Write-Route Narrowing
type: task
status: completed
description: >-
  The end-to-end auction driver authenticates every REST call as the commissioner, so since the
  election write routes were narrowed to ownership it can drive only the two mirror teams that have
  a user. Its settlement and proxy scenarios abort, leaving implied-price gating with no end-to-end
  exercise.
base_uri: user:task/league/repair-auction-driver-after-write-route-narrowing.md
created_at: '2026-09-05T02:42:27.190Z'
entity_id: 9c5abc26-b5ff-49aa-af19-c76a38f61e5c
finished_at: '2026-09-05T03:40:02.907Z'
observations:
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-09-05T03:58:34.111Z'
visibility_analyzed_at: '2026-11-05T23:50:03.264Z'
---

# Repair the Auction End-to-End Driver After the Write-Route Narrowing

`scripts/drive-auction-end-to-end.mjs` is the only thing that drives the auction against real players, real rosters and the real routes. It has been partly broken since `a53c7a1a0`, and nobody noticed because nothing re-ran it.

## The defect

`api()` in the driver sends `commissioner_token()` on every REST call. That worked because `verifyUserTeam` accepted the commissioner for every team in the league. `a53c7a1a0` closed the election write routes to ownership — correctly, on a security finding proven by execution — and the driver was never updated.

So every `elect()` and `withdraw()` for a team the commissioner does not own now returns `400 {"error":"invalid teamId"}`.

**A token swap alone cannot fix it.** On the league 119 mirror only two of ten teams have a `users_teams` row at all — team 327 (user 1) and team 337 (user 5). Eight teams have no user, so there is no token that can act for them and the REST route is closed to them by construction.

## Reproduction

Measured 2026-09-05 at ref `94010184f`:

```
node scripts/drive-auction-end-to-end.mjs --lid 119
```

| scenario | result |
|---|---|
| elections | 7 passed, 1 failed, ABORTED |
| settlement | 5 passed, 1 failed, ABORTED |
| blocks | 47 passed, 1 not drivable |
| modes | 13 passed |
| proxy-bidding | 10 passed, 2 failed, ABORTED |

The two anchor failures:

- `elections: a second team can elect on the same player -- {"error":"invalid teamId"}`
- `settlement: the top ceiling is accepted -- elect 8`

**Confirmed not a regression from the settlement-refusal change.** A control run at the same ref with `0da25079b` reverted reproduces both failures identically.

## Why it matters

Implied-price gating (`5dbf666de`) is deployed and changes when a player sells and at what price. The settlement scenario aborts before reaching it, so **the rule has never been exercised end to end** — it is covered by specs alone, and a wrong gate sells a player early and irreversibly.

## The shape of the repair

Setup elections should be SEEDED, and only the assertions that are actually about the route should go through the route.

- Add a seeding helper that writes an `auction_elections` row directly for a team with no user, using `upsert_auction_election` inside a transaction the driver owns. Seeding deliberately fires no settlement, which is what makes it usable as setup: the field can be built up without selling the player.
- Drive the LAST election of a completing field through the REST route as a team that does have an owner, so the settlement still fires from a real request on a real route. This is the same shape `test/auction.settlement-refusal.spec.mjs` uses.
- Resolve a per-team token from `users_teams` for the calls that must stay on the route, rather than always sending the commissioner's.
- Keep at least one case asserting that the route REFUSES a team the caller does not own, so the repair cannot quietly re-widen what `a53c7a1a0` closed.

**Do not widen the routes to make the driver pass.** That is the hole `a53c7a1a0` closed, and the guide now says so.

## Two other defects found in the same run

- **The driver's exit code is not an oracle in either direction.** A full run exited 0 while printing 7 failures; the same failures under `--only elections,settlement` exited 1. Per `user:guideline/surface-pipeline-failures.md` the output oracle must be distinct from the exit code, and here neither is trustworthy. Fix the exit code and keep the printed summary as the oracle.
- **`proxy-bidding: the second manager can fund the human bid -- team 337 holds $0`.** The guide already warns to pick teams by BUDGET rather than team id, and the driver picks team 337 regardless. Independent of the auth defect.

## Plan

1. **Fix the exit code**, so the repair below can be scored by running the thing rather than by reading its output. Smallest independent piece.
2. **Add the election seeding helper** and convert the setup half of the elections, settlement and proxy scenarios to it.
3. **Resolve per-team tokens from `users_teams`** for the calls that must remain on the route, and add the negative case that the route refuses a non-owner.
4. **Pick the proxy-bidding teams by budget**, closing the `$0` failure.
5. **Re-run the full driver against league 119** and require the settlement scenario to reach and exercise implied-price gating — the two-holdout board where one team is priced out and one is not, which is the only shape that discriminates the rule.

## Verification notes

Score item 5 as a PAIR. A settlement that completes proves the driver runs; it does not prove the gate fired. Require a log line carrying the `(N more shown but priced out)` suffix, which is the only positive evidence the implied-price discharge did any work — a board where every contender declines produces a correct settlement and exercises nothing.
