integrity

package
v0.8.4 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package integrity checks the control plane SQLite database for corruption and stages a verified snapshot to replace it.

Index

Constants

View Source
const (
	ModeQuick = "quick"
	ModeFull  = "full"
)

Check modes.

View Source
const (
	EnvCheckInterval = "APP_INTEGRITY_CHECK_INTERVAL"
	EnvFullInterval  = "APP_INTEGRITY_FULL_INTERVAL"
)

Environment variables that tune the checks.

View Source
const PendingFilename = "restore-pending.json"

PendingFilename is the marker the next boot reads to swap in a staged snapshot.

Variables

View Source
var ErrCorrupt = errors.New("database file is corrupt")

ErrCorrupt means SQLite reported the database file as damaged.

View Source
var ErrNoVerifiedBackup = errors.New("no verified control plane snapshot is available")

ErrNoVerifiedBackup means no snapshot passed verification.

Functions

func BootCheck

func BootCheck(ctx context.Context, path string) error

BootCheck runs a quick_check on the database file before the store opens it. A missing file is fine.

func ClearPending

func ClearPending(dataDir string) error

ClearPending cancels a staged restore.

func IntervalsFromEnv

func IntervalsFromEnv(getenv func(string) string) (quick, full time.Duration)

IntervalsFromEnv reads the quick and full check intervals; zero disables the loop.

func LatestVerified

func LatestVerified(ctx context.Context, m BackupLister) (string, error)

LatestVerified re-verifies snapshots newest first and returns the first that passes.

func RunPragma

func RunPragma(ctx context.Context, db Querier, mode string) error

RunPragma runs quick_check or integrity_check and returns an ErrCorrupt wrapped error unless SQLite answers ok.

func Swap

func Swap(ctx context.Context, dataDir, dbFile, src string, now time.Time) (aside string, version int, err error)

Swap replaces the live database with the snapshot at src, keeping the old file beside it. The control plane must not be running.

Types

type Applied

type Applied struct {
	Pending Pending `json:"pending"`
	Aside   string  `json:"aside"`
}

Applied is the result of swapping a staged snapshot in at boot.

func ApplyPending

func ApplyPending(ctx context.Context, dataDir, dbFile string, now time.Time) (*Applied, error)

ApplyPending swaps a staged snapshot in. It runs before the store opens, so no connection holds the file. The marker is removed whether or not the swap succeeds, so a bad snapshot cannot loop every boot.

type BackupLister

type BackupLister interface {
	List() ([]cpbackup.Info, error)
	Verify(ctx context.Context, name string) (cpbackup.VerifyResult, error)
}

BackupLister is the slice of cpbackup.Manager the restore path needs.

type Candidate

type Candidate struct {
	Name       string     `json:"name"`
	SizeBytes  int64      `json:"size_bytes"`
	CreatedAt  time.Time  `json:"created_at"`
	VerifiedAt *time.Time `json:"verified_at,omitempty"`
	Verified   bool       `json:"verified"`
}

Candidate is one snapshot the operator can restore.

func Candidates

func Candidates(m BackupLister) ([]Candidate, error)

Candidates lists snapshots newest first with their last recorded verification.

type Checker

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

Checker runs quick and full integrity checks and remembers the result.

func NewChecker

func NewChecker(db Querier, logger *slog.Logger) *Checker

NewChecker returns a Checker over db. Before the first check it reports healthy.

func (*Checker) Check

func (c *Checker) Check(ctx context.Context, mode string) Status

Check runs one check in the given mode (anything but ModeFull runs the cheap quick_check) and records it.

func (*Checker) Run

func (c *Checker) Run(ctx context.Context, interval, fullEvery time.Duration)

Run checks on every interval until ctx ends, upgrading to a full check once fullEvery has passed since the last one.

func (*Checker) Status

func (c *Checker) Status() Status

Status returns the latest result.

type Pending

type Pending struct {
	Name          string    `json:"name"`
	SHA256        string    `json:"sha256"`
	SchemaVersion int       `json:"schema_version"`
	StagedAt      time.Time `json:"staged_at"`
	StagedBy      string    `json:"staged_by,omitempty"`
}

Pending describes a snapshot staged to replace the database at the next boot.

func ReadPending

func ReadPending(dataDir string) (*Pending, error)

ReadPending returns the staged restore, or nil when none is staged.

func Stage

func Stage(ctx context.Context, dataDir, name, by string, now time.Time) (Pending, error)

Stage verifies the named snapshot and marks it to replace the database at the next boot.

type Querier

type Querier interface {
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}

Querier is the slice of *sql.DB a check needs.

type Service

type Service struct {
	*Checker
	// contains filtered or unexported fields
}

Service ties the checker to the snapshot store and the staged restore marker.

func NewService

func NewService(db Querier, dataDir string, backups BackupLister, logger *slog.Logger) *Service

NewService returns a Service for the database behind db, with snapshots listed by backups under dataDir.

func (*Service) CancelRestore

func (s *Service) CancelRestore() error

CancelRestore removes a staged restore.

func (*Service) Restore

func (s *Service) Restore(ctx context.Context, name, by string) (Pending, error)

Restore stages the named snapshot, or the newest one that verifies when name is empty. It takes effect at the next boot.

func (*Service) View

func (s *Service) View() (View, error)

View returns the current status, staged restore and restorable snapshots.

type Status

type Status struct {
	Healthy    bool      `json:"healthy"`
	Mode       string    `json:"mode"`
	CheckedAt  time.Time `json:"checked_at"`
	Error      string    `json:"error,omitempty"`
	Checks     int64     `json:"checks"`
	Failures   int64     `json:"failures"`
	LastFullAt time.Time `json:"last_full_at"`
}

Status is the outcome of the most recent check.

type View

type View struct {
	Status     Status      `json:"status"`
	Pending    *Pending    `json:"pending,omitempty"`
	Candidates []Candidate `json:"candidates"`
}

View is everything the health page and CLI show about database integrity.

Jump to

Keyboard shortcuts

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