Skip to content

Commit 0d7985b

Browse files
Daxsumclaude
andcommitted
fix(api): gate message-quota paywall behind BILLING_ENABLED, off by default
Self-hosted deployments had no way to disable the per-plan message send/receive quota (200/month on the free plan) and the "Upgrade to send more messages" 402 response, unlike the existing ENTITLEMENT_ENABLED-gated contact/API-key/schedule limits. Add the same enabled-flag pattern to BillingService so self-hosters aren't capped by default. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0147RMBR3grGHNtHNj5PypNU
1 parent 0ef0761 commit 0d7985b

3 files changed

Lines changed: 14 additions & 0 deletions

File tree

‎api/.env.docker‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ USE_HTTP_LOGGER=true
99
# Defaults to "false" for self-hosted deployments (no limits).
1010
ENTITLEMENT_ENABLED=false
1111

12+
# Set to "true" to enable the per-plan message send/receive quota (e.g. 200
13+
# messages/month on the free plan) and the "Upgrade to send more messages"
14+
# paywall. Defaults to "false" for self-hosted deployments (no limits).
15+
BILLING_ENABLED=false
16+
1217
EVENTS_QUEUE_TYPE=emulator
1318
EVENTS_QUEUE_NAME=events-local
1419
EVENTS_QUEUE_ENDPOINT=http://localhost:8000/v1/events

‎api/pkg/di/container.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,7 @@ func (container *Container) BillingService() (service *services.BillingService)
999999
return services.NewBillingService(
10001000
container.Logger(),
10011001
container.Tracer(),
1002+
os.Getenv("BILLING_ENABLED") == "true",
10021003
container.InMemoryCache(),
10031004
container.Mailer(),
10041005
container.UserEmailFactory(),

‎api/pkg/services/billing_service.go‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type BillingService struct {
2020
service
2121
logger telemetry.Logger
2222
tracer telemetry.Tracer
23+
enabled bool
2324
cache cache.Cache
2425
emailFactory emails.UserEmailFactory
2526
mailer emails.Mailer
@@ -28,9 +29,11 @@ type BillingService struct {
2829
}
2930

3031
// NewBillingService creates a new BillingService
32+
// The enabled flag should come from the BILLING_ENABLED environment variable.
3133
func NewBillingService(
3234
logger telemetry.Logger,
3335
tracer telemetry.Tracer,
36+
enabled bool,
3437
cache cache.Cache,
3538
mailer emails.Mailer,
3639
emailFactory emails.UserEmailFactory,
@@ -40,6 +43,7 @@ func NewBillingService(
4043
return &BillingService{
4144
logger: logger.WithService(fmt.Sprintf("%T", s)),
4245
tracer: tracer,
46+
enabled: enabled,
4347
cache: cache,
4448
emailFactory: emailFactory,
4549
mailer: mailer,
@@ -53,6 +57,10 @@ func (service *BillingService) IsEntitledWithCount(ctx context.Context, userID e
5357
ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
5458
defer span.End()
5559

60+
if !service.enabled {
61+
return nil
62+
}
63+
5664
user, err := service.userRepository.Load(ctx, userID)
5765
if err != nil {
5866
ctxLogger.Error(service.tracer.WrapErrorSpan(span, stacktrace.Propagatef(err, "cannot load user with ID [%s], entitlement successful", userID)))

0 commit comments

Comments
 (0)