Documentation
¶
Overview ¶
Package tenancy implements VORTEX's multi-tenancy layer (build plan M8): namespaces that isolate routes, secrets, metrics, and logs per tenant, with per-namespace resource quotas enforced at the HTTP and TCP edge. Standard library only.
Index ¶
- Variables
- func NamespaceIDFromContext(ctx context.Context) string
- func WithNamespace(ctx context.Context, ns *Namespace) context.Context
- type Enforcer
- func (e *Enforcer) HTTPMiddleware(namespaceID string) func(http.Handler) http.Handler
- func (e *Enforcer) RecordBandwidth(namespaceID string, bytes int64)
- func (e *Enforcer) SetRouteCount(namespaceID string, n int)
- func (e *Enforcer) Stats(namespaceID string) QuotaStats
- func (e *Enforcer) TCPMiddleware(namespaceID string) func(net.Conn) (net.Conn, error)
- type IsolatedMetrics
- type IsolatedSecretStore
- type Namespace
- type NamespaceConfig
- type QuotaConfig
- type QuotaStats
- type Registry
- func (r *Registry) Create(cfg NamespaceConfig) (*Namespace, error)
- func (r *Registry) Delete(id string) error
- func (r *Registry) Get(id string) (*Namespace, error)
- func (r *Registry) List(orgID string) []*Namespace
- func (r *Registry) Load(path string) error
- func (r *Registry) Save(path string) error
- func (r *Registry) Update(id string, cfg NamespaceConfig) error
Constants ¶
This section is empty.
Variables ¶
var ( ErrAlreadyExists = errors.New("tenancy: namespace already exists") ErrNotFound = errors.New("tenancy: namespace not found") )
Registry errors.
var ErrQuotaExceeded = errors.New("tenancy: quota exceeded")
ErrQuotaExceeded is returned by CheckQuota when a resource is over its limit.
Functions ¶
func NamespaceIDFromContext ¶
NamespaceIDFromContext returns the namespace ID in ctx, or "".
Types ¶
type Enforcer ¶
type Enforcer struct {
// contains filtered or unexported fields
}
Enforcer enforces namespace quotas at the HTTP and TCP layers. It is safe for concurrent use.
func NewEnforcer ¶
NewEnforcer builds an Enforcer backed by registry. It starts a background goroutine that resets bandwidth counters once per window.
func (*Enforcer) HTTPMiddleware ¶
HTTPMiddleware returns a middleware that enforces the connection quota for namespaceID: it increments the active-connection counter for the duration of each request and rejects with 429 when the limit is reached.
func (*Enforcer) RecordBandwidth ¶
RecordBandwidth adds bytes to a namespace's current-window bandwidth counter.
func (*Enforcer) SetRouteCount ¶
SetRouteCount records the number of routes assigned to a namespace.
func (*Enforcer) Stats ¶
func (e *Enforcer) Stats(namespaceID string) QuotaStats
Stats returns a snapshot of a namespace's usage.
func (*Enforcer) TCPMiddleware ¶
TCPMiddleware returns a connection wrapper enforcing MaxConnections for a namespace. It returns an error (closing the connection) when the limit is reached; otherwise it returns a wrapped conn that decrements the counter on Close.
type IsolatedMetrics ¶
type IsolatedMetrics struct {
// contains filtered or unexported fields
}
IsolatedMetrics wraps observability.Metrics, prefixing the route label with the namespace ID so each namespace's metrics are attributable to it.
func NewIsolatedMetrics ¶
func NewIsolatedMetrics(metrics *observability.Metrics, nsID string) *IsolatedMetrics
NewIsolatedMetrics wraps metrics for namespace nsID.
func (*IsolatedMetrics) RecordBytes ¶
func (m *IsolatedMetrics) RecordBytes(route string, in, out int64)
RecordBytes records bytes under the namespaced label.
func (*IsolatedMetrics) RecordRequest ¶
func (m *IsolatedMetrics) RecordRequest(route, method string, status int, dur time.Duration)
RecordRequest records a request under the namespaced route label.
func (*IsolatedMetrics) SetActiveConns ¶
func (m *IsolatedMetrics) SetActiveConns(route, protocol string, n int64)
SetActiveConns sets the active-connection gauge under the namespaced label.
type IsolatedSecretStore ¶
type IsolatedSecretStore struct {
// contains filtered or unexported fields
}
IsolatedSecretStore wraps a SecretStore, prefixing every key with a sanitized namespace ID so secrets in different namespaces never collide and one namespace cannot read another's secrets.
func NewIsolatedSecretStore ¶
func NewIsolatedSecretStore(store *secrets.SecretStore, nsID string) *IsolatedSecretStore
NewIsolatedSecretStore wraps store for namespace nsID.
func (*IsolatedSecretStore) Delete ¶
func (s *IsolatedSecretStore) Delete(name string) error
Delete removes the namespace-prefixed key.
func (*IsolatedSecretStore) Exists ¶
func (s *IsolatedSecretStore) Exists(name string) (bool, error)
Exists reports whether the namespace-prefixed key is set.
func (*IsolatedSecretStore) Get ¶
func (s *IsolatedSecretStore) Get(name string) (string, error)
Get retrieves the namespace-prefixed key.
func (*IsolatedSecretStore) List ¶
func (s *IsolatedSecretStore) List() ([]string, error)
List returns this namespace's secret names with the prefix stripped, so a namespace sees only its own keys.
func (*IsolatedSecretStore) Set ¶
func (s *IsolatedSecretStore) Set(name, value string) error
Set stores value under the namespace-prefixed key.
type Namespace ¶
type Namespace struct {
// contains filtered or unexported fields
}
Namespace is a tenant isolation boundary with quotas. It is immutable after creation except via the Registry's Update.
func NamespaceFromContext ¶
NamespaceFromContext returns the namespace stored in ctx, if any.
func NewNamespace ¶
func NewNamespace(cfg NamespaceConfig) (*Namespace, error)
NewNamespace validates cfg and constructs a Namespace. ID and OrgID are required; ID must be alphanumeric and hyphens only.
func (*Namespace) CheckQuota ¶
CheckQuota reports whether current usage of resource is within quota. A zero limit means unlimited (always nil). It returns an error wrapping ErrQuotaExceeded (naming the resource and limit) when over.
resource is one of: "routes", "secrets", "connections", "bandwidth".
func (*Namespace) Config ¶
func (n *Namespace) Config() NamespaceConfig
Config returns a copy of the namespace's full config.
func (*Namespace) Quotas ¶
func (n *Namespace) Quotas() QuotaConfig
Quotas returns the namespace's quota configuration.
type NamespaceConfig ¶
type NamespaceConfig struct {
ID string `json:"id"`
Name string `json:"name"`
OrgID string `json:"org_id"`
Quotas QuotaConfig `json:"quotas"`
}
NamespaceConfig describes a tenant namespace.
type QuotaConfig ¶
type QuotaConfig struct {
MaxRoutes int `json:"max_routes"`
MaxSecrets int `json:"max_secrets"`
MaxConnections int64 `json:"max_connections"`
BandwidthMbps int64 `json:"bandwidth_mbps"` // 0 = unlimited
MaxAgents int `json:"max_agents"` // reserved for the agent system
}
QuotaConfig bounds a namespace's resource use. A zero limit means unlimited.
type QuotaStats ¶
type QuotaStats struct {
ActiveConns int64
BandwidthUsed int64 // bytes in the current window
RouteCount int
}
QuotaStats is a snapshot of a namespace's live resource usage.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds all namespaces, keyed by ID. It is safe for concurrent use.
func (*Registry) Create ¶
func (r *Registry) Create(cfg NamespaceConfig) (*Namespace, error)
Create validates and stores a new namespace. It returns ErrAlreadyExists if the ID is taken.
func (*Registry) List ¶
List returns all namespaces for orgID. An empty orgID returns every namespace.
func (*Registry) Load ¶
Load replaces the registry contents with the namespaces in the JSON file at path. A missing file is treated as an empty registry (not an error).