Documentation
¶
Index ¶
- Constants
- Variables
- func CheckLimit(ctx context.Context, meter UsageMeter, tenantID string) error
- type BillingProvider
- type EnforcementMiddleware
- type Handler
- type InMemoryMeter
- func (m *InMemoryMeter) CheckLimit(_ context.Context, tenantID string) (bool, int64, error)
- func (m *InMemoryMeter) GetUsage(_ context.Context, tenantID string, period time.Time) (*UsageReport, error)
- func (m *InMemoryMeter) RecordExecution(_ context.Context, tenantID, pipelineName string) error
- func (m *InMemoryMeter) SetPlan(tenantID, planID string)
- type MockBillingProvider
- func (m *MockBillingProvider) CancelSubscription(_ context.Context, subscriptionID string) error
- func (m *MockBillingProvider) CreateCustomer(_ context.Context, tenantID, _ string) (string, error)
- func (m *MockBillingProvider) CreateSubscription(_ context.Context, customerID, planID string) (string, error)
- func (m *MockBillingProvider) HandleWebhook(_ context.Context, payload []byte, _ string) error
- func (m *MockBillingProvider) ReportUsage(_ context.Context, subscriptionID string, quantity int64) error
- type Plan
- type SQLiteMeter
- func (m *SQLiteMeter) CheckLimit(ctx context.Context, tenantID string) (bool, int64, error)
- func (m *SQLiteMeter) GetUsage(ctx context.Context, tenantID string, period time.Time) (*UsageReport, error)
- func (m *SQLiteMeter) RecordExecution(ctx context.Context, tenantID, pipelineName string) error
- func (m *SQLiteMeter) SetPlan(tenantID, planID string)
- type StripePlanIDs
- type StripeProvider
- func (p *StripeProvider) CancelSubscription(_ context.Context, subscriptionID string) error
- func (p *StripeProvider) CreateCustomer(_ context.Context, tenantID, email string) (string, error)
- func (p *StripeProvider) CreateSubscription(_ context.Context, customerID, planID string) (string, error)
- func (p *StripeProvider) HandleWebhook(_ context.Context, payload []byte, signature string) error
- func (p *StripeProvider) ReportUsage(_ context.Context, _ string, _ int64) error
- type Subscription
- type TenantIDFunc
- type UsageEntry
- type UsageMeter
- type UsageReport
Constants ¶
const ( StatusActive = "active" StatusPastDue = "past_due" StatusCanceled = "canceled" StatusTrialing = "trialing" )
SubscriptionStatus constants for well-known Stripe subscription states.
Variables ¶
var ( PlanFree = Plan{ ID: "free", Name: "Free", PriceMonthly: 0, ExecutionsPerMonth: 1000, MaxPipelines: 5, MaxStepsPerPipeline: 20, RetentionDays: 7, MaxWorkers: 2, } PlanStarter = Plan{ ID: "starter", Name: "Starter", PriceMonthly: 4900, ExecutionsPerMonth: 50_000, MaxPipelines: 25, MaxStepsPerPipeline: 50, RetentionDays: 30, MaxWorkers: 8, Features: []string{"email-support", "custom-domains"}, } PlanProfessional = Plan{ ID: "professional", Name: "Professional", PriceMonthly: 19900, ExecutionsPerMonth: 500_000, MaxPipelines: 0, MaxStepsPerPipeline: 0, RetentionDays: 90, MaxWorkers: 32, Features: []string{"email-support", "custom-domains", "priority-builds", "advanced-analytics"}, } PlanEnterprise = Plan{ ID: "enterprise", Name: "Enterprise", PriceMonthly: 0, ExecutionsPerMonth: 0, MaxPipelines: 0, MaxStepsPerPipeline: 0, RetentionDays: 365, MaxWorkers: 0, Features: []string{ "sso", "multi-region", "dedicated-infrastructure", "sla-guarantee", "priority-support", "custom-domains", "advanced-analytics", "audit-log-export", }, } // AllPlans is the ordered list of available plans. AllPlans = []Plan{PlanFree, PlanStarter, PlanProfessional, PlanEnterprise} )
Predefined billing plans.
var ErrLimitExceeded = billingError("execution limit exceeded for current billing period")
ErrLimitExceeded is returned by CheckLimit when a tenant has exhausted their plan's execution quota for the current billing period.
Functions ¶
func CheckLimit ¶ added in v0.1.5
func CheckLimit(ctx context.Context, meter UsageMeter, tenantID string) error
CheckLimit is a convenience wrapper for non-HTTP enforcement paths (e.g. gRPC handlers or internal pipeline runners). It returns an error when the tenant has exceeded their plan limit.
Types ¶
type BillingProvider ¶
type BillingProvider interface {
// CreateCustomer registers a new billing customer for the given tenant.
CreateCustomer(ctx context.Context, tenantID, email string) (customerID string, err error)
// CreateSubscription starts a subscription for the customer on the given plan.
CreateSubscription(ctx context.Context, customerID, planID string) (subscriptionID string, err error)
// CancelSubscription cancels an active subscription.
CancelSubscription(ctx context.Context, subscriptionID string) error
// ReportUsage reports metered usage for a subscription.
ReportUsage(ctx context.Context, subscriptionID string, quantity int64) error
// HandleWebhook processes an incoming webhook payload from the payment provider.
HandleWebhook(ctx context.Context, payload []byte, signature string) error
}
BillingProvider abstracts payment and subscription management.
type EnforcementMiddleware ¶ added in v0.1.5
type EnforcementMiddleware struct {
// contains filtered or unexported fields
}
EnforcementMiddleware wraps an HTTP handler and rejects requests from tenants that have exceeded their plan's execution limit.
func NewEnforcementMiddleware ¶ added in v0.1.5
func NewEnforcementMiddleware(meter UsageMeter, getTenantID TenantIDFunc) *EnforcementMiddleware
NewEnforcementMiddleware creates an EnforcementMiddleware. The meter is queried on every request; the getTenantID function is used to extract the current tenant from the request context or headers.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler exposes billing endpoints over HTTP.
func NewHandler ¶
func NewHandler(meter UsageMeter, provider BillingProvider) *Handler
NewHandler creates a new billing HTTP handler.
func (*Handler) RegisterRoutes ¶
RegisterRoutes registers billing endpoints on the given mux.
type InMemoryMeter ¶
type InMemoryMeter struct {
// contains filtered or unexported fields
}
InMemoryMeter is a thread-safe in-memory UsageMeter suitable for tests.
func NewInMemoryMeter ¶
func NewInMemoryMeter() *InMemoryMeter
NewInMemoryMeter creates an InMemoryMeter.
func (*InMemoryMeter) CheckLimit ¶
CheckLimit checks whether the tenant may run another execution.
func (*InMemoryMeter) GetUsage ¶
func (m *InMemoryMeter) GetUsage(_ context.Context, tenantID string, period time.Time) (*UsageReport, error)
GetUsage returns the usage report for the given period.
func (*InMemoryMeter) RecordExecution ¶
func (m *InMemoryMeter) RecordExecution(_ context.Context, tenantID, pipelineName string) error
RecordExecution records a single execution for the tenant.
func (*InMemoryMeter) SetPlan ¶
func (m *InMemoryMeter) SetPlan(tenantID, planID string)
SetPlan associates a tenant with a billing plan.
type MockBillingProvider ¶
type MockBillingProvider struct {
// Customers maps tenantID -> customerID.
Customers map[string]string
// Subscriptions maps subscriptionID -> planID.
Subscriptions map[string]string
// UsageReports collects (subscriptionID, quantity) pairs.
UsageReports []UsageEntry
// WebhookPayloads collects raw webhook bodies.
WebhookPayloads [][]byte
// Error fields allow tests to inject failures.
CreateCustomerErr error
CreateSubscriptionErr error
CancelSubscriptionErr error
ReportUsageErr error
HandleWebhookErr error
// contains filtered or unexported fields
}
MockBillingProvider is a test double that records calls and returns configurable results.
func NewMockBillingProvider ¶
func NewMockBillingProvider() *MockBillingProvider
NewMockBillingProvider creates a MockBillingProvider ready for use.
func (*MockBillingProvider) CancelSubscription ¶
func (m *MockBillingProvider) CancelSubscription(_ context.Context, subscriptionID string) error
CancelSubscription cancels a mock subscription.
func (*MockBillingProvider) CreateCustomer ¶
CreateCustomer creates a mock customer.
func (*MockBillingProvider) CreateSubscription ¶
func (m *MockBillingProvider) CreateSubscription(_ context.Context, customerID, planID string) (string, error)
CreateSubscription creates a mock subscription.
func (*MockBillingProvider) HandleWebhook ¶
HandleWebhook records the webhook payload.
func (*MockBillingProvider) ReportUsage ¶
func (m *MockBillingProvider) ReportUsage(_ context.Context, subscriptionID string, quantity int64) error
ReportUsage records a usage report.
type Plan ¶
type Plan struct {
ID string `json:"id"`
Name string `json:"name"`
PriceMonthly int `json:"price_monthly"` // cents
ExecutionsPerMonth int64 `json:"executions_per_month"` // 0 = unlimited
MaxPipelines int `json:"max_pipelines"` // 0 = unlimited
MaxStepsPerPipeline int `json:"max_steps_per_pipeline"` // 0 = unlimited
RetentionDays int `json:"retention_days"`
MaxWorkers int `json:"max_workers"`
Features []string `json:"features,omitempty"`
}
Plan represents a billing plan with usage limits.
func (Plan) IsUnlimited ¶
IsUnlimited reports whether the plan has no execution limit.
type SQLiteMeter ¶
type SQLiteMeter struct {
// contains filtered or unexported fields
}
SQLiteMeter is a UsageMeter backed by a SQLite database.
func NewSQLiteMeter ¶
func NewSQLiteMeter(db *sql.DB) (*SQLiteMeter, error)
NewSQLiteMeter creates a new SQLiteMeter and initialises the schema.
func (*SQLiteMeter) CheckLimit ¶
CheckLimit checks whether the tenant may run another execution.
func (*SQLiteMeter) GetUsage ¶
func (m *SQLiteMeter) GetUsage(ctx context.Context, tenantID string, period time.Time) (*UsageReport, error)
GetUsage returns the usage report for the given period from SQLite.
func (*SQLiteMeter) RecordExecution ¶
func (m *SQLiteMeter) RecordExecution(ctx context.Context, tenantID, pipelineName string) error
RecordExecution records an execution in SQLite.
func (*SQLiteMeter) SetPlan ¶
func (m *SQLiteMeter) SetPlan(tenantID, planID string)
SetPlan associates a tenant with a billing plan.
type StripePlanIDs ¶ added in v0.1.5
StripePlanIDs maps plan IDs to Stripe price IDs (monthly). These must be configured to match Stripe dashboard price objects.
type StripeProvider ¶ added in v0.1.5
type StripeProvider struct {
// contains filtered or unexported fields
}
StripeProvider implements BillingProvider using the Stripe API.
func NewStripeProvider ¶ added in v0.1.5
func NewStripeProvider(apiKey, webhookSecret string, planPriceIDs StripePlanIDs) *StripeProvider
NewStripeProvider creates a StripeProvider with the given API key, webhook secret, and mapping from plan IDs to Stripe price IDs.
func (*StripeProvider) CancelSubscription ¶ added in v0.1.5
func (p *StripeProvider) CancelSubscription(_ context.Context, subscriptionID string) error
CancelSubscription cancels a Stripe subscription at period end.
func (*StripeProvider) CreateCustomer ¶ added in v0.1.5
CreateCustomer creates a new Stripe customer for the given tenant.
func (*StripeProvider) CreateSubscription ¶ added in v0.1.5
func (p *StripeProvider) CreateSubscription(_ context.Context, customerID, planID string) (string, error)
CreateSubscription creates a new Stripe subscription for the customer on the given plan.
func (*StripeProvider) HandleWebhook ¶ added in v0.1.5
HandleWebhook validates the Stripe webhook signature and dispatches known events.
func (*StripeProvider) ReportUsage ¶ added in v0.1.5
ReportUsage is a no-op for Stripe fixed-price plans. For metered billing, override this to call the Stripe usage records API.
type Subscription ¶ added in v0.1.5
type Subscription struct {
ID string `json:"id"`
CustomerID string `json:"customer_id"`
PlanID string `json:"plan_id"`
Status string `json:"status"` // active, past_due, canceled, trialing
CurrentPeriodEnd time.Time `json:"current_period_end"`
StripeSubscriptionID string `json:"stripe_subscription_id,omitempty"`
}
Subscription represents an active or historical billing subscription for a tenant.
type TenantIDFunc ¶ added in v0.1.5
TenantIDFunc extracts a tenant ID from an incoming HTTP request. The caller provides this so that enforcement is not coupled to any specific authentication scheme.
type UsageEntry ¶
UsageEntry records a single usage report.
type UsageMeter ¶
type UsageMeter interface {
// RecordExecution records a single pipeline execution for the tenant.
RecordExecution(ctx context.Context, tenantID, pipelineName string) error
// GetUsage returns the usage report for the given billing period.
GetUsage(ctx context.Context, tenantID string, period time.Time) (*UsageReport, error)
// CheckLimit checks whether the tenant is allowed to run another execution
// and returns the remaining executions in the current period.
CheckLimit(ctx context.Context, tenantID string) (allowed bool, remaining int64, err error)
}
UsageMeter tracks and queries resource consumption per tenant.
type UsageReport ¶
type UsageReport struct {
TenantID string `json:"tenant_id"`
Period time.Time `json:"period"` // first day of billing period
ExecutionCount int64 `json:"execution_count"`
PipelineCount int `json:"pipeline_count"`
StepCount int `json:"step_count"`
WorkerPeak int `json:"worker_peak"`
}
UsageReport summarizes resource usage for a tenant during a billing period.