grants

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Overview

Package grants stores short-lived broker approval grants.

Index

Constants

View Source
const (
	NotificationStatusReserved    = "reserved"
	NotificationStatusUsed        = "used"
	NotificationStatusUsedExpired = "used:expired"
)

Variables

View Source
var (
	ErrNotFound             = errors.New("grant not found")
	ErrInvalidDecisionToken = errors.New("invalid grant decision token")
	ErrNotPending           = errors.New("grant is not pending")
	ErrNotActive            = errors.New("grant is not active")
	ErrIdempotencyConflict  = errors.New("idempotency conflict")
	ErrUnsupportedState     = errors.New("unsupported grant state")
)
View Source
var (
	ErrInvalidCursor = errors.New("invalid event cursor")
	ErrCursorExpired = errors.New("event cursor is no longer retained")
)
View Source
var (
	ErrRevisionConflict = errors.New("grant revision conflict")
	ErrInvalidCommand   = errors.New("invalid operator command")
)
View Source
var (
	ErrInvalidGrantCursor = errors.New("invalid grant cursor")
	ErrInvalidQuery       = errors.New("invalid grant query")
)
View Source
var (
	ErrInvalidTransition  = errors.New("invalid grant transition")
	ErrConstraintExceeded = errors.New("approval constraint exceeded")
)

Functions

This section is empty.

Types

type ActivationCheck added in v0.2.0

type ActivationCheck func(context.Context, Grant, ApprovalConstraints) error

ActivationCheck runs under the grant-store lock before approval commits.

type ApprovalConstraints added in v0.2.0

type ApprovalConstraints struct {
	Duration         time.Duration
	MaxUses          usebudget.Limit
	MaxUsesSpecified bool
}

ApprovalConstraints contains provider-neutral approval narrowing.

type DecisionAction added in v0.2.0

type DecisionAction string

DecisionAction is one Operator V1 lifecycle transition.

const (
	ActionApprove DecisionAction = "approve"
	ActionDeny    DecisionAction = "deny"
	ActionRevoke  DecisionAction = "revoke"
)

type Event

type Event struct {
	Cursor        string    `json:"cursor"`
	Kind          EventKind `json:"kind"`
	GrantID       string    `json:"grant_id"`
	Status        Status    `json:"status"`
	UsedCount     int       `json:"used_count"`
	ReservedCount int       `json:"reserved_count"`
	Revision      int64     `json:"revision"`
	Time          time.Time `json:"time"`
}

Event is the safe durable lifecycle notification returned to consumers.

type EventKind

type EventKind string

EventKind identifies one durable grant lifecycle transition.

const (
	EventRequestCreated     EventKind = "request.created"
	EventRequestApproved    EventKind = "request.approved"
	EventRequestDenied      EventKind = "request.denied"
	EventRequestCanceled    EventKind = "request.canceled"
	EventRequestExpired     EventKind = "request.expired"
	EventGrantRevoked       EventKind = "grant.revoked"
	EventGrantReserved      EventKind = "grant.reserved"
	EventGrantConsumed      EventKind = "grant.consumed"
	EventGrantReleased      EventKind = "grant.released"
	EventExecutionSucceeded EventKind = "execution.succeeded"
	EventExecutionFailed    EventKind = "execution.failed"
	EventExecutionAmbiguous EventKind = "execution.ambiguous"
)

type EventPage

type EventPage struct {
	Events     []Event `json:"events"`
	NextCursor string  `json:"next_cursor,omitempty"`
	HasMore    bool    `json:"has_more"`
}

EventPage is one bounded event-cursor result.

type Grant

type Grant struct {
	ID                        string              `json:"id"`
	DecisionTokenVerifier     string              `json:"decision_token_verifier"`
	Client                    string              `json:"client"`
	ClientRequestID           string              `json:"client_request_id,omitempty"`
	Operation                 string              `json:"operation"`
	Target                    policy.Target       `json:"target"`
	Attrs                     map[string][]string `json:"attrs,omitempty"`
	Metadata                  map[string]string   `json:"metadata,omitempty"`
	Reason                    string              `json:"reason"`
	Status                    Status              `json:"status"`
	Revision                  int64               `json:"revision"`
	CreatedAt                 time.Time           `json:"created_at"`
	PendingExpiresAt          time.Time           `json:"pending_expires_at"`
	ExpiresAt                 time.Time           `json:"expires_at,omitzero"`
	Duration                  time.Duration       `json:"duration"`
	RequestedDuration         time.Duration       `json:"requested_duration"`
	PendingTimeout            time.Duration       `json:"pending_timeout"`
	DecidedAt                 time.Time           `json:"decided_at,omitzero"`
	DecidedBy                 string              `json:"decided_by,omitempty"`
	DecidedOnBehalfOf         string              `json:"decided_on_behalf_of,omitempty"`
	UsedAt                    time.Time           `json:"used_at,omitzero"`
	UsedCount                 int                 `json:"used_count"`
	UseRevision               int                 `json:"use_revision,omitempty"`
	ReservedCount             int                 `json:"reserved_count,omitempty"`
	ReservedAt                time.Time           `json:"reserved_at,omitzero"`
	ReservationRetained       bool                `json:"reservation_retained,omitempty"`
	ReservationRevision       int                 `json:"reservation_revision,omitempty"`
	MaxUses                   usebudget.Limit     `json:"max_uses"`
	RequestedMaxUses          usebudget.Limit     `json:"requested_max_uses"`
	RequestedMaxUsesDefaulted bool                `json:"requested_max_uses_defaulted"`
	ExpiredFrom               Status              `json:"expired_from,omitempty"`
	Notification              *MessageRef         `json:"notification,omitempty"`
	NotificationStatus        string              `json:"notification_status,omitempty"`
	NotificationClaimedAt     time.Time           `json:"notification_claimed_at,omitzero"`
	NotificationClaimUntil    time.Time           `json:"notification_claim_until,omitzero"`
	// NotificationDeliveryUnresolved records an ambiguous send attempt until
	// the current claim is completed or reclaimed.
	NotificationDeliveryUnresolved bool `json:"notification_delivery_unresolved,omitempty"`
}

Grant is one durable approval record.

type ImmutablePlan added in v0.2.0

type ImmutablePlan struct {
	Digest     string
	SchemaName string
	Canonical  []byte
	CreatedAt  time.Time
}

ImmutablePlan is the provider-neutral envelope committed with a grant.

type MessageRef

type MessageRef = notify.MessageRef

MessageRef is the durable form of an editable operator notification.

type NotificationClaim

type NotificationClaim struct {
	Grant         Grant  `json:"grant"`
	DecisionToken string `json:"-"`
}

NotificationClaim carries the fresh raw decision token for one claimed delivery attempt. Only its verifier is stored in Grant.

type OperatorDecision added in v0.2.0

type OperatorDecision struct {
	ID               string
	Action           DecisionAction
	Approver         string
	OnBehalfOf       string
	ExpectedRevision int64
	IdempotencyKey   string
	Constraints      ApprovalConstraints
}

OperatorDecision is a normalized revision-bound Operator V1 command.

type OperatorDecisionResult added in v0.2.0

type OperatorDecisionResult struct {
	Grant       Grant
	Previous    Grant
	EventCursor string
	Replay      bool
}

OperatorDecisionResult reports the originally committed representation on replay.

type Options

type Options struct {
	PendingTimeout     time.Duration
	DefaultDuration    time.Duration
	MaxDuration        time.Duration
	ReservationTimeout time.Duration
	MaxEvents          int
	Now                func() time.Time
	NewID              func(int) (string, error)
}

Options configures a Store.

type Page

type Page struct {
	Grants      []Grant `json:"grants"`
	NextCursor  string  `json:"next_cursor,omitempty"`
	HasMore     bool    `json:"has_more"`
	EventCursor string  `json:"event_cursor,omitempty"`
}

Page is one deterministic, bounded grant query result.

type Query

type Query struct {
	StatusGroup StatusGroup
	Client      string
	Operation   string
	Target      *policy.Target
	Cursor      string
	Limit       int
}

Query bounds and filters one operator-inbox listing.

type Request

type Request struct {
	Client           string
	ClientRequestID  string
	Operation        string
	Target           policy.Target
	Attrs            map[string][]string
	Metadata         map[string]string
	Reason           string
	Duration         time.Duration
	PendingTimeout   time.Duration
	MaxUses          usebudget.Limit
	MaxUsesSpecified bool
	MaxUsesDefaulted bool
}

Request creates one pending approval grant.

type RequestResult

type RequestResult struct {
	Grant         Grant  `json:"grant"`
	DecisionToken string `json:"-"`
}

RequestResult returns the durable grant plus the raw one-time decision token needed to notify approvers. The token is not part of Grant and is omitted from JSON so grant/status responses do not leak approval authority.

type RevisionConflictError

type RevisionConflictError struct {
	Current Grant
}

RevisionConflictError returns the authoritative state after a stale command.

func (*RevisionConflictError) Error

func (e *RevisionConflictError) Error() string

func (*RevisionConflictError) Unwrap

func (e *RevisionConflictError) Unwrap() error

type Status

type Status string

Status is a grant lifecycle state.

const (
	StatusPending  Status = "pending"
	StatusActive   Status = "active"
	StatusDenied   Status = "denied"
	StatusExpired  Status = "expired"
	StatusConsumed Status = "consumed"
	StatusRevoked  Status = "revoked"
	StatusCanceled Status = "canceled"
)

Grant status values.

type StatusGroup

type StatusGroup string

StatusGroup selects a useful operator-inbox lifecycle group.

const (
	StatusGroupPending StatusGroup = "pending"
	StatusGroupActive  StatusGroup = "active"
	StatusGroupHistory StatusGroup = "history"
	StatusGroupAll     StatusGroup = "all"
)

type StatusUpdate

type StatusUpdate struct {
	Grant              Grant
	Kind               StatusUpdateKind
	Status             Status
	NotificationStatus string
}

StatusUpdate remains due until MarkNotificationStatus records delivery.

func (StatusUpdate) NotificationStatusKey

func (u StatusUpdate) NotificationStatusKey() string

NotificationStatusKey returns the durable delivery key for this update.

type StatusUpdateKind

type StatusUpdateKind string

StatusUpdateKind describes why an operator notification needs an update.

const (
	StatusUpdateLifecycle           StatusUpdateKind = "lifecycle"
	StatusUpdateRetainedReservation StatusUpdateKind = "retained_reservation"
	StatusUpdateUsed                StatusUpdateKind = "used"
	StatusUpdateUsedExpired         StatusUpdateKind = "used_expired"
)

type Store

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

Store owns one durable grant file.

func New

func New(path string, opts Options) *Store

New returns a Store.

func NewDatabase added in v0.2.0

func NewDatabase(database *state.Database, opts Options) *Store

NewDatabase returns a Store backed by BrokerKit's transactional SQLite state. The database owner remains responsible for closing it.

func (*Store) ActivePolicyGrants

func (s *Store) ActivePolicyGrants() ([]policy.Grant, error)

ActivePolicyGrants returns active grant overlays for policy evaluation.

func (*Store) ApplyOperatorDecision added in v0.2.0

func (s *Store) ApplyOperatorDecision(ctx context.Context, command OperatorDecision, validate ActivationCheck) (OperatorDecisionResult, error)

ApplyOperatorDecision atomically validates and commits one revision-bound decision.

func (*Store) ApprovalNotificationsDue added in v0.2.0

func (s *Store) ApprovalNotificationsDue() ([]Grant, error)

ApprovalNotificationsDue returns pending approval deliveries in durable outbox order. SQLite-backed stores recover these entries after restart.

func (*Store) Approve

func (s *Store) Approve(id string, decisionToken string, approver string) (Grant, error)

Approve activates a pending grant.

func (*Store) ApproveWithNotification

func (s *Store) ApproveWithNotification(id string, decisionToken string, approver string, ref MessageRef) (Grant, error)

ApproveWithNotification atomically approves a pending grant and records a callback-carried notification when no notification is already stored.

func (*Store) ApproveWithNotificationValidated added in v0.2.0

func (s *Store) ApproveWithNotificationValidated(ctx context.Context, id string, decisionToken string, approver string, ref MessageRef, validate ActivationCheck) (TokenDecisionResult, error)

ApproveWithNotificationValidated atomically validates and approves a pending notification-channel grant. The validation runs against the committed grant while the store lock is held.

func (*Store) Cancel

func (s *Store) Cancel(id string) error

Cancel closes a pending grant, usually after notification delivery fails.

func (*Store) CancelForClient added in v0.2.0

func (s *Store) CancelForClient(id, client string) (Grant, error)

CancelForClient atomically cancels a pending grant owned by client.

func (*Store) CancelIfNotificationClaimed

func (s *Store) CancelIfNotificationClaimed(id string, claimedAt time.Time) (Grant, bool, error)

CancelIfNotificationClaimed cancels only while claimedAt is current.

func (*Store) ClaimNotification

func (s *Store) ClaimNotification(id string, lease time.Duration) (NotificationClaim, bool, error)

ClaimNotification reserves notification delivery and rotates its decision token. Stale claims can be reclaimed after a process restart.

func (*Store) CommitUse

func (s *Store) CommitUse(id string) (Grant, error)

CommitUse turns one reservation into a used grant budget.

func (*Store) Deny

func (s *Store) Deny(id string, decisionToken string, approver string) (Grant, error)

Deny denies a pending grant.

func (*Store) DenyWithNotification

func (s *Store) DenyWithNotification(id string, decisionToken string, approver string, ref MessageRef) (Grant, error)

DenyWithNotification atomically denies a pending grant and records a callback-carried notification when no notification is already stored.

func (*Store) DenyWithNotificationResult added in v0.2.0

func (s *Store) DenyWithNotificationResult(ctx context.Context, id string, decisionToken string, approver string, ref MessageRef) (TokenDecisionResult, error)

DenyWithNotificationResult atomically denies a pending notification-channel grant and returns its exact transition correlation.

func (*Store) EventsAfter

func (s *Store) EventsAfter(cursor string, limit int) (EventPage, error)

EventsAfter returns durable events strictly after cursor.

func (*Store) Get

func (s *Store) Get(id string) (Grant, error)

Get returns one grant by id.

func (*Store) LatestEvent

func (s *Store) LatestEvent(id string) (Event, error)

LatestEvent returns the newest retained lifecycle event for one grant.

func (*Store) List

func (s *Store) List() ([]Grant, error)

List returns all durable grants after expiring stale records.

func (*Store) ListForClient

func (s *Store) ListForClient(client string) ([]Grant, error)

ListForClient returns all durable grants for one broker client.

func (*Store) MarkNotificationStatus

func (s *Store) MarkNotificationStatus(id string, status string) error

MarkNotificationStatus records successful delivery of one status update.

func (*Store) QueryGrants

func (s *Store) QueryGrants(query Query) (Page, error)

QueryGrants returns grants newest first, with ID as a stable tiebreaker.

func (*Store) RecordExecution

func (s *Store) RecordExecution(id string, kind EventKind) (Event, error)

RecordExecution appends one safe provider execution outcome event.

func (*Store) ReleaseUse

func (s *Store) ReleaseUse(id string) (Grant, error)

ReleaseUse releases one reserved grant use.

func (*Store) Request

func (s *Store) Request(req Request) (RequestResult, bool, error)

Request creates or returns an idempotent pending grant.

func (*Store) RequestWithPlan added in v0.2.0

func (s *Store) RequestWithPlan(req Request, plan ImmutablePlan) (RequestResult, bool, error)

RequestWithPlan atomically creates or replays a SQLite-backed grant and its immutable provider plan.

func (*Store) ReserveUse

func (s *Store) ReserveUse(id string) (Grant, error)

ReserveUse durably reserves one active grant use before execution.

func (*Store) RetainNotificationClaim

func (s *Store) RetainNotificationClaim(id string, claimedAt time.Time) (Grant, bool, error)

RetainNotificationClaim marks the current send attempt as ambiguous without canceling the grant or making the claim immediately reusable.

func (*Store) RetainUse

func (s *Store) RetainUse(id string) (Grant, error)

RetainUse preserves a reserved use for operator review after an ambiguous execution result.

func (*Store) Revoke

func (s *Store) Revoke(id string, approver string) (Grant, error)

Revoke closes an active grant.

func (*Store) RevokeForClient added in v0.2.0

func (s *Store) RevokeForClient(id, client string) (Grant, error)

RevokeForClient atomically revokes an active grant owned by client.

func (*Store) SetNotification

func (s *Store) SetNotification(id string, ref MessageRef) (Grant, error)

SetNotification records the editable operator notification for a grant.

func (*Store) SetNotificationIfClaimed

func (s *Store) SetNotificationIfClaimed(id string, claimedAt time.Time, ref MessageRef) (Grant, bool, error)

SetNotificationIfClaimed records ref only if claimedAt is still current.

func (*Store) SetNotificationIfMissing

func (s *Store) SetNotificationIfMissing(id string, ref MessageRef) (Grant, bool, error)

SetNotificationIfMissing records ref only when the grant has no notification. Consumers use this to recover the message reference carried by an accepted callback after an earlier send returned an ambiguous error.

func (*Store) StatusUpdatesDue

func (s *Store) StatusUpdatesDue() ([]StatusUpdate, error)

StatusUpdatesDue expires grants, recovers stale reservations, and returns notification updates that have not been delivered successfully.

func (*Store) SupportsPlanTransactions added in v0.2.0

func (s *Store) SupportsPlanTransactions() bool

SupportsPlanTransactions reports whether immutable plans can commit with grant creation in one database transaction.

func (*Store) WaitForEvents

func (s *Store) WaitForEvents(ctx context.Context, cursor string) (EventPage, error)

WaitForEvents blocks until an event exists after cursor or ctx is canceled.

type TokenDecisionResult added in v0.2.0

type TokenDecisionResult struct {
	Grant       Grant
	Previous    Grant
	EventCursor string
	Changed     bool
}

TokenDecisionResult correlates one token-bound transition with its durable event.

Jump to

Keyboard shortcuts

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