fix(gastown): gate billing UI on announcement flag, not shadow metering - #4833
Conversation
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.
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Executive SummaryThe latest commit narrows Overview
Issue Details (click to expand)WARNING
Files Reviewed (2 files)
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 SummaryThe only change since the last review is an oxfmt-driven formatting collapse of the Files Reviewed (1 file)
Previous review (commit 814540e)Status: No Issues Found | Recommendation: Merge Executive SummaryThe billing-UI gating change correctly threads Files Reviewed (5 files)
Reviewed by claude-sonnet-5 · Input: 38 · Output: 13.6K · Cached: 966.9K Review guidance: REVIEW.md from base branch |
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.
Problem
In production we are showing the Gas Town billing estimate UI (estimate pill,
$/hr active/$ this runcost 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:But
billing.enabledreflects shadow metering — it istruewhenever theCONTAINER_USAGEbinding is present, which is the case in production so we can collect shadow usage data before launch (seeisContainerUsageMeteringEnabled). 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 reachedTerminalBar.Fix
Gate user-facing billing UI on announcement or enforcement, not on shadow metering:
billingAnnouncementEnabledprop toTerminalBar(andTabBar), threaded from the two town layouts (GASTOWN_BILLING_ANNOUNCEMENT_ENABLED) throughMayorTerminalBar.showBilling = billingAnnouncementEnabled || billing.enforcing || billing.runPolicy === 'paused_by_user'and use it for both the horizontal chip and vertical switch. A town alreadypaused_by_userstays interactive so the user can resume it.billing.enabledremains metering-only; nothing user-facing keys off it anymore.The Mayor terminal-pane overlay (which also prints estimate strings) is only reachable when
enforcingorpaused_by_user, both covered byshowBilling, so no estimate strings leak in announcement-off mode.Behavior
Spec
Updated
.specs/gastown-usage-based-billing.md:enabledis 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— passpnpm --filter web run lint— 0 warnings / 0 errorsoxfmtformatted;git diff --checkcleanNo component tests exist for
TerminalBar; change is prop plumbing + a gating boolean.