feat(api): custom_domains_max per-tier cap#106
Merged
Conversation
Adds a per-tier count cap on custom hostnames a team may bind across their stacks, closing the gap where the boolean Features.CustomDomains flag was the only gate (Hobby Plus+ teams could bind an unbounded number of hostnames). Tier ladder (plans.yaml): anonymous / free / hobby / hobby_yearly = 0 (feature off — boolean trips first) hobby_plus / hobby_plus_yearly = 1 growth = 3 pro / pro_yearly = 5 team / team_yearly = 50 Wiring: - plans.yaml: custom_domains_max field added to every tier's limits block. - custom_domain.go Create(): after the boolean gate fires, counts existing rows via ListCustomDomainsByTeam and returns 402 with custom_domains_limit_reached + limit/current/tier + agent_action when the team is at or over the cap. Numbers come from the registry, not hardcoded. - Requires the corresponding common PR (CustomDomainsMaxLimit method + Limits.CustomDomainsMax field). Land common first. Also closes BugBash #167: - nosql.go anonymous limits now surface connections_shared_cap_pod=20 and connections_note so an agent knows the per-token cap (2) is bounded by a shared pod-wide --maxConns of 20. The companion content PR updates llms.txt to match. Tests: - internal/handlers/custom_domain_test.go covers the four policy paths: hobby trips the boolean (not the cap), hobby_plus AT cap returns 402 with agent_action, pro OVER cap returns 402, hobby_plus UNDER cap passes the count branch. - Registry-side regression: TestCustomDomainsMax_RegistryNumbers locks the per-tier numbers so plans.yaml drift fails CI. Closes BugBash U10 / #128 / #167.
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
Features.CustomDomainswas the only gate before — Hobby Plus+ teams could add unlimited hostnames./nosql/newanonymous response now advertisesconnections_shared_cap_pod=20so agents know the per-token cap (2) is bounded by a shared pod-wide--maxConns=20(BugBash #167).Tier ladder (plans.yaml)
Wiring
plans.yaml:custom_domains_maxadded to every tier's limits block.custom_domain.goCreate(): after the boolean gate fires, counts existing rows viaListCustomDomainsByTeamand returns 402custom_domains_limit_reachedwithlimit/current/tier/agent_actionwhen the team is at or over the cap. Numbers come from the registry, never hardcoded.nosql.go: anonymouslimitsmap gains two fields (connections_shared_cap_pod,connections_note) — backwards-compatible (additive).Depends on
feat/fix-g-custom-domains-max-limit) — addsLimits.CustomDomainsMax+Registry.CustomDomainsMaxLimit(). Merge that PR first.Test plan
go test ./internal/handlers/ -run TestCustomDomain— 5 PASS (boolean gate / at-cap 402 / over-cap 402 / under-cap pass / registry numbers).go test ./internal/plans/...— registry tests green.go build ./...+go vet ./...clean.Closes BugBash U10 / #128 / #167.