Skip to content

fix(gastown): preserve org billing context across model changes#1830

Closed
jrf0110 wants to merge 1 commit intomainfrom
convoy/bug-fixes-1756-1364-1632-1341/f3939d64/gt/toast/f0adf6f9
Closed

fix(gastown): preserve org billing context across model changes#1830
jrf0110 wants to merge 1 commit intomainfrom
convoy/bug-fixes-1756-1364-1632-1341/f3939d64/gt/toast/f0adf6f9

Conversation

@jrf0110
Copy link
Copy Markdown
Contributor

@jrf0110 jrf0110 commented Apr 1, 2026

Summary

When a model hot-swap occurs via PATCH /agents/:agentId/model, the KILO_CONFIG_CONTENT env var gets rebuilt and the organization ID embedded within it could be lost, breaking billing attribution.

This adds three defense layers to ensure the org billing context survives model changes:

  1. Standalone env var (GASTOWN_ORGANIZATION_ID): Set on /agents/start and read first in extractOrganizationId() before falling back to KILO_CONFIG_CONTENT extraction.
  2. Request body passthrough: organizationId field added to UpdateAgentModelRequest; Town.do.ts resolves townConfig.organization_id and threads it through container-dispatch.ts into the PATCH body.
  3. X-Town-Config sync: organization_id added to buildContainerConfig() output; the PATCH handler extracts it from the header and updates the env var.

Files changed: control-server.ts, process-manager.ts, types.ts, Town.do.ts, config.ts, container-dispatch.ts

Verification

  • pnpm typecheck — passes (0 errors)
  • pnpm format:check — passes
  • pnpm lint — passes
  • Code review: verified env var precedence (X-Town-Config > body > initial start), empty string handling, and fallback paths

Visual Changes

N/A

Reviewer Notes

  • The X-Town-Config organization_id value writes last in the PATCH handler (after the body value), which is intentional — the header is the authoritative source while the body serves as a belt-and-suspenders fallback if header parsing fails.
  • parsed.data.organizationId ?? '' on the /agents/start path means missing values produce an empty string, which extractOrganizationId() treats as falsy, correctly falling through to the KILO_CONFIG_CONTENT legacy extraction.

Store organizationId as a standalone env var (GASTOWN_ORGANIZATION_ID)
that survives KILO_CONFIG_CONTENT rebuilds. Three defense layers:

1. Set GASTOWN_ORGANIZATION_ID on /agents/start and read it first in
   extractOrganizationId() before falling back to config extraction.
2. Pass organizationId in the PATCH /model request body so the
   container receives it even if X-Town-Config parsing fails.
3. Include organization_id in buildContainerConfig and sync it to
   process.env in the PATCH handler's X-Town-Config processing.
// organization_id — keep the standalone env var in sync with the
// town config so org billing context is never lost.
const orgId = cfg.organization_id;
if (typeof orgId === 'string' && orgId) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Stale org billing context is never cleared

If organization_id is removed from the town config, this branch leaves the previous GASTOWN_ORGANIZATION_ID in process.env. extractOrganizationId() now prefers that env var over KILO_CONFIG_CONTENT, so later model swaps will continue attributing usage to the old org instead of falling back to the current town ownership. Clear or delete the env var when organization_id is absent.

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Apr 1, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
cloudflare-gastown/container/src/control-server.ts 268 GASTOWN_ORGANIZATION_ID is never cleared when organization_id is removed, so later model swaps can keep billing attribution on the previous org.

Fix these issues in Kilo Cloud

Other Observations (not in diff)

No additional issues found outside the diff.

Files Reviewed (6 files)
  • cloudflare-gastown/container/src/control-server.ts - 1 issue
  • cloudflare-gastown/container/src/process-manager.ts - 0 issues
  • cloudflare-gastown/container/src/types.ts - 0 issues
  • cloudflare-gastown/src/dos/Town.do.ts - 0 issues
  • cloudflare-gastown/src/dos/town/config.ts - 0 issues
  • cloudflare-gastown/src/dos/town/container-dispatch.ts - 0 issues

Reviewed by gpt-5.4-20260305 · 427,492 tokens

@jrf0110
Copy link
Copy Markdown
Contributor Author

jrf0110 commented Apr 1, 2026

Work consolidated into the convoy landing PR — see #1862

@jrf0110 jrf0110 closed this Apr 1, 2026
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