Documentation
¶
Overview ¶
Package migrate coordinates on-disk schema migrations for AgentGuard.
Migrations are versioned transitions of persistent state (audit log, checkpoint files, rotated archives). Each migration lives under its own subpackage (pkg/migrate/vNNN_to_vMMM/), implements the Migration interface, and registers itself at init() time via Register().
There are two entry points:
RunStartup(ctx, env): called from main.go before the server binds. Every registered migration whose Detect() returns true runs in registration order. Any error aborts startup — we never proceed past a failed migration, because half-migrated state is worse than not upgrading.
RunCLI(ctx, env, args): backs the `agentguard migrate` subcommand. Supports --dry-run (log intended actions without touching disk), --id=<migration-id> (run a specific migration out of startup order, for operators who need to re-run one explicitly), and a few convenience flags documented in the subcommand help text.
The framework is deliberately stdlib-only: no external deps, no global state that survives Reset(), and every migration receives its paths and logger through the Env struct rather than reading from package-level variables. That keeps migrations testable without touching the real disk.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrMigrationNotFound = errors.New("migration not found in registry")
ErrMigrationNotFound is returned by RunCLI when --id names a migration that is not in the registry.
Functions ¶
func Register ¶
func Register(m Migration)
Register adds a Migration to the registry. Typically called from an init() in the migration's subpackage. Duplicate IDs cause a panic — the registry is tiny and duplication indicates a programming error, not something to silently tolerate.
func ResetForTest ¶
func ResetForTest()
ResetForTest clears the migration registry. Production code must never call this — migrations are immutable once registered — but tests that Register() a fake Migration need a way to tear down between runs.
func RunCLI ¶
func RunCLI(ctx context.Context, env Env, opts CLIOptions) error
RunCLI executes the `agentguard migrate` subcommand semantics:
- --list: print the registry and return.
- --id=X: run only migration X (even if Detect=false — operator override).
- default: run every migration whose Detect() is true, like RunStartup does, but honoring --dry-run.
Errors are returned rather than Fatal'd so main.go controls the exit code and the tests can drive the same code path without os.Exit.
func RunStartup ¶
RunStartup runs every registered migration whose Detect() returns true, in registration order. If any migration errors, startup aborts — the caller (main.go) should log the error and exit non-zero.
RunStartup is safe to call when no migrations are registered (a fresh install) or when all migrations report Detect=false (an already-upgraded install). In both cases it returns nil after logging a single summary line.
Types ¶
type CLIOptions ¶
type CLIOptions struct {
DryRun bool
ID string // run only this migration, skip others
List bool // list registered migrations and exit
ResetCheckpoint bool // delete the replay checkpoint before running
AuditLogPath string
CheckpointPath string
BackupDir string
}
CLIOptions is the parsed form of the `agentguard migrate` subcommand flags.
type Env ¶
type Env struct {
// AuditLogPath is the path to the live audit.jsonl file.
AuditLogPath string
// CheckpointPath is the path to the .replay-checkpoint file.
CheckpointPath string
// BackupDir is the directory under which rollback artifacts
// (e.g. audit.jsonl.v040-backup) are written. Empty => same dir as
// AuditLogPath.
BackupDir string
// Logger is where migrations emit progress. nil => stdlib log package.
Logger *log.Logger
// Stdout is where CLI output is written. nil => os.Stdout. Primarily
// used by RunCLI; migrations themselves should log via Logger.
Stdout io.Writer
}
Env carries everything a migration may need from the host process. Paths are passed explicitly rather than via package-level globals so migrations stay testable in isolation.
type Migration ¶
type Migration interface {
// ID is a stable identifier used in logs, metrics, and the CLI flag.
// Convention: "vNNN_to_vMMM", e.g. "v040_to_v041".
ID() string
// FromVersion is the schema version this migration accepts as input.
// Detect() must fail if observed input is anything else.
FromVersion() string
// ToVersion is the schema version this migration produces.
ToVersion() string
// Description is a one-line human-readable summary for CLI help and log
// output. No trailing period, no newlines.
Description() string
// Detect reports whether the migration should run against the current
// on-disk state. Returns (true, nil) if Migrate() should execute,
// (false, nil) if state is already at ToVersion (or otherwise not this
// migration's concern), and (_, err) on read/parse failure. Read-only —
// must not modify disk.
Detect(ctx context.Context, env Env) (bool, error)
// Migrate performs the transition. When dryRun is true it must log the
// intended actions without touching disk. On error the on-disk state
// must be left unchanged — implementations typically stage output in a
// temp file and atomically rename on success.
Migrate(ctx context.Context, env Env, dryRun bool) (Result, error)
// Verify checks post-migration invariants. Called after a successful
// Migrate() and again on startup when resuming after a crash, to ensure
// previous output is still intact. Must be idempotent.
Verify(ctx context.Context, env Env) error
}
Migration is the contract every on-disk migration implements. Implementations live in pkg/migrate/vNNN_to_vMMM/ and register themselves via Register().
func Registered ¶
func Registered() []Migration
Registered returns a copy of the registry. Test-only helper; production code should call RunStartup or RunCLI instead.
type Result ¶
type Result struct {
MigrationID string
From string
To string
DryRun bool
Stats map[string]int64
Notes []string
}
Result is the summary a migration returns. Stats keys are free-form and documented per migration; common keys include "records_migrated", "bytes_written", and "backup_path" (stored as a stat for convenience although it is not a count — operators tend to look for it there).
Directories
¶
| Path | Synopsis |
|---|---|
|
Package v040_to_v041 adds the schema-v2 `_meta` header to a pre-existing v0.4.0 audit log.
|
Package v040_to_v041 adds the schema-v2 `_meta` header to a pre-existing v0.4.0 audit log. |