service

package
v0.1.8 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrManualApprovalDisabled = errors.New("no matching whitelist rule and manual approval is disabled")

ErrManualApprovalDisabled is returned when no whitelist rule matches and manual approval is disabled. Caller should respond with 403 Forbidden.

Functions

func SubstituteVariables

func SubstituteVariables(configJSON []byte, vars map[string]string) ([]byte, error)

SubstituteVariables replaces ${var} placeholders in config JSON with actual values

Types

type ApprovalRequest

type ApprovalRequest struct {
	Approved   bool                      `json:"approved"`
	ApprovedBy string                    `json:"approved_by"`
	RuleOpts   *rule.RuleGenerateOptions `json:"rule_opts,omitempty"` // Optional: generate rule with these options
}

ApprovalRequest represents the request to approve or reject a signing request

type ApprovalResponse

type ApprovalResponse struct {
	SignResponse  *SignResponse `json:"sign_response"`
	GeneratedRule *types.Rule   `json:"generated_rule,omitempty"`
}

ApprovalResponse represents the response to an approval request

type ApprovalService

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

ApprovalService handles manual approval workflow

func NewApprovalService

func NewApprovalService(
	ruleRepo storage.RuleRepository,
	ruleGenerator rule.RuleGenerator,
	notifier Notifier,
	logger *slog.Logger,
) (*ApprovalService, error)

NewApprovalService creates a new approval service

func (*ApprovalService) GenerateRule

func (s *ApprovalService) GenerateRule(ctx context.Context, req *types.SignRequest, parsed *types.ParsedPayload, opts *rule.RuleGenerateOptions) (*types.Rule, error)

GenerateRule creates and saves a rule based on an approved request with explicit options

func (*ApprovalService) PreviewRule

PreviewRule generates a rule preview without saving it This allows users to see what rule would be created before confirming

func (*ApprovalService) RequestApproval

func (s *ApprovalService) RequestApproval(ctx context.Context, req *types.SignRequest) error

RequestApproval sends a notification for manual approval

func (*ApprovalService) SupportedRuleTypes

func (s *ApprovalService) SupportedRuleTypes() []types.RuleType

SupportedRuleTypes returns the rule types that can be generated

type BudgetConfig

type BudgetConfig struct {
	MaxTotal   string `json:"max_total"`              // per-unit total cap (per period if schedule set)
	MaxPerTx   string `json:"max_per_tx"`             // per-unit per-tx cap
	MaxTxCount int    `json:"max_tx_count,omitempty"` // 0 = unlimited (per period if schedule set)
	AlertPct   int    `json:"alert_pct,omitempty"`    // default 80
}

BudgetConfig defines budget limits for an instance

type CreateInstanceRequest

type CreateInstanceRequest struct {
	TemplateID   string            `json:"template_id"`
	TemplateName string            `json:"template_name,omitempty"` // alternative: look up by name
	Name         string            `json:"name,omitempty"`          // optional override for rule name
	Variables    map[string]string `json:"variables"`

	// Scope
	ChainType     *string `json:"chain_type,omitempty"`
	ChainID       *string `json:"chain_id,omitempty"`
	APIKeyID      *string `json:"api_key_id,omitempty"`
	SignerAddress *string `json:"signer_address,omitempty"`

	// Optional: time-limited
	ExpiresAt *time.Time     `json:"expires_at,omitempty"`
	ExpiresIn *time.Duration `json:"expires_in,omitempty"` // alternative: duration from now

	// Optional: budget
	Budget *BudgetConfig `json:"budget,omitempty"`

	// Optional: periodic renewal (session with schedule)
	Schedule *ScheduleConfig `json:"schedule,omitempty"`
}

CreateInstanceRequest contains all parameters for creating a rule instance from a template

type CreateInstanceResult

type CreateInstanceResult struct {
	Rule   *types.Rule       `json:"rule"`
	Budget *types.RuleBudget `json:"budget,omitempty"`
}

CreateInstanceResult contains the created rule and optional budget

type ManualApprovalGuard

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

ManualApprovalGuard pauses all sign requests when too many consecutive "not auto-approved" outcomes occur within a time window (manual approval or rule-blocked), and sends an alert via notify. Used to detect API key abuse / brute-force: valid API key but requests repeatedly rejected by rules or needing manual approval. After resumeAfter duration it auto-resumes so the team has time to respond.

func NewManualApprovalGuard

func NewManualApprovalGuard(cfg ManualApprovalGuardConfig) (*ManualApprovalGuard, error)

NewManualApprovalGuard creates a new guard. NotifySvc and Channel may be nil when disabled.

func (*ManualApprovalGuard) IsPaused

func (g *ManualApprovalGuard) IsPaused() bool

IsPaused returns true when the guard has triggered and all sign requests should be rejected.

func (*ManualApprovalGuard) RecordManualApproval

func (g *ManualApprovalGuard) RecordManualApproval()

RecordManualApproval records a request that required manual approval (no whitelist match). Counts toward consecutive "rejection" for abuse detection.

func (*ManualApprovalGuard) RecordNonManualApproval

func (g *ManualApprovalGuard) RecordNonManualApproval()

RecordNonManualApproval resets the consecutive counter (request was auto-approved or blocked).

func (*ManualApprovalGuard) RecordRuleRejected

func (g *ManualApprovalGuard) RecordRuleRejected()

RecordRuleRejected records a request that was blocked by a blocklist rule. Counts toward consecutive "rejection" to detect API key abuse / brute-force via valid path.

func (*ManualApprovalGuard) Resume

func (g *ManualApprovalGuard) Resume()

Resume clears the paused state so sign requests are accepted again. Call via admin API or after auto-resume timer.

type ManualApprovalGuardConfig

type ManualApprovalGuardConfig struct {
	Window      time.Duration
	Threshold   int
	ResumeAfter time.Duration // pause duration after which to auto-resume (e.g. 2h); 0 = no auto-resume
	NotifySvc   *notify.NotifyService
	Channel     *notify.Channel
	Logger      *slog.Logger
}

ManualApprovalGuardConfig configures the guard.

type NoopNotifier

type NoopNotifier struct{}

NoopNotifier is a notifier that does nothing (used when notifications are disabled)

func NewNoopNotifier

func NewNoopNotifier() (*NoopNotifier, error)

NewNoopNotifier creates a new no-op notifier

func (*NoopNotifier) SendApprovalRequest

func (n *NoopNotifier) SendApprovalRequest(ctx context.Context, req *types.SignRequest) error

SendApprovalRequest does nothing

type Notifier

type Notifier interface {
	// SendApprovalRequest sends a notification about a pending approval request
	SendApprovalRequest(ctx context.Context, req *types.SignRequest) error
}

Notifier interface for sending notifications

type NotifyServiceNotifier

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

NotifyServiceNotifier implements Notifier using NotifyService

func NewNotifyServiceNotifier

func NewNotifyServiceNotifier(cfg NotifyServiceNotifierConfig) (*NotifyServiceNotifier, error)

NewNotifyServiceNotifier creates a new NotifyServiceNotifier

func (*NotifyServiceNotifier) SendApprovalRequest

func (n *NotifyServiceNotifier) SendApprovalRequest(ctx context.Context, req *types.SignRequest) error

SendApprovalRequest sends an approval notification

type NotifyServiceNotifierConfig

type NotifyServiceNotifierConfig struct {
	NotifyService *notify.NotifyService
	Channels      *notify.Channel
	Priority      int    // Pushover priority (default: 1 for high)
	Sound         string // Pushover sound (default: "persistent")
}

NotifyServiceNotifierConfig configuration for NotifyServiceNotifier

type ScheduleConfig

type ScheduleConfig struct {
	Period  time.Duration `json:"period"`             // e.g. 24h, 168h (7 days)
	StartAt *time.Time    `json:"start_at,omitempty"` // default: now
}

ScheduleConfig defines periodic budget renewal

type SignRequest

type SignRequest struct {
	APIKeyID      string          `json:"api_key_id"`
	ChainType     types.ChainType `json:"chain_type"`
	ChainID       string          `json:"chain_id"`
	SignerAddress string          `json:"signer_address"`
	SignType      string          `json:"sign_type"`
	Payload       []byte          `json:"payload"`
}

SignRequest represents a request to sign data

type SignResponse

type SignResponse struct {
	RequestID  types.SignRequestID     `json:"request_id"`
	Status     types.SignRequestStatus `json:"status"`
	Signature  []byte                  `json:"signature,omitempty"`
	SignedData []byte                  `json:"signed_data,omitempty"`
	Message    string                  `json:"message,omitempty"`
}

SignResponse represents the response to a sign request

type SignService

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

SignService orchestrates the signing request lifecycle

func NewSignService

func NewSignService(
	chainRegistry *chain.Registry,
	requestRepo storage.RequestRepository,
	ruleEngine rule.RuleEngine,
	stateMachine *statemachine.StateMachine,
	approvalService *ApprovalService,
	logger *slog.Logger,
) (*SignService, error)

NewSignService creates a new sign service

func (*SignService) CountRequests

func (s *SignService) CountRequests(ctx context.Context, filter storage.RequestFilter) (int, error)

CountRequests counts sign requests matching the filter

func (*SignService) GetRequest

func (s *SignService) GetRequest(ctx context.Context, id types.SignRequestID) (*types.SignRequest, error)

GetRequest retrieves a sign request by ID

func (*SignService) ListRequests

func (s *SignService) ListRequests(ctx context.Context, filter storage.RequestFilter) ([]*types.SignRequest, error)

ListRequests lists sign requests with filter

func (*SignService) PreviewRuleForRequest

func (s *SignService) PreviewRuleForRequest(ctx context.Context, requestID types.SignRequestID, opts *rule.RuleGenerateOptions) (*types.Rule, error)

PreviewRuleForRequest generates a rule preview for a pending request

func (*SignService) ProcessApproval

func (s *SignService) ProcessApproval(ctx context.Context, requestID types.SignRequestID, req *ApprovalRequest) (*ApprovalResponse, error)

ProcessApproval processes a manual approval for a pending request

func (*SignService) SetApprovalGuard

func (s *SignService) SetApprovalGuard(guard *ManualApprovalGuard)

SetApprovalGuard sets the optional guard that pauses sign requests when too many consecutive manual-approval outcomes occur. Call after construction when enabled.

func (*SignService) SetManualApprovalEnabled

func (s *SignService) SetManualApprovalEnabled(enabled bool)

SetManualApprovalEnabled sets whether requests with no whitelist match go to manual approval (true) or are rejected immediately (false). Default is false. Call after construction from config.

func (*SignService) Sign

func (s *SignService) Sign(ctx context.Context, req *SignRequest) (*SignResponse, error)

Sign processes a sign request. Requests are persisted only after basic checks pass (chain adapter + ValidateBasicRequest: format and size). Then signer existence, ValidatePayload, and rules run; failures update the same record to rejected for audit.

func (*SignService) SupportedRuleTypes

func (s *SignService) SupportedRuleTypes() []types.RuleType

SupportedRuleTypes returns the rule types that can be generated

type TemplateService

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

TemplateService manages rule templates and instance creation

func NewTemplateService

func NewTemplateService(
	templateRepo storage.TemplateRepository,
	ruleRepo storage.RuleRepository,
	budgetRepo storage.BudgetRepository,
	logger *slog.Logger,
) (*TemplateService, error)

NewTemplateService creates a new template service

func (*TemplateService) CreateInstance

CreateInstance creates a rule instance from a template with bound variables

func (*TemplateService) RevokeInstance

func (s *TemplateService) RevokeInstance(ctx context.Context, ruleID types.RuleID) error

RevokeInstance disables a rule instance and deletes its budgets

Jump to

Keyboard shortcuts

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