server

package
v0.6.0 Latest Latest
Warning

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

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

Documentation

Overview

Package server provides the HTTP API for the online calibration subsystem. It exposes endpoints for ingesting calibration events, retrieving per-team thresholds, and deleting team data. All protected routes require a Bearer token supplied at construction time.

Package server defines the server-side interfaces and types for the online calibration subsystem. Implementations of these interfaces handle event persistence, profile materialisation, and cross-org signal computation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIServer

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

APIServer is an HTTP server that exposes the calibration API. It wraps an EventStore for persistence and a chi.Router for routing. APIServer implements http.Handler so it can be passed directly to http.ListenAndServe or used in httptest.NewServer.

func NewAPIServer

func NewAPIServer(store EventStore, apiKey string) *APIServer

NewAPIServer constructs and wires an APIServer with the given EventStore and API key. The API key is used by authMiddleware to validate Bearer tokens on all protected routes.

Routes:

GET  /v1/health                  – unauthenticated liveness probe
POST /v1/events/batch            – ingest a batch of calibration events
GET  /v1/calibration/{teamID}    – retrieve per-team thresholds + cross-org signals
DELETE /v1/teams/{teamID}/data   – erase all data for a team (GDPR)

func (*APIServer) ServeHTTP

func (s *APIServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler by delegating to the underlying chi router.

type EventStore

type EventStore interface {
	// AppendEvents stores a batch of events for the given team. Events are
	// appended in the order provided; the store must not reorder them.
	// Returns an error if any event in the batch cannot be persisted — in that
	// case the implementation should treat the batch atomically (all-or-nothing)
	// where the underlying storage supports it.
	AppendEvents(ctx context.Context, teamID string, events []calibration.Event) error

	// GetTeamProfile returns the materialised calibration profile for each of
	// the requested ruleIDs belonging to teamID. Rules that have no profile yet
	// are omitted from the result slice rather than returned as zero values.
	GetTeamProfile(ctx context.Context, teamID string, ruleIDs []string) ([]calibration.RuleProfile, error)

	// GetGlobalStats returns anonymised cross-org calibration signals for each
	// of the requested ruleIDs. The returned map is keyed by rule ID. Rules
	// that have no cross-org data are omitted from the map.
	GetGlobalStats(ctx context.Context, ruleIDs []string) (map[string]calibration.CrossOrgSignal, error)

	// UpdateProfileFromFeedback incrementally updates the materialised
	// RuleProfile for the rule identified in fb.RuleID, belonging to teamID.
	// Implementations should apply the feedback without requiring a full replay
	// of all events, enabling low-latency profile updates on the hot path.
	UpdateProfileFromFeedback(ctx context.Context, teamID string, fb calibration.FeedbackPayload) error

	// DeleteTeamData removes all events and materialised profiles associated
	// with teamID. This method exists to satisfy GDPR right-to-erasure
	// obligations and must purge data completely from the backing store.
	DeleteTeamData(ctx context.Context, teamID string) error

	// Close releases any resources held by the store (connections, file
	// handles, background goroutines, etc.). After Close returns, no other
	// methods may be called.
	Close() error
}

EventStore persists calibration events and materialized profiles.

All methods accept a context so that callers can enforce deadlines and propagate cancellation. Implementations must be safe for concurrent use.

type SQLiteStore

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

SQLiteStore is a file-backed implementation of EventStore using SQLite. It persists calibration events and materialised per-team rule profiles. All public methods are safe for concurrent use; SQLite WAL mode allows concurrent readers alongside a single writer.

func NewSQLiteStore

func NewSQLiteStore(path string) (*SQLiteStore, error)

NewSQLiteStore opens (or creates) a SQLite database at path and runs schema migrations. WAL journal mode and a 5-second busy timeout are enabled so that concurrent writers do not immediately return SQLITE_BUSY errors.

The caller is responsible for calling Close when done.

func (*SQLiteStore) AppendEvents

func (s *SQLiteStore) AppendEvents(ctx context.Context, teamID string, events []calibration.Event) error

AppendEvents stores a batch of calibration events for teamID atomically. All events in the batch are inserted within a single transaction; if any insertion fails the entire batch is rolled back and an error is returned.

func (*SQLiteStore) Close

func (s *SQLiteStore) Close() error

Close releases the underlying database connection. No further method calls may be made on s after Close returns.

func (*SQLiteStore) DeleteTeamData

func (s *SQLiteStore) DeleteTeamData(ctx context.Context, teamID string) error

DeleteTeamData removes all events and materialised profiles associated with teamID. It satisfies GDPR right-to-erasure obligations by purging data from both the events and team_rule_profiles tables.

func (*SQLiteStore) GetGlobalStats

func (s *SQLiteStore) GetGlobalStats(ctx context.Context, ruleIDs []string) (map[string]calibration.CrossOrgSignal, error)

GetGlobalStats returns anonymised cross-org calibration signals for each rule in ruleIDs. This method is a placeholder for a future task; it currently returns nil, nil for all inputs.

func (*SQLiteStore) GetTeamProfile

func (s *SQLiteStore) GetTeamProfile(ctx context.Context, teamID string, ruleIDs []string) ([]calibration.RuleProfile, error)

GetTeamProfile returns the materialised calibration profile for each rule in ruleIDs that has at least one feedback event recorded for teamID. Rules with no profile are omitted from the result slice rather than returned as zero values. Derived fields are recomputed via RuleProfile.Recalculate before the profiles are returned.

Returns nil, nil when ruleIDs is empty.

func (*SQLiteStore) UpdateProfileFromFeedback

func (s *SQLiteStore) UpdateProfileFromFeedback(ctx context.Context, teamID string, fb calibration.FeedbackPayload) error

UpdateProfileFromFeedback applies a single feedback verdict to the materialised team_rule_profiles row for fb.RuleID and teamID. It uses an UPSERT so the first feedback for a rule creates the row and subsequent feedbacks increment the appropriate counter.

Derived fields (NoiseRate, ConfCalibration, SuppressBelow) are NOT stored in the database; they are computed in-memory by RuleProfile.Recalculate when the profile is read back via GetTeamProfile.

Jump to

Keyboard shortcuts

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