entitlement

package
v1.0.0-beta.236 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

README

Entitlements

Entitlements answer whether a customer may use a feature and, when relevant, return the state behind that decision. They connect product configuration to a customer's usage attribution, but they do not own raw usage or accounting entries.

Domain model

An entitlement belongs to a customer and a feature. At most one entitlement for the same feature is active for a customer at a given time.

Type Meaning
boolean grants access while active
static grants access and carries an immutable JSON configuration
metered derives access from metered usage and grant balance

Entitlement values are time-bound. An entitlement is active from its configured start, or creation time, until its configured end or deletion. The end is exclusive. Outside that interval it provides no access.

Ownership and lifecycle

Entitlements may be created directly or derived from subscriptions. Subscription owns the customer-specific schedule that materializes and supersedes subscription-managed entitlements. Entitlement owns their persisted lifecycle and value resolution.

Definitions are historical. Deletion ends an entitlement at a timestamp rather than erasing it, and overriding supersedes the previous definition rather than changing its meaning in the past.

An entitlement identifies the customer-feature relationship. Metered value calculations resolve that customer's usage attribution when querying the feature's meter.

Metered entitlements

A metered entitlement connects a feature's meter to grants owned by the entitlement. Metered usage consumes active grants in priority order. Uncovered usage becomes overage.

Access is allowed while balance remains. A soft limit continues to allow access after the balance is exhausted; it does not prevent usage or overage from being calculated.

Measurement begins at the entitlement's measurement start. Usage before that time is outside the entitlement calculation.

Metered values inherit Credit's one-minute resolution. They must not be used to express sub-minute access transitions.

Usage periods and resets

Usage periods partition a metered entitlement's usage over time. The initial period begins at measurement start and later periods follow the configured recurrence.

An explicit reset ends the current period and starts a new one. The reset may retain the original recurrence anchor or establish a new one. Grant rollover and preserved-overage behavior are part of the credit reset, not separate entitlement balances.

See Credit for grant consumption, reset, history, and snapshot semantics.

Value events

Entitlement value reads calculate the value at the requested time. Separately, the balance worker recalculates values when usage or entitlement state changes and publishes value events for notifications and downstream consumers.

Those event payloads are sometimes called snapshots, but they are not the durable credit balance snapshots used to resume calculations. Event handlers are retried, so consumers must process them idempotently.

Crossing a future entitlement or grant activation or expiry time does not by itself produce a value event. Reads reflect the new state, while event consumers observe it after another recalculation trigger or a scheduled recalculation.

Boundaries

  • Features and meters define what is measured; entitlement selects the feature, customer attribution, and access policy.
  • Streaming owns raw usage and meter queries.
  • Credit owns grants, balance calculation, resets, history, and balance snapshots for metered entitlements.
  • Subscriptions may materialize and supersede subscription-managed entitlements.
  • Notifications consume entitlement value events; those events are not a transactional source of balance truth.
  • Billing and Ledger own monetary and accounting state.

Documentation

Index

Constants

View Source
const ErrCodeEntitlementCreatePropertyMismatch models.ErrorCode = "entitlement_create_property_mismatch"
View Source
const ErrCodeEntitlementGrantsOnlySupportedForMeteredEntitlements models.ErrorCode = "entitlement_grants_only_supported_for_metered_entitlements"
View Source
const (
	EventSubsystem metadata.EventSubsystem = "entitlement"
)

Variables

View Source
var ErrEntitlementCreatePropertyMismatch = models.NewValidationIssue(
	ErrCodeEntitlementCreatePropertyMismatch,
	"entitlement create property mismatch",
)
View Source
var ErrEntitlementGrantsOnlySupportedForMeteredEntitlements = models.NewValidationIssue(
	ErrCodeEntitlementGrantsOnlySupportedForMeteredEntitlements,
	"grants are only supported for metered entitlements",
)
View Source
var MAX_SAFE_ITERATIONS = 1000000

Functions

func ValidateUniqueConstraint

func ValidateUniqueConstraint(ents []Entitlement) error

ValidateUniqueConstraint validates the uniqueness constraints of the entitlements The constraint is formally stated as follows:

For entitlement E 1. The ActiveFromTime is E.ActiveFrom or E.CreatedAt (if E.ActiveFrom is nil) 2. The ActiveToTime is E.ActiveTo or E.DeletedAt (if E.ActiveTo is nil). This can be nil.

Entitlement E is active at time T if and only if: 1. E.ActiveFromTime <= T and E.ActiveToTime > T 2. E.ActiveFromTime <= T and E.ActiveToTime is nil

For a set of unique entitlements S, where all E in S share the same feature (by key) and customer: 1. Let T1 be the first ActiveFromTime for any E in S sorted ascending 2. Let T2 be the last ActiveToTime for any E in S sorted ascending

The constraint:

For all E in S at any time T where T1 <= T < T2, there is at most one E that is active.

Types

type Access

type Access struct {
	// Map of featureKey to entitlement value + ID
	Entitlements map[string]EntitlementValueWithId
}

type AlreadyDeletedError

type AlreadyDeletedError struct {
	EntitlementID string
}

func (*AlreadyDeletedError) Error

func (e *AlreadyDeletedError) Error() string

type AlreadyExistsError

type AlreadyExistsError struct {
	EntitlementID string
	FeatureID     string
	CustomerID    string
}

func (*AlreadyExistsError) Error

func (e *AlreadyExistsError) Error() string

type BalanceHistoryWindow

type BalanceHistoryWindow struct {
	From           time.Time
	To             time.Time
	UsageInPeriod  float64
	BalanceAtStart float64
	OverageAtStart float64
}

BalanceHistoryWindow is the usage of a metered entitlement in a single window together with the balance the window started with.

type CreateCustomerEntitlementGrantInput

type CreateCustomerEntitlementGrantInput struct {
	CustomerID    customer.CustomerID
	EntitlementID string
	Grant         CreateEntitlementGrantInputs
}

CreateCustomerEntitlementGrantInput issues a grant for the entitlement referenced by ID within the customer referenced by ID. Only metered entitlements can own grants.

func (CreateCustomerEntitlementGrantInput) Validate

type CreateCustomerEntitlementInput

type CreateCustomerEntitlementInput struct {
	CustomerID  customer.CustomerID
	Entitlement CreateEntitlementInputs
	Grants      []CreateEntitlementGrantInputs
}

CreateCustomerEntitlementInput creates an entitlement for the customer referenced by ID. The namespace and usage attribution of the entitlement are taken from the resolved customer, so callers leave them unset.

func (CreateCustomerEntitlementInput) Validate

type CreateEntitlementGrantInputs

type CreateEntitlementGrantInputs struct {
	credit.CreateGrantInput
}

type CreateEntitlementInputs

type CreateEntitlementInputs struct {
	Namespace        string                             `json:"namespace"`
	FeatureID        *string                            `json:"featureId"`
	FeatureKey       *string                            `json:"featureKey"`
	UsageAttribution streaming.CustomerUsageAttribution `json:"usageAttribution"`
	EntitlementType  EntitlementType                    `json:"type"`
	Metadata         map[string]string                  `json:"metadata,omitempty"`
	Annotations      models.Annotations                 `json:"annotations,omitempty"`

	// ActiveFrom allows entitlements to be scheduled for future activation.
	// If not set, the entitlement is active immediately.
	ActiveFrom *time.Time `json:"activeFrom,omitempty"`
	// ActiveTo allows entitlements to be descheduled for future activation.
	// If not set, the entitlement is active until deletion.
	ActiveTo *time.Time `json:"activeTo,omitempty"`

	MeasureUsageFrom        *MeasureUsageFromInput `json:"measureUsageFrom,omitempty"`
	IssueAfterReset         *float64               `json:"issueAfterReset,omitempty"`
	IssueAfterResetPriority *uint8                 `json:"issueAfterResetPriority,omitempty"`
	IsSoftLimit             *bool                  `json:"isSoftLimit,omitempty"`
	Config                  *string                `json:"config,omitempty"`
	UsagePeriod             *UsagePeriodInput      `json:"usagePeriod,omitempty"`
	PreserveOverageAtReset  *bool                  `json:"preserveOverageAtReset,omitempty"`

	// UnitConfig is the rate card's UnitConfig snapshotted onto the entitlement at
	// subscription time. The metered grant-owner adapter uses it to convert usage
	// into billing units at balance-check time (OM-400). It is the typed DTO from the
	// leaf unitconfig package (not productcatalog) so this package, which sits below
	// productcatalog in the import graph, can reference it without a cycle. Only
	// metered entitlements created from a unit_config rate card carry it; nil means
	// balances are computed in raw metered units, as before.
	UnitConfig *unitconfig.UnitConfig `json:"unitConfig,omitempty"`

	SubscriptionManaged bool `json:"subscriptionManaged,omitempty"`
}

func (CreateEntitlementInputs) Equal

func (CreateEntitlementInputs) GetType

func (CreateEntitlementInputs) Validate

func (c CreateEntitlementInputs) Validate() error

type CreateEntitlementRepoInputs

type CreateEntitlementRepoInputs struct {
	Namespace        string                             `json:"namespace"`
	FeatureID        string                             `json:"featureId"`
	FeatureKey       string                             `json:"featureKey"`
	UsageAttribution streaming.CustomerUsageAttribution `json:"usageAttribution"`
	EntitlementType  EntitlementType                    `json:"type"`
	Metadata         map[string]string                  `json:"metadata,omitempty"`
	ActiveFrom       *time.Time                         `json:"activeFrom,omitempty"`
	ActiveTo         *time.Time                         `json:"activeTo,omitempty"`

	Annotations models.Annotations `json:"annotations,omitempty"`

	MeasureUsageFrom        *time.Time             `json:"measureUsageFrom,omitempty"`
	IssueAfterReset         *float64               `json:"issueAfterReset,omitempty"`
	IssueAfterResetPriority *uint8                 `json:"issueAfterResetPriority,omitempty"`
	IsSoftLimit             *bool                  `json:"isSoftLimit,omitempty"`
	Config                  *string                `json:"config,omitempty"`
	UnitConfig              *unitconfig.UnitConfig `json:"unitConfig,omitempty"`
	UsagePeriod             *UsagePeriodInput      `json:"usagePeriod,omitempty"`
	CurrentUsagePeriod      *timeutil.ClosedPeriod `json:"currentUsagePeriod,omitempty"`
	PreserveOverageAtReset  *bool                  `json:"preserveOverageAtReset,omitempty"`
}

type CustomerEntitlementAPIService

type CustomerEntitlementAPIService interface {
	CreateCustomerEntitlement(ctx context.Context, input CreateCustomerEntitlementInput) (*Entitlement, error)
	OverrideCustomerEntitlement(ctx context.Context, input OverrideCustomerEntitlementInput) (*Entitlement, error)
	GetCustomerEntitlementHistory(ctx context.Context, input GetCustomerEntitlementHistoryInput) (CustomerEntitlementHistory, error)
	GetCustomerEntitlement(ctx context.Context, input GetCustomerEntitlementInput) (*Entitlement, error)
	ListCustomerEntitlements(ctx context.Context, input ListCustomerEntitlementsInput) (pagination.Result[Entitlement], error)
	ResetCustomerEntitlementUsage(ctx context.Context, input ResetCustomerEntitlementUsageInput) error
	DeleteCustomerEntitlement(ctx context.Context, input DeleteCustomerEntitlementInput) error
	ListCustomerEntitlementGrants(ctx context.Context, input ListCustomerEntitlementGrantsInput) (pagination.Result[grant.Grant], error)
	CreateCustomerEntitlementGrant(ctx context.Context, input CreateCustomerEntitlementGrantInput) (grant.Grant, error)
}

CustomerEntitlementAPIService is the API-facing facade for customer-scoped entitlement operations. Every operation resolves the customer and rejects deleted customers; operations addressing an entitlement report one owned by another customer as not found.

type CustomerEntitlementAccess

type CustomerEntitlementAccess struct {
	FeatureKey string
	Type       EntitlementType
	Value      EntitlementValue
}

CustomerEntitlementAccess carries the entitlement type separately from the value because an inactive entitlement yields a NoAccessValue that no longer identifies its type.

type CustomerEntitlementAccessAPIService

type CustomerEntitlementAccessAPIService interface {
	GetCustomerEntitlementAccess(ctx context.Context, input GetCustomerEntitlementAccessInput) (CustomerEntitlementAccess, error)
	ListCustomerEntitlementAccess(ctx context.Context, input ListCustomerEntitlementAccessInput) ([]CustomerEntitlementAccess, error)
}

CustomerEntitlementAccessAPIService is the API-facing facade for customer-scoped entitlement access. It resolves the customer, rejects deleted customers, and hides inactive entitlements so handlers only map the result.

type CustomerEntitlementHistory

type CustomerEntitlementHistory struct {
	Windows  []BalanceHistoryWindow
	Burndown engine.GrantBurnDownHistory
}

type DeleteCustomerEntitlementInput

type DeleteCustomerEntitlementInput struct {
	CustomerID    customer.CustomerID
	EntitlementID string
}

DeleteCustomerEntitlementInput addresses an entitlement by ID within the customer referenced by ID. An entitlement that belongs to another customer is reported as not found.

func (DeleteCustomerEntitlementInput) Validate

type Entitlement

type Entitlement struct {
	GenericProperties

	// All none-core fields are optional
	// metered
	MeasureUsageFrom        *time.Time `json:"measureUsageFrom,omitempty"`
	IssueAfterReset         *float64   `json:"issueAfterReset,omitempty"`
	IssueAfterResetPriority *uint8     `json:"issueAfterResetPriority,omitempty"`
	IsSoftLimit             *bool      `json:"isSoftLimit,omitempty"`
	LastReset               *time.Time `json:"lastReset,omitempty"`
	PreserveOverageAtReset  *bool      `json:"preserveOverageAtReset,omitempty"`

	// static
	Config *string `json:"config,omitempty"`

	// UnitConfig is the rate card's UnitConfig snapshotted onto the entitlement
	// (metered entitlements only). See CreateEntitlementInputs.UnitConfig.
	UnitConfig *unitconfig.UnitConfig `json:"unitConfig,omitempty"`
}

Normalized representation of an entitlement in the system

func (Entitlement) AsCreateEntitlementInputs

func (e Entitlement) AsCreateEntitlementInputs(cust customer.Customer) CreateEntitlementInputs

func (Entitlement) GetCadence

func (e Entitlement) GetCadence() models.CadencedModel

func (Entitlement) GetType

func (e Entitlement) GetType() EntitlementType

func (Entitlement) IsActive

func (e Entitlement) IsActive(at time.Time) bool

IsActive returns if the entitlement is active at the given time Period start is determined by

type EntitlementAPIService

type EntitlementAPIService interface {
	GetEntitlementByID(ctx context.Context, input GetEntitlementByIDInput) (*Entitlement, error)
	ListNamespaceEntitlements(ctx context.Context, input ListNamespaceEntitlementsInput) (pagination.Result[Entitlement], error)
}

EntitlementAPIService is the API-facing facade for namespace-wide entitlement operations that are not scoped to a single customer.

type EntitlementCreatedEventV2

type EntitlementCreatedEventV2 entitlementEventV2

func NewEntitlementCreatedEventPayloadV2

func NewEntitlementCreatedEventPayloadV2(ent Entitlement, c *customer.Customer) EntitlementCreatedEventV2

func (EntitlementCreatedEventV2) EventMetadata

func (EntitlementCreatedEventV2) EventName

func (e EntitlementCreatedEventV2) EventName() string

func (EntitlementCreatedEventV2) Validate

func (e EntitlementCreatedEventV2) Validate() error

type EntitlementDeletedEventV2

type EntitlementDeletedEventV2 entitlementEventV2

func NewEntitlementDeletedEventPayloadV2

func NewEntitlementDeletedEventPayloadV2(ent Entitlement, c *customer.Customer) EntitlementDeletedEventV2

func (EntitlementDeletedEventV2) EventMetadata

func (EntitlementDeletedEventV2) EventName

func (e EntitlementDeletedEventV2) EventName() string

func (EntitlementDeletedEventV2) Validate

func (e EntitlementDeletedEventV2) Validate() error

type EntitlementRepo

type EntitlementRepo interface {
	// GetActiveEntitlementOfSubjectAt returns the active entitlement of a customer at a given time by feature key
	GetActiveEntitlementOfCustomerAt(ctx context.Context, namespace string, customerID string, featureKey string, at time.Time) (*Entitlement, error)

	// GetScheduledEntitlements returns all scheduled entitlements for a given customer-feature pair that become inactive after the given time, sorted by the time they become active
	GetScheduledEntitlements(ctx context.Context, namespace string, customerID string, featureKey string, starting time.Time) ([]Entitlement, error)

	// DeactivateEntitlement deactivates an entitlement by setting the activeTo time. If the entitlement is already deactivated, it returns an error.
	DeactivateEntitlement(ctx context.Context, entitlementID models.NamespacedID, at time.Time) error

	CreateEntitlement(ctx context.Context, entitlement CreateEntitlementRepoInputs) (*Entitlement, error)
	GetEntitlement(ctx context.Context, entitlementID models.NamespacedID) (*Entitlement, error)
	DeleteEntitlement(ctx context.Context, entitlementID models.NamespacedID, at time.Time) error

	ListEntitlements(ctx context.Context, params ListEntitlementsParams) (pagination.Result[Entitlement], error)

	// ListNamespacesWithActiveEntitlements returns a list of namespaces that have active entitlements
	//
	// Active in this context means the entitlement is active at any point between now and the given time.
	// If includeDeletedAfter is before the current time, it will include namespaces that have entitlements active at that instance.
	ListNamespacesWithActiveEntitlements(ctx context.Context, includeDeletedAfter time.Time) ([]string, error)

	UpdateEntitlementUsagePeriod(ctx context.Context, entitlementID models.NamespacedID, params UpdateEntitlementUsagePeriodParams) error

	// ListActiveEntitlementsWithExpiredUsagePeriod returns a list of active entitlements with usage period that expired before the highwatermark
	// - Only entitlements active at the highwatermark are considered.
	// - The list is sorted by the current usage period end, then by created at, then by id.
	// - The list is paginated by the cursor & limit.
	// - CurrentUsagePeriod won't be mapped to the calculated values
	ListActiveEntitlementsWithExpiredUsagePeriod(ctx context.Context, params ListExpiredEntitlementsParams) ([]Entitlement, error)

	// UpsertEntitlementCurrentPeriods upserts the current usage period for a list of entitlements
	// - If an entitlement is found, it will be updated
	// - If any update fails, the entire operation will fail
	UpsertEntitlementCurrentPeriods(ctx context.Context, updates []UpsertEntitlementCurrentPeriodElement) error

	LockEntitlementForTx(ctx context.Context, tx *entutils.TxDriver, entitlementID models.NamespacedID, wait bool) error

	entutils.TxCreator
}

type EntitlementType

type EntitlementType string
const (
	// EntitlementTypeMetered represents entitlements where access is determined by usage and balance calculations
	EntitlementTypeMetered EntitlementType = "metered"
	// EntitlementTypeStatic represents entitlements where access is described by a static configuration
	EntitlementTypeStatic EntitlementType = "static"
	// EntitlementTypeBoolean represents boolean access
	EntitlementTypeBoolean EntitlementType = "boolean"
)

func (EntitlementType) StrValues

func (e EntitlementType) StrValues() []string

func (EntitlementType) String

func (e EntitlementType) String() string

func (EntitlementType) Values

func (e EntitlementType) Values() []EntitlementType

type EntitlementValue

type EntitlementValue interface {
	HasAccess() bool
}

type EntitlementValueWithId

type EntitlementValueWithId struct {
	Type  EntitlementType
	Value EntitlementValue
	ID    string
}

type EntitlementWithCustomer

type EntitlementWithCustomer struct {
	Entitlement
	Customer customer.Customer
}

type ForbiddenError

type ForbiddenError struct {
	Message string
}

func (*ForbiddenError) Error

func (e *ForbiddenError) Error() string

type GenericProperties

type GenericProperties struct {
	models.NamespacedModel
	models.ManagedModel
	models.MetadataModel
	models.Annotations

	// ActiveFrom allows entitlements to be scheduled for future activation.
	// If not set, the entitlement is active immediately.
	ActiveFrom *time.Time `json:"activeFrom,omitempty"`
	// ActiveTo allows entitlements to be descheduled for future activation.
	// If not set, the entitlement is active until deletion.
	ActiveTo *time.Time `json:"activeTo,omitempty"`

	ID         string `json:"id,omitempty"`
	FeatureID  string `json:"featureId,omitempty"`
	FeatureKey string `json:"featureKey,omitempty"`

	CustomerID string `json:"customerId,omitempty"`

	EntitlementType           EntitlementType        `json:"type,omitempty"`
	UsagePeriod               *UsagePeriod           `json:"usagePeriod,omitempty"`
	CurrentUsagePeriod        *timeutil.ClosedPeriod `json:"currentUsagePeriod,omitempty"`
	OriginalUsagePeriodAnchor *time.Time             `json:"originalUsagePeriodAnchor,omitempty"`
}

GenericProperties is the core fields of an entitlement that are always applicable regadless of type

func (GenericProperties) ActiveFromTime

func (e GenericProperties) ActiveFromTime() time.Time

ActiveFromTime returns the time the entitlement is active from. Its either the ActiveFrom field or the CreatedAt field

func (GenericProperties) ActiveToTime

func (e GenericProperties) ActiveToTime() *time.Time

ActiveToTime returns the time the entitlement is active to. Its either the ActiveTo field or the DeletedAt field or nil

func (GenericProperties) Validate

func (e GenericProperties) Validate() error

type GetCustomerEntitlementAccessInput

type GetCustomerEntitlementAccessInput struct {
	CustomerID    customer.CustomerID
	FeatureKey    string
	EntitlementID string
	At            time.Time
}

GetCustomerEntitlementAccessInput addresses the entitlement by exactly one of FeatureKey or EntitlementID.

func (GetCustomerEntitlementAccessInput) Validate

type GetCustomerEntitlementHistoryInput

type GetCustomerEntitlementHistoryInput struct {
	CustomerID    customer.CustomerID
	EntitlementID string
	From          *time.Time
	To            *time.Time
	WindowSize    meter.WindowSize
	TimeZone      *time.Location
}

GetCustomerEntitlementHistoryInput queries the history of a metered entitlement. From defaults to the last reset and To to the current time; TimeZone defaults to UTC.

func (GetCustomerEntitlementHistoryInput) Validate

type GetCustomerEntitlementInput

type GetCustomerEntitlementInput struct {
	CustomerID    customer.CustomerID
	EntitlementID string
}

GetCustomerEntitlementInput addresses an entitlement by ID within the customer referenced by ID. An entitlement that belongs to another customer is reported as not found.

func (GetCustomerEntitlementInput) Validate

func (i GetCustomerEntitlementInput) Validate() error

type GetEntitlementByIDInput

type GetEntitlementByIDInput struct {
	Namespace     string
	EntitlementID string
}

func (GetEntitlementByIDInput) Validate

func (i GetEntitlementByIDInput) Validate() error

type GrantAPIService

type GrantAPIService interface {
	ListNamespaceGrants(ctx context.Context, input ListNamespaceGrantsInput) (pagination.Result[grant.Grant], error)
	VoidGrant(ctx context.Context, input VoidGrantInput) error
}

GrantAPIService is the API-facing facade for grant operations that are not scoped to a single customer entitlement.

type InvalidFeatureError

type InvalidFeatureError struct {
	FeatureID string
	Message   string
}

func (*InvalidFeatureError) Error

func (e *InvalidFeatureError) Error() string

type InvalidValueError

type InvalidValueError struct {
	Message string
	Type    EntitlementType
}

func (*InvalidValueError) Error

func (e *InvalidValueError) Error() string

type ListCustomerEntitlementAccessInput

type ListCustomerEntitlementAccessInput struct {
	CustomerID customer.CustomerID
}

func (ListCustomerEntitlementAccessInput) Validate

type ListCustomerEntitlementGrantsInput

type ListCustomerEntitlementGrantsInput struct {
	CustomerID    customer.CustomerID
	EntitlementID string

	IncludeDeleted bool

	OrderBy grant.OrderBy
	Order   sortx.Order
	Page    pagination.Page
}

ListCustomerEntitlementGrantsInput lists the grants of the entitlement referenced by ID within the customer referenced by ID. Grants only exist for metered entitlements, so the list of any other entitlement type is empty. Deleted grants are excluded unless IncludeDeleted is set; voided and expired grants are always part of the list as they remain part of the balance history.

func (ListCustomerEntitlementGrantsInput) Validate

type ListCustomerEntitlementsInput

type ListCustomerEntitlementsInput struct {
	CustomerID customer.CustomerID

	FeatureID  *filter.FilterULID
	FeatureKey *filter.FilterString
	Type       *filter.FilterString

	OrderBy ListEntitlementsOrderBy
	Order   sortx.Order
	Page    pagination.Page
}

ListCustomerEntitlementsInput lists the entitlements of the customer referenced by ID that are active at the time of the call. An unset OrderBy sorts by creation time so pagination is stable.

func (ListCustomerEntitlementsInput) Validate

func (i ListCustomerEntitlementsInput) Validate() error

type ListEntitlementsOrderBy

type ListEntitlementsOrderBy string
const (
	ListEntitlementsOrderByCreatedAt ListEntitlementsOrderBy = "created_at"
	ListEntitlementsOrderByUpdatedAt ListEntitlementsOrderBy = "updated_at"
)

func (ListEntitlementsOrderBy) StrValues

func (o ListEntitlementsOrderBy) StrValues() []string

func (ListEntitlementsOrderBy) Values

type ListEntitlementsParams

type ListEntitlementsParams struct {
	IDs              []string
	Namespaces       []string
	SubjectKeys      []string
	CustomerIDs      []string
	CustomerKeys     []string
	FeatureIDs       []string
	FeatureKeys      []string
	FeatureIDsOrKeys []string
	EntitlementTypes []EntitlementType

	CustomerID      *filter.FilterULID
	FeatureID       *filter.FilterULID
	FeatureKey      *filter.FilterString
	EntitlementType *filter.FilterString

	OrderBy ListEntitlementsOrderBy
	Order   sortx.Order
	// TODO[galexi]: We should clean up how these 4 fields are used together.
	IncludeDeleted      bool
	IncludeDeletedAfter time.Time
	ExcludeInactive     bool
	ActiveAt            *time.Time

	Page pagination.Page
	// will be deprecated
	Limit int
	// will be deprecated
	Offset int
}

type ListEntitlementsWithCustomerResult

type ListEntitlementsWithCustomerResult struct {
	Entitlements  pagination.Result[Entitlement]
	CustomersByID map[models.NamespacedID]*customer.Customer
}

type ListExpiredEntitlementsParams

type ListExpiredEntitlementsParams struct {
	Namespaces    []string
	Highwatermark time.Time
	Limit         int
	// Cursor is the ID of the last entitlement in the previous page
	// If not provided, the query will return the first page of results
	Cursor *paginationv2.Cursor
}

type ListNamespaceEntitlementsInput

type ListNamespaceEntitlementsInput struct {
	Namespace string

	CustomerID *filter.FilterULID
	FeatureID  *filter.FilterULID
	FeatureKey *filter.FilterString
	Type       *filter.FilterString

	OrderBy ListEntitlementsOrderBy
	Order   sortx.Order
	Page    pagination.Page
}

ListNamespaceEntitlementsInput lists the entitlements of every customer in the namespace that are active at the time of the call. An unset OrderBy sorts by creation time so pagination is stable.

func (ListNamespaceEntitlementsInput) Validate

type ListNamespaceGrantsInput

type ListNamespaceGrantsInput struct {
	Namespace      string
	IncludeDeleted bool

	CustomerID *filter.FilterULID
	FeatureID  *filter.FilterULID

	OrderBy grant.OrderBy
	Order   sortx.Order
	Page    pagination.Page
}

ListNamespaceGrantsInput lists the grants of every entitlement in the namespace. Deleted grants and the grants of deleted entitlements are excluded unless IncludeDeleted is set; voided and expired grants are always listed. FeatureIDsOrKeys matches the entitlement's feature by either its ID or its key.

func (ListNamespaceGrantsInput) Validate

func (i ListNamespaceGrantsInput) Validate() error

type MeasureUsageFromEnum

type MeasureUsageFromEnum string
const (
	MeasureUsageFromCurrentPeriodStart MeasureUsageFromEnum = "CURRENT_PERIOD_START"
	MeasureUsageFromNow                MeasureUsageFromEnum = "NOW"
)

func (MeasureUsageFromEnum) Validate

func (e MeasureUsageFromEnum) Validate() error

func (MeasureUsageFromEnum) Values

type MeasureUsageFromInput

type MeasureUsageFromInput struct {
	// contains filtered or unexported fields
}

func (MeasureUsageFromInput) Equal

func (*MeasureUsageFromInput) FromEnum

func (*MeasureUsageFromInput) FromTime

func (m *MeasureUsageFromInput) FromTime(t time.Time) error

func (MeasureUsageFromInput) Get

type NoAccessValue

type NoAccessValue struct{}

func (*NoAccessValue) HasAccess

func (*NoAccessValue) HasAccess() bool

type NotFoundError

type NotFoundError struct {
	EntitlementID models.NamespacedID
}

func (*NotFoundError) Error

func (e *NotFoundError) Error() string

type OverrideCustomerEntitlementInput

type OverrideCustomerEntitlementInput struct {
	CustomerID    customer.CustomerID
	EntitlementID string
	Entitlement   CreateEntitlementInputs
	Grants        []CreateEntitlementGrantInputs
}

OverrideCustomerEntitlementInput replaces the entitlement referenced by ID with a new one created from Entitlement and Grants, following the same rules as CreateCustomerEntitlementInput.

func (OverrideCustomerEntitlementInput) Validate

type ResetCustomerEntitlementUsageInput

type ResetCustomerEntitlementUsageInput struct {
	CustomerID      customer.CustomerID
	EntitlementID   string
	EffectiveAt     *time.Time
	RetainAnchor    bool
	PreserveOverage *bool
}

ResetCustomerEntitlementUsageInput starts a new usage period for a metered entitlement. EffectiveAt defaults to the current time; the credit connector rejects a time in the future or before the last reset. A nil PreserveOverage keeps the entitlement's own overage setting.

func (ResetCustomerEntitlementUsageInput) Validate

type Service

type Service interface {
	models.ServiceHooks[Entitlement]

	// Facade interfaces provide convenience helpers for the API layer.
	CustomerEntitlementAccessAPIService
	CustomerEntitlementAPIService
	EntitlementAPIService
	GrantAPIService

	// Meant for API use primarily
	CreateEntitlement(ctx context.Context, input CreateEntitlementInputs, grants []CreateEntitlementGrantInputs) (*Entitlement, error)
	// OverrideEntitlement replaces a currently active entitlement with a new one.
	OverrideEntitlement(ctx context.Context, customerID string, entitlementIdOrFeatureKey string, input CreateEntitlementInputs, grants []CreateEntitlementGrantInputs) (*Entitlement, error)

	ScheduleEntitlement(ctx context.Context, input CreateEntitlementInputs) (*Entitlement, error)
	// SupersedeEntitlement replaces an entitlement by scheduling a new one
	SupersedeEntitlement(ctx context.Context, entitlementId string, input CreateEntitlementInputs) (*Entitlement, error)

	GetEntitlement(ctx context.Context, namespace string, id string) (*Entitlement, error)
	GetEntitlementWithCustomer(ctx context.Context, namespace string, id string) (*EntitlementWithCustomer, error)
	DeleteEntitlement(ctx context.Context, namespace string, id string, at time.Time) error

	GetEntitlementValue(ctx context.Context, namespace string, customerID string, idOrFeatureKey string, at time.Time) (EntitlementValue, error)

	GetEntitlementsOfCustomer(ctx context.Context, namespace string, customerId string, at time.Time) ([]Entitlement, error)
	ListEntitlements(ctx context.Context, params ListEntitlementsParams) (pagination.Result[Entitlement], error)
	ListEntitlementsWithCustomer(ctx context.Context, params ListEntitlementsParams) (ListEntitlementsWithCustomerResult, error)

	// Attempts to get the entitlement in an ambiguous situation where it's unclear if the entitlement is referenced by ID or FeatureKey + CustomerID.
	// First attempts to resolve by ID, then by FeatureKey + CustomerID.
	//
	// For consistency, it is forbidden for entitlements to be created for featueres the keys of which could be mistaken for entitlement IDs.
	GetEntitlementOfCustomerAt(ctx context.Context, namespace string, customerID string, idOrFeatureKey string, at time.Time) (*Entitlement, error)

	// GetAccess returns the access of a customer.
	// It returns a map of featureKey to entitlement value + ID.
	GetAccess(ctx context.Context, namespace string, customerID string) (Access, error)
}

type SubTypeConnector

type SubTypeConnector interface {
	GetValue(ctx context.Context, entitlement *Entitlement, at time.Time) (EntitlementValue, error)

	// Runs before creating the entitlement, building the Repository inputs.
	// If it returns an error the operation has to fail.
	BeforeCreate(entitlement CreateEntitlementInputs, feature feature.Feature) (*CreateEntitlementRepoInputs, error)

	// Runs after entitlement creation.
	// If it returns an error the operation has to fail.
	AfterCreate(ctx context.Context, entitlement *Entitlement) error
}

FIXME[galexi]: we can get rid of this concept due to better hierarchy

type TypedEntitlement

type TypedEntitlement interface {
	GetType() EntitlementType
}

type UniquenessConstraintError

type UniquenessConstraintError struct {
	E1, E2 Entitlement
}

func (*UniquenessConstraintError) Error

func (e *UniquenessConstraintError) Error() string

type UpdateEntitlementUsagePeriodParams

type UpdateEntitlementUsagePeriodParams struct {
	CurrentUsagePeriod timeutil.ClosedPeriod
}

type UpsertEntitlementCurrentPeriodElement

type UpsertEntitlementCurrentPeriodElement struct {
	models.NamespacedID
	CurrentUsagePeriod timeutil.ClosedPeriod
}

type UsagePeriod

type UsagePeriod struct {
	// contains filtered or unexported fields
}

func NewStartingUsagePeriod

func NewStartingUsagePeriod(rec timeutil.Recurrence, start time.Time) UsagePeriod

func NewUsagePeriod

func NewUsagePeriod(recs []timeutil.Timed[timeutil.Recurrence]) UsagePeriod

When providing an initial value (single element in list), for metered entitlements, timed.GetTime() should return measureUsageFrom!

func NewUsagePeriodFromRecurrence

func NewUsagePeriodFromRecurrence(rec timeutil.Recurrence) UsagePeriod

Intended for testing mainly

func (UsagePeriod) Equal

func (u UsagePeriod) Equal(other UsagePeriod) bool

func (UsagePeriod) GetCurrentPeriodAt

func (u UsagePeriod) GetCurrentPeriodAt(at time.Time) (timeutil.ClosedPeriod, error)

func (*UsagePeriod) GetOriginalValueAsUsagePeriodInput

func (u *UsagePeriod) GetOriginalValueAsUsagePeriodInput() *UsagePeriodInput

func (UsagePeriod) GetResetTimelineInclusive

func (u UsagePeriod) GetResetTimelineInclusive(inPeriod timeutil.ClosedPeriod) (timeutil.SimpleTimeline, error)

func (UsagePeriod) GetUsagePeriodInputAt

func (u UsagePeriod) GetUsagePeriodInputAt(at time.Time) (UsagePeriodInput, int, error)

func (UsagePeriod) MarshalJSON

func (u UsagePeriod) MarshalJSON() ([]byte, error)

func (*UsagePeriod) UnmarshalJSON

func (u *UsagePeriod) UnmarshalJSON(data []byte) error

func (UsagePeriod) Validate

func (u UsagePeriod) Validate() error

type UsagePeriodInput

type UsagePeriodInput = timeutil.Timed[timeutil.Recurrence]

func NewStartingUsagePeriodInput

func NewStartingUsagePeriodInput(rec timeutil.Recurrence, start time.Time) UsagePeriodInput

func NewUsagePeriodInputFromRecurrence

func NewUsagePeriodInputFromRecurrence(rec timeutil.Recurrence) UsagePeriodInput

Intended for testing mainly

type VoidGrantInput

type VoidGrantInput struct {
	GrantID models.NamespacedID
	At      *time.Time
}

VoidGrantInput voids a grant from At, or from the time of the call when At is unset. Usage already deducted from the grant is kept.

func (VoidGrantInput) Validate

func (i VoidGrantInput) Validate() error

type WrongTypeError

type WrongTypeError struct {
	Expected EntitlementType
	Actual   EntitlementType
}

func (*WrongTypeError) Error

func (e *WrongTypeError) Error() string

Directories

Path Synopsis
v2
hooks
validators

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL