backup

package
v0.1.7 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package backup snapshots and restores the bridge's state directory.

A snapshot bundles every file an operator would otherwise have to re-pair / re-scan to recover after corruption: the manifest SQLite database (`bridge.db`), the token store (`tokens.json`), the TLS material (`server.crt` + `server.key`), and the live config (`bridge.yaml`). The snapshot also writes a small `manifest.json` describing the bridge version and protocol version that produced it — Restore refuses incompatible snapshots so a future schema change doesn't get silently rolled back into.

Snapshots are written to `<dataDir>/backups/<timestamp>/`. The directory and files are permissioned 0700 / 0600 because the bundle contains the TLS private key and token hashes — anyone with read access could impersonate the bridge or forge an authenticated request. Operators are warned about this on every backup.

The manifest copy uses SQLite's `VACUUM INTO`, which produces a clean, atomic copy of a WAL-mode database without locking out the running bridge. Restoring the manifest db while the bridge is running is unsafe (the WAL would be inconsistent with the new main file), so `bridge restore` warns + requires `--yes`.

Index

Constants

View Source
const BackupsDirName = "backups"

BackupsDirName is the dir under `dataDir` that holds snapshots.

View Source
const ManifestDBFileName = "bridge.db"

ManifestDBFileName is the on-disk basename for the SQLite manifest inside a backup directory. Three duplicates flagged by go:S1192; extracted so a future rename only happens once across Capture, captured-list emission, and Restore.

View Source
const ManifestFile = "manifest.json"

ManifestFile is the metadata file written into every snapshot dir.

View Source
const SchemaVersion = 1

Snapshot schema version. Bump on incompatible layout changes (e.g. new mandatory file, restructured manifest). Restore refuses snapshots whose `SchemaVersion` doesn't match this constant.

View Source
const SensitivityNotice = "" /* 148-byte string literal not displayed */

SensitivityNotice is the warning Snapshot writes to the operator — exposed as a constant so the CLI, the admin UI, and the docs all show the same wording.

Variables

This section is empty.

Functions

func CleanSnapshotPath

func CleanSnapshotPath(p string) string

CleanSnapshotPath normalizes the operator-supplied snapshot path before use. Exported for the CLI; tests use it too so the canonical shape is one definition.

func EnsureBackupsDir

func EnsureBackupsDir(dataDir string) error

EnsureBackupsDir is a small convenience that creates the backups root with the right permissions if it doesn't yet exist. Useful for the periodic ticker on a fresh `bridge init`.

func EnsureFreshDataDirSibling

func EnsureFreshDataDirSibling(prefix string) (string, error)

EnsureFreshDataDirSibling helps tests construct a writable scratch `dataDir` that isn't the live bridge state. Returns the path on success; callers `defer os.RemoveAll(path)` to clean up.

func List

func List(backupsRoot string) ([]snapshotEntry, error)

List returns the snapshots under `backupsRoot`, newest-first. Directories without a readable manifest are skipped (likely in-progress or corrupt — operator can clean them up by hand).

func LooksLikeSnapshotDir

func LooksLikeSnapshotDir(path string) bool

LooksLikeSnapshotDir returns true when `path` contains a readable, well-formed `manifest.json` (any positive schema version). Used by the Restore CLI's pre-flight validation to surface a clear "this isn't a snapshot directory" error before loading config — the schema-version compatibility check happens later in Restore so that a future-version snapshot produces a precise mismatch error rather than a generic "not recognized" rejection.

func Prune

func Prune(backupsRoot string, keep int) (int, error)

Prune deletes the oldest snapshots in `backupsRoot`, keeping at most `keep` most recent. A `keep` of zero or below is treated as "retain everything"; the caller is responsible for clamping if they want a different floor. Returns the count of dirs deleted.

func Restore

func Restore(snapshotDir string, dst Targets) error

Restore copies files from a snapshot directory back into place. The caller is responsible for stopping the running bridge first — restoring the manifest db while serve is up will leave the WAL inconsistent with the new main file (the running connection is unaware of the swap).

Per-file copies are atomic (temp + rename); if any copy fails the previously-restored files are NOT rolled back, but each individual target stays internally consistent. In practice the whole-dir snapshot was atomic (created in one Snapshot call) so a partial restore is the most useful failure mode anyway.

func Snapshot

func Snapshot(ctx context.Context, src Sources) (snapDir string, retErr error)

Snapshot captures every present file in `src` into a fresh timestamped directory under `<src.DataDir>/backups/`. Returns the absolute path of the created directory.

`ctx` is forwarded to the SQLite VACUUM INTO step so the periodic ticker can cancel an in-flight snapshot on bridge shutdown. Pass `context.Background()` if you don't have a richer scope.

Types

type Manifest

type Manifest struct {
	SchemaVersion   int       `json:"schemaVersion"`
	BridgeVersion   string    `json:"bridgeVersion"`
	ProtocolVersion int       `json:"protocolVersion"`
	CreatedAt       time.Time `json:"createdAt"`
	Files           []string  `json:"files"`
}

Manifest is the metadata file written alongside each snapshot. It records what produced the snapshot and which files are inside — the file list lets Restore copy back exactly what was captured without over-restoring (e.g. don't try to restore `server.crt` from a snapshot that didn't include one).

type Sources

type Sources struct {
	DataDir    string // required — where `<dataDir>/backups/<stamp>/` is created
	ManifestDB string // typically `<dataDir>/bridge.db`
	TokensJSON string // typically `<dataDir>/tokens.json`
	ServerCert string // typically `<dataDir>/server.crt`
	ServerKey  string // typically `<dataDir>/server.key`
	BridgeYAML string // path to the bridge config file
}

Sources points at the live files that should be captured.

Empty fields are skipped (with the exception of `DataDir`, which is required because it determines where the snapshot dir lands). Missing-on-disk files are also skipped silently — a freshly `bridge init`'d install hasn't pair'd anyone yet, so `tokens.json` may not exist.

type Targets

type Targets struct {
	ManifestDB string
	TokensJSON string
	ServerCert string
	ServerKey  string
	BridgeYAML string
}

Targets points at where each restored file should land. Mirrors `Sources` field-for-field. Empty fields skip that file (so the caller can choose to exclude e.g. `bridge.yaml` if they want to keep the live config untouched).

Jump to

Keyboard shortcuts

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