fix(gastown): preserve org billing context across model changes#1830
Closed
fix(gastown): preserve org billing context across model changes#1830
Conversation
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) { |
Contributor
There was a problem hiding this comment.
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.
Contributor
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Fix these issues in Kilo Cloud Other Observations (not in diff)No additional issues found outside the diff. Files Reviewed (6 files)
Reviewed by gpt-5.4-20260305 · 427,492 tokens |
4 tasks
Contributor
Author
|
Work consolidated into the convoy landing PR — see #1862 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a model hot-swap occurs via
PATCH /agents/:agentId/model, theKILO_CONFIG_CONTENTenv 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:
GASTOWN_ORGANIZATION_ID): Set on/agents/startand read first inextractOrganizationId()before falling back toKILO_CONFIG_CONTENTextraction.organizationIdfield added toUpdateAgentModelRequest;Town.do.tsresolvestownConfig.organization_idand threads it throughcontainer-dispatch.tsinto the PATCH body.organization_idadded tobuildContainerConfig()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.tsVerification
pnpm typecheck— passes (0 errors)pnpm format:check— passespnpm lint— passesVisual Changes
N/A
Reviewer Notes
organization_idvalue 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/startpath means missing values produce an empty string, whichextractOrganizationId()treats as falsy, correctly falling through to theKILO_CONFIG_CONTENTlegacy extraction.