Documentation
¶
Overview ¶
Package tenant defines the multi-tenant management types and service.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrDuplicate = errors.New("nexus: tenant already exists")
ErrDuplicate reports an existing tenant ID or slug.
var ErrInUse = errors.New("nexus: tenant is in use")
ErrInUse reports that a tenant cannot be deleted because it still has keys or usage history. Disable it instead.
var ErrInvalid = errors.New("nexus: invalid tenant input")
ErrInvalid wraps every input the tenant service refuses, such as a missing name or slug.
var ErrNotFound = errors.New("nexus: tenant not found")
ErrNotFound reports that no tenant matched. Stores return it from FindByID, FindBySlug and Update, never a nil tenant with a nil error.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// AllowedModels, when not empty, limits the tenant to these models. A
// request is admitted when the model it asked for, or the model an
// alias resolved it to, is listed. Names are case-sensitive and match
// exactly; surrounding spaces are trimmed when the tenant is saved. An
// alias with several targets is checked against the target picked for
// that request, so list every target when it matters.
AllowedModels []string `json:"allowed_models,omitempty"`
// BlockedModels refuses a request when the model it asked for, or the
// model an alias resolved it to, is listed. Blocks win over allows. An
// alias with several targets is checked against the target picked for
// that request, so list every target when it matters.
BlockedModels []string `json:"blocked_models,omitempty"`
// DefaultModel is the model a request gets when it names none. It is
// filled before alias resolution, so it may be an alias.
DefaultModel string `json:"default_model,omitempty"`
// RoutingStrategy is stored for the dashboard; not enforced by the
// gateway yet.
RoutingStrategy string `json:"routing_strategy,omitempty"`
// GuardrailPolicy is stored for the dashboard; not enforced by the
// gateway yet.
GuardrailPolicy string `json:"guardrail_policy,omitempty"`
// CacheEnabled false turns the response cache off for this tenant, for
// reading and for writing. Nil follows the gateway setting.
CacheEnabled *bool `json:"cache_enabled,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Config holds per-tenant overrides.
type CreateInput ¶
type CreateInput struct {
Name string `json:"name"`
Slug string `json:"slug"`
Quota *Quota `json:"quota,omitempty"`
Config *Config `json:"config,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
CreateInput is the input for creating a tenant.
type Events ¶
type Events interface {
EmitTenantCreated(ctx context.Context, tenantID id.TenantID)
EmitTenantDisabled(ctx context.Context, tenantID id.TenantID)
}
Events receives tenant lifecycle events. *plugin.Registry satisfies it.
type InUseFunc ¶
InUseFunc reports whether a tenant still has keys that belong to it. The gateway builds it from the key store. It is a func, not the key store, because the key package imports this one.
type ListOptions ¶
type ListOptions struct {
Status string `json:"status,omitempty"`
Search string `json:"search,omitempty"`
Limit int `json:"limit,omitempty"`
Cursor string `json:"cursor,omitempty"`
}
ListOptions configures tenant listing. Search matches name or slug, anywhere, ignoring case. Lists are newest first and cursor paged.
type ListResult ¶
ListResult is one page of tenants. NextCursor is "" on the last page.
type Option ¶
type Option func(*service)
Option configures the tenant service.
func WithEvents ¶
WithEvents reports created tenants, and tenants that leave active.
type Quota ¶
type Quota struct {
RPM int `json:"rpm"` // requests per minute
TPM int `json:"tpm"` // tokens per minute
DailyRequests int `json:"daily_requests"` // max requests per day (0 = unlimited)
MonthlyBudgetUSD money.USD `json:"monthly_budget_usd"` // max spend per month, exact; zero means no budget
MaxTokensPerReq int `json:"max_tokens_per_req"` // max tokens per single request
// Streaming-specific limits. The gateway enforces them by default,
// through the stream lifecycle stage reading the tenant's quota.
MaxStreamDuration time.Duration `json:"max_stream_duration,omitempty"` // wall-clock cap per stream (0 = unlimited)
MaxStreamTokens int `json:"max_stream_tokens,omitempty"` // output-token cap per stream (0 = unlimited)
}
Quota defines limits for a tenant.
type Service ¶
type Service interface {
Create(ctx context.Context, input *CreateInput) (*Tenant, error)
Get(ctx context.Context, id string) (*Tenant, error)
GetBySlug(ctx context.Context, slug string) (*Tenant, error)
Update(ctx context.Context, id string, input *UpdateInput) (*Tenant, error)
Delete(ctx context.Context, id string) error
List(ctx context.Context, opts *ListOptions) (*ListResult, error)
UpdateQuota(ctx context.Context, id string, quota *Quota) error
SetStatus(ctx context.Context, id string, status Status) error
}
Service manages tenant lifecycle.
func NewService ¶
NewService creates a new tenant service.
type Store ¶
type Store interface {
Insert(ctx context.Context, t *Tenant) error
FindByID(ctx context.Context, id string) (*Tenant, error)
FindBySlug(ctx context.Context, slug string) (*Tenant, error)
Update(ctx context.Context, t *Tenant) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, opts *ListOptions) (*ListResult, error)
}
Store is the persistence interface for tenants. Finders and Update return ErrNotFound when no tenant matches; Delete of an unknown id is a no-op.
type Tenant ¶
type Tenant struct {
ID id.TenantID `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"` // URL-safe identifier
Status Status `json:"status"`
Quota Quota `json:"quota"`
Config Config `json:"config"`
Metadata map[string]string `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Tenant represents an isolated customer / team / project.