core

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package core contains the business logic of the Sphinx control plane: event bus, delta diffing, tamper-evident capture chain, SLA policy engine, governance metrics and the persistence store.

Index

Constants

View Source
const (
	TopicRequests  = "requests"
	TopicDecisions = "decisions"
	TopicPolicies  = "policies"
	TopicCapture   = "capture"
)

Topic names published on the event bus.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned when a row does not exist.

Functions

func CanonicalJSON

func CanonicalJSON(v any) ([]byte, error)

CanonicalJSON serializes a value deterministically: object keys sorted, compact separators (",", ":"), HTML escaping disabled and numbers emitted verbatim from json.Number. This matches the Python canonical form used to compute content hashes (json.dumps(sort_keys=True, separators=(",", ":"), ensure_ascii=False)).

func ContentOf

func ContentOf(eventType, eventName string, sequence int, input, output, metadata map[string]any, status string) map[string]any

ContentOf builds the subset of event fields protected by the content hash.

func GenerateSeed

func GenerateSeed() ([]byte, error)

GenerateSeed returns a random 32-byte Ed25519 seed.

func HashContent

func HashContent(payload map[string]any) (string, error)

HashContent returns the SHA3-256 hex digest of a content payload's canonical JSON form.

func IsStateError

func IsStateError(err error) bool

IsStateError reports whether err is a state-conflict error.

func NewKeyFromSeedB64

func NewKeyFromSeedB64(seedB64 string) (ed25519.PrivateKey, error)

NewKeyFromSeedB64 loads an Ed25519 private key from a base64 32-byte seed.

func SeedToB64

func SeedToB64(seed []byte) string

SeedToB64 base64-encodes a 32-byte seed for persistence.

func SignMessage

func SignMessage(priv ed25519.PrivateKey, prevHash, contentHash string) string

SignMessage signs prev_hash + content_hash with the org key.

func SummarizeDelta

func SummarizeDelta(changes []Change) *string

SummarizeDelta renders up to 5 changes as a short human-readable string.

func VerifyChain

func VerifyChain(events []map[string]any, pub ed25519.PublicKey) (valid bool, checked int, errors []string)

VerifyChain rechecks a set of capture event DTOs: content hashes, prev_hash linkage and Ed25519 signatures. Events are grouped by (agent_id, session_id) and walked in sequence order.

func VerifySignature

func VerifySignature(pub ed25519.PublicKey, prevHash, contentHash, sigB64 string) bool

VerifySignature reports whether the base64 signature is valid for prev_hash + content_hash.

Types

type Bus

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

Bus is an in-process pub/sub hub. Subscribers opt into topics and receive buffered, non-blocking delivery (a full queue drops the event, mirroring the original Python implementation).

func NewBus

func NewBus() *Bus

NewBus creates an empty event bus.

func (*Bus) Publish

func (b *Bus) Publish(topic string, data any)

Publish delivers an event to every subscriber of the topic. Never blocks.

func (*Bus) Subscribe

func (b *Bus) Subscribe(topics ...string) chan Event

Subscribe registers a channel for the given topics and returns it.

func (*Bus) Unsubscribe

func (b *Bus) Unsubscribe(topics []string, ch chan Event)

Unsubscribe removes the channel from the given topics.

type CaptureEventIn

type CaptureEventIn struct {
	EventType     string          `json:"event_type"`
	EventName     string          `json:"event_name"`
	InputPayload  json.RawMessage `json:"input_payload"`
	OutputPayload json.RawMessage `json:"output_payload"`
	Metadata      json.RawMessage `json:"metadata"`
	Status        string          `json:"status"`
}

CaptureEventIn is one event submitted by an SDK; chain fields are server-assigned during ingestion.

type CaptureFilter

type CaptureFilter struct {
	AgentID   *string
	SessionID *string
	EventType *models.CaptureEventType
	Limit     int
	Offset    int
}

CaptureFilter narrows a capture-event listing.

type Change

type Change struct {
	Op   DeltaOp `json:"op"`
	Path string  `json:"path"`
	From any     `json:"from,omitempty"`
	To   any     `json:"to,omitempty"`
}

Change is one path-level diff entry.

func DiffDicts

func DiffDicts(base, modified map[string]any, path string) []Change

DiffDicts recursively diffs two JSON objects into an ordered change list, producing the same shape as the original Python implementation: {"op": "add"|"remove"|"replace", "path": "a.b[2].c", "from"?: ..., "to"?: ...}.

type CreateParams

type CreateParams struct {
	AgentID       string
	Title         string
	ActionPayload json.RawMessage
	Description   string
	SessionID     string
	Framework     string
	RiskLevel     models.RiskLevel
	Priority      int
	PolicyID      *string
	Requester     string
	Metadata      json.RawMessage
}

CreateParams describes a new approval request.

type DecisionFilter

type DecisionFilter struct {
	Source    *models.DecisionSource
	Agreement *bool
	Q         *string
	Limit     int
	Offset    int
}

DecisionFilter narrows a decision-log listing.

type DeltaOp

type DeltaOp string

DeltaOp describes one change between two payloads.

const (
	DeltaAdd     DeltaOp = "add"
	DeltaRemove  DeltaOp = "remove"
	DeltaReplace DeltaOp = "replace"
)

type Event

type Event struct {
	Topic string `json:"topic"`
	Data  any    `json:"data"`
}

Event is a single message delivered to subscribers, serialized as {"topic": ..., "data": ...} over the WebSocket.

type Feedback

type Feedback struct {
	ApprovedWithFeedback int `json:"approved_with_feedback"`
	NegativeOutcomes     int `json:"negative_outcomes"`
}

type Governance

type Governance struct {
	EscalationRate    float64 `json:"escalation_rate"`
	TimeoutRate       float64 `json:"timeout_rate"`
	CorrectionRate    float64 `json:"correction_rate"`
	ReviewerAgreement float64 `json:"reviewer_agreement"`
	ErrorEscapeRate   float64 `json:"error_escape_rate"`
	SLAComplianceRate float64 `json:"sla_compliance_rate"`
}

type Latency

type Latency struct {
	HumanReviews int     `json:"human_reviews"`
	AvgSeconds   float64 `json:"avg_seconds"`
	P50Seconds   float64 `json:"p50_seconds"`
	P95Seconds   float64 `json:"p95_seconds"`
}

type MetricsResult

type MetricsResult struct {
	Window     WindowInfo `json:"window"`
	Totals     TotalsInfo `json:"totals"`
	Governance Governance `json:"governance"`
	Latency    Latency    `json:"latency"`
	Risk       RiskInfo   `json:"risk"`
	Feedback   Feedback   `json:"feedback"`
}

MetricsResult mirrors the /api/metrics response of the original service.

type PolicyEngine

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

PolicyEngine is the background SLA timeout loop. Every interval it finds pending requests past their deadline and applies the policy's on_timeout action (auto-approve / auto-reject / escalate).

func NewPolicyEngine

func NewPolicyEngine(store *Store, interval time.Duration) *PolicyEngine

NewPolicyEngine creates an idle SLA engine.

func (*PolicyEngine) Start

func (e *PolicyEngine) Start()

Start launches the background loop.

func (*PolicyEngine) Stop

func (e *PolicyEngine) Stop()

Stop halts the background loop.

type PolicyPatch

type PolicyPatch struct {
	Description          *string
	RiskLevels           *[]models.RiskLevel
	TimeoutSeconds       *int
	OnTimeout            *models.TimeoutAction
	AutoApproveBelowRisk *bool
	MinReviewers         *int
	Enabled              *bool
}

PolicyPatch carries only the fields a client wants to change (PATCH semantics).

type RequestFilter

type RequestFilter struct {
	Status    *models.RequestStatus
	Framework *string
	AgentID   *string
	Escalated *bool
	Risk      *models.RiskLevel
	Q         *string
	Limit     int
	Offset    int
}

RequestFilter narrows a request listing.

type ResolveParams

type ResolveParams struct {
	Approved        bool
	DecisionPayload json.RawMessage // nil => keep the agent payload
	Source          models.DecisionSource
	ReviewerID      string
	Note            string
	Amend           bool
	RecordDecision  bool
}

ResolveParams controls how a request is decided.

type RiskBucket

type RiskBucket struct {
	Created   int `json:"created"`
	Escalated int `json:"escalated"`
}

type RiskInfo

type RiskInfo map[string]RiskBucket

type StateError

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

StateError is a state-conflict (409) business error.

func (*StateError) Error

func (e *StateError) Error() string

type Store

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

Store persists the control-plane state to SQLite and implements the service layer shared by the REST API, the MCP server and the SLA policy engine.

func New

func New(db *sql.DB, bus *Bus) *Store

New creates a Store backed by the given database.

func (*Store) ApplyTimeout

func (s *Store) ApplyTimeout(ctx context.Context, req *models.ApprovalRequest) (*models.ApprovalRequest, error)

ApplyTimeout fires the SLA timeout for a pending request, degrading per its policy (auto-approve / auto-reject / escalate).

func (*Store) Bus

func (s *Store) Bus() *Bus

Bus exposes the event bus.

func (*Store) CancelRequest

func (s *Store) CancelRequest(ctx context.Context, req *models.ApprovalRequest, agentID string) (*models.ApprovalRequest, error)

CancelRequest cancels a pending request (the agent withdrew it).

func (*Store) Close

func (s *Store) Close() error

Close releases the database.

func (*Store) ComputeMetrics

func (s *Store) ComputeMetrics(ctx context.Context, sinceDays *int) (*MetricsResult, error)

ComputeMetrics derives the governance KPIs from the current state.

func (*Store) CreatePolicy

func (s *Store) CreatePolicy(ctx context.Context, p models.Policy) (*models.Policy, error)

CreatePolicy inserts a policy, rejecting duplicate names.

func (*Store) CreateRequest

func (s *Store) CreateRequest(ctx context.Context, p CreateParams) (*models.ApprovalRequest, error)

CreateRequest opens an approval ticket and returns it. Low-risk requests under an auto-approve policy are resolved instantly (auto_policy source).

func (*Store) DB

func (s *Store) DB() *sql.DB

DB exposes the underlying database handle.

func (*Store) EscalateRequest

func (s *Store) EscalateRequest(ctx context.Context, req *models.ApprovalRequest, reviewerID, note string) (*models.ApprovalRequest, error)

EscalateRequest marks a pending request as escalated.

func (*Store) FindPendingOverdue

func (s *Store) FindPendingOverdue(ctx context.Context, at time.Time) ([]*models.ApprovalRequest, error)

FindPendingOverdue returns pending, non-fired requests past their SLA deadline.

func (*Store) GetRequest

func (s *Store) GetRequest(ctx context.Context, idOrRef string) (*models.ApprovalRequest, error)

GetRequest fetches a request by id or SPH- ref.

func (*Store) IngestCaptureBatch

func (s *Store) IngestCaptureBatch(ctx context.Context, agentID, sessionID string, events []CaptureEventIn) ([]*models.CaptureEvent, error)

IngestCaptureBatch chains and stores one or more events for an agent.

func (*Store) ListCapture

func (s *Store) ListCapture(ctx context.Context, f CaptureFilter) (int, []*models.CaptureEvent, error)

ListCapture returns capture events (newest first).

func (*Store) ListDecisions

func (s *Store) ListDecisions(ctx context.Context, f DecisionFilter) (int, []*models.DecisionLog, error)

ListDecisions returns decision log entries (newest first) plus the total.

func (*Store) ListPolicies

func (s *Store) ListPolicies(ctx context.Context) ([]*models.Policy, error)

ListPolicies returns all policies ordered by creation time.

func (*Store) ListRequests

func (s *Store) ListRequests(ctx context.Context, f RequestFilter) (int, []*models.ApprovalRequest, error)

ListRequests returns matching requests (newest first) plus the total count.

func (*Store) ResolveRequest

func (s *Store) ResolveRequest(ctx context.Context, req *models.ApprovalRequest, params ResolveParams) (*models.ApprovalRequest, error)

ResolveRequest approves or rejects a pending request, recording a decision log entry and publishing a "decided" event.

func (*Store) SubmitFeedback

func (s *Store) SubmitFeedback(ctx context.Context, req *models.ApprovalRequest, outcome models.Outcome, note, agentID string) (*models.ApprovalRequest, error)

SubmitFeedback records the real-world outcome of a decided action.

func (*Store) UpdatePolicy

func (s *Store) UpdatePolicy(ctx context.Context, id string, patch PolicyPatch) (*models.Policy, error)

UpdatePolicy applies a partial update to a policy.

func (*Store) VerifyCapture

func (s *Store) VerifyCapture(ctx context.Context, agentID, sessionID *string) (valid bool, checked, chains int, errs []string, err error)

VerifyCapture recomputes the hash chain and checks every signature.

type TotalsInfo

type TotalsInfo struct {
	Requests  int            `json:"requests"`
	ByStatus  map[string]int `json:"by_status"`
	Escalated int            `json:"escalated"`
	Pending   int            `json:"pending"`
}

type WindowInfo

type WindowInfo struct {
	SinceDays   *int   `json:"since_days"`
	GeneratedAt string `json:"generated_at"`
}

Jump to

Keyboard shortcuts

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