Skip to content

fix(gastown): gate billing UI on announcement flag, not shadow metering - #4833

Merged
jrf0110 merged 3 commits into
mainfrom
fix/gastown-billing-ui-announcement-gate
Jul 28, 2026
Merged

fix(gastown): gate billing UI on announcement flag, not shadow metering#4833
jrf0110 merged 3 commits into
mainfrom
fix/gastown-billing-ui-announcement-gate

Conversation

@jrf0110

@jrf0110 jrf0110 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem

In production we are showing the Gas Town billing estimate UI (estimate pill, $/hr active / $ this run cost strings, and the "Allow automatic starts" switch) even though billing has not been announced or enforced.

Root cause: the terminal-bar billing chip was gated on billing.enabled:

{horizontal && billing && (billing.enabled || billing.runPolicy === 'paused_by_user') && ( ... )}

But billing.enabled reflects shadow metering — it is true whenever the CONTAINER_USAGE binding is present, which is the case in production so we can collect shadow usage data before launch (see isContainerUsageMeteringEnabled). Enforcement (GASTOWN_BILLING_ENABLED) and the announcement flag (GASTOWN_BILLING_ANNOUNCEMENT_ENABLED) are both off in production. So metering-only opened the gate and users saw billing estimates prematurely.

The intended "advance user-facing notice" signal — GASTOWN_BILLING_ANNOUNCEMENT_ENABLED — was only wired to the overview-page banner and never reached TerminalBar.

Fix

Gate user-facing billing UI on announcement or enforcement, not on shadow metering:

  • Add a billingAnnouncementEnabled prop to TerminalBar (and TabBar), threaded from the two town layouts (GASTOWN_BILLING_ANNOUNCEMENT_ENABLED) through MayorTerminalBar.
  • Compute showBilling = billingAnnouncementEnabled || billing.enforcing || billing.runPolicy === 'paused_by_user' and use it for both the horizontal chip and vertical switch. A town already paused_by_user stays interactive so the user can resume it.
  • billing.enabled remains metering-only; nothing user-facing keys off it anymore.

The Mayor terminal-pane overlay (which also prints estimate strings) is only reachable when enforcing or paused_by_user, both covered by showBilling, so no estimate strings leak in announcement-off mode.

Behavior

Env Announcement Enforcing Billing UI
Production (today) off off hidden (was shown)
Announcement rollout on off shown (pill + estimate + switch)
Enforcement rollout on/off on shown + blocking UI
Local dev on on shown

Spec

Updated .specs/gastown-usage-based-billing.md: enabled is metering-only and MUST NOT gate user-facing UI; the estimate pill / cost strings / automatic-start control are shown only under announcement or enforcement. Added a changelog entry.

Verification

  • pnpm --filter web run typecheck — pass
  • pnpm --filter web run lint — 0 warnings / 0 errors
  • oxfmt formatted; git diff --check clean

No component tests exist for TerminalBar; change is prop plumbing + a gating boolean.

The terminal-bar estimate pill, cost strings, and automatic-start control
were gated on billing.enabled, which reflects shadow metering (CONTAINER_USAGE
binding present) and is intentionally on in production before launch. This
surfaced billing estimates to users while GASTOWN_BILLING_ENABLED and
GASTOWN_BILLING_ANNOUNCEMENT_ENABLED were both off in production.

Gate user-facing billing UI on the announcement flag or enforcing instead.
Thread GASTOWN_BILLING_ANNOUNCEMENT_ENABLED from the town layouts through
MayorTerminalBar into TerminalBar/TabBar. A town already paused_by_user stays
interactive so the user can resume it.
@kilo-code-bot

kilo-code-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The latest commit narrows showBilling to the announcement flag alone, but the Mayor terminal-pane overlay still gates its cost-string visibility on billing.enforcing/paused_by_user directly, reopening a billing-info leak during an announcement-off enforcement rollout that the PR's own description says shouldn't happen.

Overview

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

WARNING

File Line Issue
apps/web/src/components/gastown/TerminalBar.tsx 630 showBilling dropped the enforcing/paused_by_user disjuncts, but the Mayor terminal-pane overlay (gated on !terminalEnabled, which depends on billing.enforcing/runPolicy directly) can still surface cost strings when announcement is off and enforcement is on, contradicting the PR's stated invariant.
Files Reviewed (2 files)
  • apps/web/src/components/gastown/TerminalBar.tsx - 1 issue
  • .specs/gastown-usage-based-billing.md - 0 issues

Fix these issues in Kilo Cloud

Previous Review Summaries (2 snapshots, latest commit 5c8dce4)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 5c8dce4)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The only change since the last review is an oxfmt-driven formatting collapse of the showBilling boolean expression in TerminalBar.tsx into a single line; the logic is unchanged.

Files Reviewed (1 file)
  • apps/web/src/components/gastown/TerminalBar.tsx

Previous review (commit 814540e)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The billing-UI gating change correctly threads GASTOWN_BILLING_ANNOUNCEMENT_ENABLED from both town layouts through MayorTerminalBar into TerminalBar/TabBar, and showBilling consistently replaces the old billing.enabled check for both the horizontal chip and vertical switch, matching the PR's stated intent.

Files Reviewed (5 files)
  • .specs/gastown-usage-based-billing.md
  • apps/web/src/app/(app)/gastown/[townId]/MayorTerminalBar.tsx
  • apps/web/src/app/(app)/gastown/[townId]/layout.tsx
  • apps/web/src/app/(app)/organizations/[id]/gastown/[townId]/layout.tsx
  • apps/web/src/components/gastown/TerminalBar.tsx

Reviewed by claude-sonnet-5 · Input: 38 · Output: 13.6K · Cached: 966.9K

Review guidance: REVIEW.md from base branch main

jrf0110 added 2 commits July 28, 2026 10:04
Drop the enforcing and paused_by_user disjuncts from showBilling so
GASTOWN_BILLING_ANNOUNCEMENT_ENABLED is the single gate for the estimate
pill, cost strings, and automatic-start control. Enforcement is true in
local dev (GASTOWN_BILLING_ENABLED), which was keeping the UI visible even
with the announcement flag off.
Comment thread apps/web/src/components/gastown/TerminalBar.tsx
@jrf0110
jrf0110 merged commit b91a97d into main Jul 28, 2026
16 checks passed
@jrf0110
jrf0110 deleted the fix/gastown-billing-ui-announcement-gate branch July 28, 2026 16:02
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.

2 participants