refactor: rename region → siteId across DB, API, daemon, and client - #118
Conversation
Reserve `region` for the real region (na-us-seattle / "Seattle") and rename the sequenced site identifier every job/agent/schedule stores (na-us-seattle-02) to `siteId`, across DB (9 columns), wire protocol (hard cut), public API + OpenAPI, and client helpers (clean split: formatRegion→formatSite, new formatRegion(region)/regionOf). Region-scope filters and AWS S3 region are explicitly out of scope. 🤖 Built with SMT <smt@agora.build>
4-task plan (DB+schema+server / daemon / client / openapi) implementing designs/2026-08-22-region-to-siteid-refactor-design.md. 🤖 Built with SMT <smt@agora.build>
The `region` column on nine tables stored a full sequenced site id (na-us-seattle-02), not a region. Rename column + field + isAllocatedSite helper to siteId; drop the ignored job-poll ?region= param; keep genuine region-scope filters untouched. Hard cut, no wire alias. 🤖 Built with SMT <smt@agora.build>
Consume Core's siteId wire fields; poll /api/eval-agent/jobs with no site query (Core derives it from the token). S3Config.region untouched. 🤖 Built with SMT <smt@agora.build>
formatRegion now formats a region ("Seattle"); the old site-label behavior
("Seattle 02") moves to formatSite; add regionOf(). Rename useRegionOptions
-> useSiteOptions, REGIONS -> SITES, and read siteId from the renamed API
responses (eval agents, jobs, schedules, metrics/leaderboard, clash events).
Also move the eval-jobs list filter param region -> siteId across server,
storage, client, and its api.test case.
🤖 Built with SMT <smt@agora.build>
The exact-site fields are site ids; rename to siteId and remove the pre-0023 enum [na, apac, eu, sa] that no longer exists in data. 🤖 Built with SMT <smt@agora.build>
…g sweep - clash-detail: move the streamInfo useQuery above the early returns — called conditionally, it changes hook order between renders and crashes the match page once data loads (react-hooks/rules-of-hooks). - clash-detail: remove the dead match.region displays (clash_matches never had a region/site column; formatSite(undefined) rendered blanks). - delete client/src/lib/mockData.ts (no importers). - full-tests-run.sh: default DATABASE_URL to the local dev DB so the DB-backed storage-level suites actually run instead of silently skipping. - reword stale "region" comments/log lines that now mean site (storage, index, routes-api-v1, schema) — SQL and logic untouched. 🤖 Built with SMT <smt@agora.build>
Full local gate now green: unit 1556/1556 (85 files), audio 12/12,
E2E 133 passed / 0 failed.
- siteId drift in DB-level fixtures (site_id NOT NULL violations once
DATABASE_URL reaches vitest): shared-agents-reap-query,
session-secrets-class, tier-classification now insert siteId.
- clash.test: assert event.siteId (raw rows carry siteId; one stale
.region assert cascaded into 7 failures via undefined eventId).
- dispatch-integration: agent jobs listing rows carry siteId.
- s3.test: /api/eval-jobs returns {data,total}, not a bare array
(pre-existing, surfaced once R2 creds were configured).
- e2e/admin.spec: admin login lands on /console/users since #52.
- e2e/clash.spec: role-based locators (bare text= hits nav links,
badges, and event names — strict-mode violations).
- e2e/run-your-own: wait for the page heading instead of networkidle
(flaky against the Vite dev server); site-placeholder + renamed-tab
assertions match the current UI.
- e2e/workflow-provider: domcontentloaded instead of networkidle.
- e2e/console.spec: poll for the client-side auth redirect instead of
racing it with a one-shot content snapshot.
- eval-agent-daemon: drop the redundant extraneous-query-params copy of
the fetch-jobs test (flagged in the final branch review).
- NEW tests/site-id-wire.test.ts: locks the wire contract the refactor
defines — eval-agents/eval-jobs/leaderboard emit siteId (never
region), ?siteId= filters and validates, and eval-agent-token
create/list keep the documented back-compat region key carrying a
site-id value.
🤖 Built with SMT <smt@agora.build>
🤖 Codex Code ReviewFindings
No other security, authorization, injection, or performance issues stood out in the reviewed refactor paths. I did not run the test suite in this read-only environment. |
🤖 Claude Code ReviewReviewed the full diff against Deployed eval-agent daemons will silently stall
this.region = agent.region; // vox-agentd.ts:336 (old)
...
if (!this.region) return []; // vox-agentd.ts:408 (old)So after this deploys, every unupgraded agent registers successfully, heartbeats successfully, shows online/idle in the console — and never fetches a job again. No error is logged on either side; the only symptom is jobs aging out through The reverse also breaks: the new daemon reads Cheapest fix is to emit both keys from register for one release: res.json({ id: agent.id, name: agent.name, siteId: agent.siteId, region: agent.siteId, state: agent.state, leaseId });Dropping Breaking change to public API v1 without back-compat
const siteId = req.body.siteId ?? req.body.region;In-app API docs now show a request that 400s
Copy-pasting that from the UI now fails. Needs Minor
I could not run |
Finishes what #118 enumerated: no public response surface uses the `region` JSON key for a site-id value anymore. - Responses renamed outright (precedent #118): eval-agent-tokens list/create (+ legacy admin routes), run-targets agents, eval-agents/dispatchable shared rows (seam key no longer leaks), clash-runner tokens/list. - Clash-runner daemon wire dual-keys `siteId` + `region` (register + assignment payloads) — deployed runners still read `region`; drop the alias after the next runner redeploy (vox-upgrade.sh). - Request bodies canonically take `siteId`; legacy `region` stays ACCEPTED as an alias (eval-schedules, workflow run, clash event/ token/schedule) so scripted API users don't break. Existing tests keep sending the alias — continuous coverage of that path; the canonical key + alias are pinned in site-id-wire.test.ts. - Client writers/readers flipped to siteId on console-eval-agents, console-clash, console-evalsets, console-workflow-detail, run-your-own (incl. the curl doc example). - Internal/seam DTOs (dispatch.ts, permissions.ts, marketplace AgentSummary/setListing context) intentionally untouched — internal naming debt only, no wire impact. Gate: tsc clean, unit 1557/1557, audio 12/12, E2E green (one known rare admin-login flake under full-suite parallelism, 19/19 x3 standalone; agora-e2e 13/13 after a lingering remote ConvoAI session timed out). 🤖 Built with SMT <smt@agora.build>
Summary
Completes the region → siteId terminology refactor: the DB columns, server responses, daemon, and client all now call an exact site ID (
<base>-<NN>, e.g.na-us-seattle-01) what it is, ending theregion-means-two-things overload.site_id+ 2 indexes (migration0025, v34, data-preserving).siteId; the eval-jobs list filter is?siteId=.vox_eval_agentdconsumessiteIdjob rows; the ignored job-poll param is gone.formatRegion/formatSitesplit; all hand-rolled interfaces and call-sites readsiteId(including the silent non-tsc cases: eval-agents, leaderboard, org-settings schedules, run-your-own jobs, clash pages).[na,apac,eu,sa]enum removed everywhere.clash-detail.tsxcalleduseQueryafter early returns — the match page crashed once data loaded.site_idNOT NULL), stale E2E specs (admin redirect since feat: admin edits user role/plan; move User Management + Providers under /console #52, renamed tabs, strict-mode locators), flakynetworkidlewaits replaced with deterministic ones.full-tests-run.shdefaultsDATABASE_URLso DB-level suites can't silently skip.mockData.ts, deadmatch.regiondisplays), stale region-wording comments swept.tests/site-id-wire.test.tslocks the wire contract (renamed surfaces emitsiteId, neverregion;?siteId=validates; token endpoints keep the documented back-compatregionkey).Known scope decision (documented, not a bug)
A few surfaces still use the
regionJSON key carrying a site-id value (eval-agent-token responses, run-targets agents, clash-runner admin lists, several POST request bodies). Server ↔ client are internally consistent and the wire test pins the contract; closing this fully is a follow-up.Test plan
npm run checkclean,npm test1556/1556./scripts/full-tests-run.sh: unit + audio + E2E all greenGenerated with SMT smt@agora.build