service

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrOperatorNotFound   = errors.New("operator not found")
	ErrUsernameExists     = errors.New("username already exists")
	ErrInvalidCredentials = errors.New("invalid credentials")
	ErrSetupAlreadyDone   = errors.New("setup has already been completed")
	ErrNoOperatorsExist   = errors.New("no operators exist; run setup first")
	ErrIncorrectPassword  = errors.New("current password is incorrect")
	ErrCannotDeleteSelf   = errors.New("cannot delete yourself")
	ErrLastOperator       = errors.New("cannot delete the last operator")
)
View Source
var (
	ErrPolicyNotFound           = errors.New("policy not found")
	ErrPolicyTypeConflict       = errors.New("a policy for this request type already exists")
	ErrNoStages                 = errors.New("policy must have at least one approval stage")
	ErrInvalidStageIndex        = errors.New("stage indices must be sequential starting from 0")
	ErrInvalidDisplayTemplate   = errors.New("invalid display template")
	ErrThresholdNoMaxCheckers   = errors.New("max_checkers is required when rejection_policy is 'threshold'")
	ErrInvalidAuthorizationMode = errors.New("authorization_mode must be 'any' or 'all' when both allowed_checker_roles and allowed_permissions are set")
)
View Source
var (
	ErrRequestNotFound          = errors.New("request not found")
	ErrRequestNotPending        = errors.New("request is not in pending status")
	ErrDuplicateRequest         = errors.New("a pending request with the same identity already exists")
	ErrIdempotencyConflict      = errors.New("request with this idempotency key already exists")
	ErrSelfApproval             = errors.New("maker cannot approve their own request")
	ErrAlreadyActioned          = errors.New("checker has already acted on this request")
	ErrInvalidCheckerRole       = errors.New("checker does not have a required role")
	ErrInvalidCheckerPermission = errors.New("checker does not have a required permission")
	ErrNotEligibleReviewer      = errors.New("checker is not in the eligible reviewers list")
	ErrInvalidStage             = errors.New("request is at an invalid stage for this policy")
	ErrMissingIdentityFields    = errors.New("missing identity field in payload")
)
View Source
var (
	ErrTenantNotFound     = errors.New("tenant not found")
	ErrTenantSlugExists   = errors.New("tenant slug already exists")
	ErrTenantSlugInvalid  = errors.New("tenant slug must be lowercase alphanumeric with hyphens only")
	ErrTenantSlugRequired = errors.New("tenant slug is required")
	ErrTenantNameRequired = errors.New("tenant name is required")
)
View Source
var (
	ErrWebhookNotFound   = errors.New("webhook not found")
	ErrWebhookValidation = errors.New("webhook validation error")
)

Functions

This section is empty.

Types

type ExpiryWorker

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

func NewExpiryWorker

func NewExpiryWorker(requests store.RequestStore, audits store.AuditStore, checkInterval time.Duration) *ExpiryWorker

func (*ExpiryWorker) SetMetrics

func (w *ExpiryWorker) SetMetrics(m *metrics.Metrics)

SetMetrics sets the optional Prometheus metrics collector.

func (*ExpiryWorker) SetSSESignal

func (w *ExpiryWorker) SetSSESignal(signal func(requestID uuid.UUID))

SetSSESignal configures the callback invoked after a request expires to notify connected SSE clients.

func (*ExpiryWorker) SetWebhookDispatch

func (w *ExpiryWorker) SetWebhookDispatch(
	runInTx func(ctx context.Context, fn func(tx *store.Stores) error) error,
	enqueue func(ctx context.Context, outbox store.OutboxStore, webhooks store.WebhookStore, req *model.Request, approvals []model.Approval) error,
	signal func(),
)

SetWebhookDispatch configures transactional webhook dispatch for expired requests.

func (*ExpiryWorker) Start

func (w *ExpiryWorker) Start(ctx context.Context)

type OperatorService

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

OperatorService handles operator management and authentication for the admin console.

func NewOperatorService

func NewOperatorService(operators store.OperatorStore, jwtSecret string) *OperatorService

NewOperatorService creates a new OperatorService. If jwtSecret is empty, a random 32-byte secret is generated (sessions won't survive restarts).

func (*OperatorService) ChangePassword

func (s *OperatorService) ChangePassword(ctx context.Context, operatorID uuid.UUID, currentPassword, newPassword string) error

ChangePassword changes an operator's password. Requires the current password for verification.

func (*OperatorService) CreateOperator

func (s *OperatorService) CreateOperator(ctx context.Context, username, password, displayName string) (*model.Operator, error)

CreateOperator creates a new operator (called by an existing operator).

func (*OperatorService) DeleteOperator

func (s *OperatorService) DeleteOperator(ctx context.Context, callerID, targetID uuid.UUID) error

DeleteOperator deletes an operator. Cannot delete yourself or the last operator.

func (*OperatorService) GetCurrentOperator

func (s *OperatorService) GetCurrentOperator(ctx context.Context, id uuid.UUID) (*model.Operator, error)

GetCurrentOperator returns the operator for the given ID.

func (*OperatorService) ListOperators

func (s *OperatorService) ListOperators(ctx context.Context, filter store.OperatorFilter) ([]model.Operator, int, error)

func (*OperatorService) Login

func (s *OperatorService) Login(ctx context.Context, username, password string) (*model.Operator, string, error)

Login authenticates an operator and returns a JWT token.

func (*OperatorService) NeedsSetup

func (s *OperatorService) NeedsSetup(ctx context.Context) (bool, error)

NeedsSetup returns true if no operators exist yet.

func (*OperatorService) Setup

func (s *OperatorService) Setup(ctx context.Context, username, password, displayName string) (*model.Operator, string, error)

Setup creates the first operator. Returns ErrSetupAlreadyDone if operators already exist.

func (*OperatorService) ValidateToken

func (s *OperatorService) ValidateToken(tokenString string) (*OperatorTokenClaims, error)

ValidateToken parses and validates a JWT token, returning the claims.

type OperatorTokenClaims

type OperatorTokenClaims struct {
	jwt.RegisteredClaims
	Username string `json:"username"`
}

OperatorTokenClaims are the JWT claims for console operator sessions.

type PolicyService

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

func NewPolicyService

func NewPolicyService(policies store.PolicyStore) *PolicyService

func (*PolicyService) Create

func (s *PolicyService) Create(ctx context.Context, policy *model.Policy) error

func (*PolicyService) Delete

func (s *PolicyService) Delete(ctx context.Context, id uuid.UUID) error

func (*PolicyService) DistinctRequestTypes added in v0.1.2

func (s *PolicyService) DistinctRequestTypes(ctx context.Context) ([]string, error)

func (*PolicyService) GetByID

func (s *PolicyService) GetByID(ctx context.Context, id uuid.UUID) (*model.Policy, error)

func (*PolicyService) GetByRequestType

func (s *PolicyService) GetByRequestType(ctx context.Context, requestType string) (*model.Policy, error)

func (*PolicyService) List

func (s *PolicyService) List(ctx context.Context, filter store.PolicyFilter) ([]model.Policy, int, error)

func (*PolicyService) Update

func (s *PolicyService) Update(ctx context.Context, policy *model.Policy) error

type RequestService

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

func NewRequestService

func NewRequestService(
	requests store.RequestStore,
	approvals store.ApprovalStore,
	policies store.PolicyStore,
	audits store.AuditStore,
	authorizationHook *auth.AuthorizationHook,
) *RequestService

func (*RequestService) Approve

func (s *RequestService) Approve(ctx context.Context, requestID uuid.UUID, checkerID string, roles []string, comment *string) (*model.Request, error)

func (*RequestService) CanViewerAct

func (s *RequestService) CanViewerAct(ctx context.Context, req *model.Request, viewerID string, viewerRoles, viewerPermissions []string) bool

CanViewerAct determines whether the given viewer can approve or reject the request based on the same checks enforced by processDecision. The dynamic_authorization_url is intentionally skipped (HTTP call not suitable for the read path); it is still enforced on actual approve/reject.

func (*RequestService) Cancel

func (s *RequestService) Cancel(ctx context.Context, requestID uuid.UUID, makerID string) (*model.Request, error)

func (*RequestService) Create

func (s *RequestService) Create(ctx context.Context, req *model.Request) (*model.Request, error)

func (*RequestService) GetByID

func (s *RequestService) GetByID(ctx context.Context, id uuid.UUID) (*model.Request, error)

func (*RequestService) List

func (s *RequestService) List(ctx context.Context, filter store.RequestFilter) ([]model.Request, int, error)

func (*RequestService) Reject

func (s *RequestService) Reject(ctx context.Context, requestID uuid.UUID, checkerID string, roles []string, comment *string) (*model.Request, error)

func (*RequestService) SetMetrics

func (s *RequestService) SetMetrics(m *metrics.Metrics)

SetMetrics sets the optional Prometheus metrics collector.

func (*RequestService) SetSSESignal

func (s *RequestService) SetSSESignal(signal func(requestID uuid.UUID))

SetSSESignal configures the callback invoked after a request's state changes to notify connected SSE clients. Called post-commit alongside signalWebhooks.

func (*RequestService) SetWebhookDispatch

func (s *RequestService) SetWebhookDispatch(
	runInTx func(ctx context.Context, fn func(tx *store.Stores) error) error,
	enqueue func(ctx context.Context, outbox store.OutboxStore, webhooks store.WebhookStore, req *model.Request, approvals []model.Approval) error,
	signal func(),
)

SetWebhookDispatch configures transactional webhook dispatch via an outbox table. enqueue writes outbox rows (should be called inside a transaction), signal wakes the delivery worker (should be called after the transaction commits), and runInTx executes a function within a database transaction.

type TenantService

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

func NewTenantService

func NewTenantService(tenants store.TenantStore) *TenantService

func (*TenantService) Create

func (s *TenantService) Create(ctx context.Context, slug, name string) (*model.Tenant, error)

func (*TenantService) Delete

func (s *TenantService) Delete(ctx context.Context, id uuid.UUID) error

func (*TenantService) GetBySlug

func (s *TenantService) GetBySlug(ctx context.Context, slug string) (*model.Tenant, error)

func (*TenantService) IsRegistered

func (s *TenantService) IsRegistered(slug string) bool

IsRegistered checks whether a tenant slug exists using the in-memory cache, avoiding a database round-trip on every API request.

func (*TenantService) List

func (s *TenantService) List(ctx context.Context, filter store.TenantFilter) ([]model.Tenant, int, error)

func (*TenantService) LoadCache

func (s *TenantService) LoadCache(ctx context.Context) error

LoadCache pre-populates the in-memory slug set from the database. Call this once during server startup.

func (*TenantService) StartCacheRefresh

func (s *TenantService) StartCacheRefresh(ctx context.Context, interval time.Duration)

StartCacheRefresh runs a background goroutine that periodically reloads the tenant slug cache from the database. This keeps instances in sync when tenants are created or deleted on a different instance. The goroutine stops when ctx is cancelled.

type WebhookService

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

func NewWebhookService

func NewWebhookService(webhooks store.WebhookStore) *WebhookService

func (*WebhookService) Create

func (s *WebhookService) Create(ctx context.Context, webhook *model.Webhook) error

func (*WebhookService) Delete

func (s *WebhookService) Delete(ctx context.Context, id uuid.UUID) error

func (*WebhookService) GetMatchingWebhooks

func (s *WebhookService) GetMatchingWebhooks(ctx context.Context, event string, requestType string) ([]model.Webhook, error)

func (*WebhookService) List

func (s *WebhookService) List(ctx context.Context, filter store.WebhookFilter) ([]model.Webhook, int, error)

Jump to

Keyboard shortcuts

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