Skip to content

refactor: close region→siteId half-migration on public wire keys - #119

Merged
guohai merged 1 commit into
mainfrom
feat/close-region-siteid-half-migration
Aug 23, 2026
Merged

refactor: close region→siteId half-migration on public wire keys#119
guohai merged 1 commit into
mainfrom
feat/close-region-siteid-half-migration

Conversation

@guohai

@guohai guohai commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #118: no public response surface uses the region JSON key for a site-id value anymore.

  • Responses renamed outright (same precedent as refactor: rename region → siteId across DB, API, daemon, and client #118): GET/POST /api/eval-agent-tokens (+ legacy /api/admin/eval-agent-tokens), run-targets agents, /api/eval-agents/dispatchable shared rows (the marketplace seam's internal region key no longer leaks to the wire), clash-runner tokens/list.
  • Clash-runner daemon wire dual-keys siteId + region (register response + assignment payloads): deployed runner containers still read region; drop the alias after the next runner redeploy via vox-upgrade.sh.
  • Request bodies canonically take siteId; the legacy region body key remains 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 and contract are pinned in tests/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).
  • Intentionally untouched: internal/seam DTOs (dispatch.ts, permissions.ts, marketplace AgentSummary/setListing context) — internal naming only, zero wire impact.

Test plan

  • npm run check clean; unit 1557/1557; audio 12/12; E2E green — one known rare admin-login flake under full-suite parallelism (passes 19/19 ×3 standalone); agora-e2e 13/13 against the real ConvoAI API.
  • New wire-contract tests: token create/list emit siteId (never region); legacy region body alias proven read via a successful create.

Generated with SMT smt@agora.build

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>
@github-actions

Copy link
Copy Markdown

🤖 Codex Code Review

Findings

  • Medium: server/routes.ts:3070 drops ownerId from GET /api/eval-agents/dispatchable shared rows. Before this PR, shared returned the marketplace AgentSummary as-is (tokenId, region, pricePerUnit, ownerId). The refactor should only rename region to siteId, but it now silently removes ownerId, which is an unrelated public API regression for consumers that use owner attribution. Preserve it in the mapped object, e.g. include ownerId: l.ownerId.

No security issues found in the changed paths. I did not run tests because the environment is read-only.

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

The refactor is coherent and the server↔client key flip is complete — I checked every response surface that changed against its consumers (grep for .region across client/src now returns zero hits outside formatRegion), and every request body the client sends now uses siteId. /api/v1 already required siteId, so the curl snippet update in run-your-own.tsx:596 is correct.

Incidental security improvement worth noting: server/routes.ts:3070 previously spread shared wholesale, which meant AgentSummary.ownerId (server/marketplace.ts:6) — the owner of other users' shared agents — was exposed to any authenticated caller of /api/eval-agents/dispatchable. The explicit projection drops it. Good.

Findings:

1. The clash-runner region aliases are dead code, and the justifying comment is factually wrong (server/routes.ts:6148-6150, 6257-6260, 6267-6268)

The comments say "Deployed clash-runner daemons still read region". They don't. vox_clash_runner/clash-runner.ts contains zero references to region or siteId — commit ebae6b4 ("remove RUNNER_REGION", Apr 2026) removed the last one, and it was only ever sent in the register request body, never read from a response. The assignment handler reads exactly assignment.match.{id,topic,maxDurationSeconds,config} (clash-runner.ts:156-292).

So a PR whose stated purpose is closing the half-migration adds three new dual-keyed region fields to the wire, and tests/clash-runner-lifecycle.test.ts:117-121 now asserts the alias must stay. That's the half-migration re-opened on a different endpoint. Recommend dropping all three aliases and the test assertion; if you want to keep them defensively, the comment should say "possible unverified out-of-tree consumers", not assert a dependency that provably doesn't exist in this repo.

2. Body alias exists, query alias doesn't (server/routes.ts:4083)

The rationale for req.body.siteId ?? req.body.region is "so scripted API users don't break", but /api/workflows/:id/run-targets and the eval-jobs list read req.query.siteId with no region fallback. A script that passed ?region=… is still broken. Not a regression from this PR (query keys flipped in #118), but the compat story is only half-applied — either extend the alias to the query readers or drop the claim from the comments.

3. Minor: ?? lets an empty canonical key mask a valid legacy one

req.body.siteId ?? req.body.region — a client sending {siteId: "", region: "na-us-seattle-01"} gets a 400 instead of falling back. Defensible as "canonical key wins," but || is the more forgiving read if compat is the goal. Low impact.

Validation is intact everywhere the alias was introduced: all five sites run the resolved value through String() + storage.isAllocatedSite() (2132, 3995, 5883, 6069, 6672), so a non-string or object body value fails closed at 400. No auth or injection surface changed.

@guohai
guohai merged commit 25db97f into main Aug 23, 2026
7 checks passed
@guohai
guohai deleted the feat/close-region-siteid-half-migration branch August 23, 2026 10:10
guohai added a commit that referenced this pull request Aug 23, 2026
…ey (#120)

Removes every remaining `region` alias from the API (follow-up to #119,
per decision: no backward compatibility needed):

- Request bodies read `siteId` ONLY (eval-schedules, workflow run,
  clash event/token/schedule). The legacy `region` body key is dead.
- Token create reads `regionLocationBaseId` ONLY (drops the pre-refactor
  `region` base-id body alias).
- Clash-runner wire: register + assignment payloads emit only `siteId`.
  Verified safe: the runner daemon never read the site field at all
  (consumes id/state/match.{id,topic,maxDurationSeconds} only), so no
  runner redeploy is required. Eval-agentd fleet already upgraded.
- Tests: all request bodies flipped to canonical keys (~70 sites);
  site-id-wire now asserts the legacy key is REJECTED, with a canonical
  control proving the 400 is the missing key.

Gate: tsc clean, unit 1557/1557 (agora-e2e 13/13 + health 281/281
re-verified after a lingering remote ConvoAI session timed out and the
local daemon was restarted), audio 12/12, E2E 133 passed / 0 failed.

🤖 Built with SMT <smt@agora.build>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant