Skip to content

feat(api): custom_domains_max per-tier cap#106

Merged
mastermanas805 merged 1 commit into
masterfrom
feat/fix-g-custom-domains-max
May 14, 2026
Merged

feat(api): custom_domains_max per-tier cap#106
mastermanas805 merged 1 commit into
masterfrom
feat/fix-g-custom-domains-max

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Summary

  • New per-tier count cap on custom hostnames a team may bind. The boolean Features.CustomDomains was the only gate before — Hobby Plus+ teams could add unlimited hostnames.
  • Mongo /nosql/new anonymous response now advertises connections_shared_cap_pod=20 so agents know the per-token cap (2) is bounded by a shared pod-wide --maxConns=20 (BugBash #167).

Tier ladder (plans.yaml)

Tier custom_domains_max
anonymous / free / hobby / hobby_yearly 0 (boolean gate trips first)
hobby_plus / hobby_plus_yearly 1
growth 3
pro / pro_yearly 5
team / team_yearly 50

Wiring

  • plans.yaml: custom_domains_max added to every tier's limits block.
  • custom_domain.go Create(): after the boolean gate fires, counts existing rows via ListCustomDomainsByTeam and returns 402 custom_domains_limit_reached with limit/current/tier/agent_action when the team is at or over the cap. Numbers come from the registry, never hardcoded.
  • nosql.go: anonymous limits map gains two fields (connections_shared_cap_pod, connections_note) — backwards-compatible (additive).

Depends on

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.
  • Pre-existing failing tests (TestTeamSelf_Get_ReturnsTeamRow, TestIsolation_FingerprintReuse_ReturnsSameToken) confirmed unrelated to this PR — they fail on origin/master too.

Closes BugBash U10 / #128 / #167.

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.
@mastermanas805 mastermanas805 merged commit 8ff98a0 into master May 14, 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