pipeline

package
v0.1.12 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: AGPL-3.0 Imports: 25 Imported by: 0

Documentation

Overview

Package pipeline orchestrates a backup run: WORM check -> enumerate -> per repo (clone --mirror, bundle, checksum, immutable upload) -> signed run-manifest. A repo failure makes the run fail and the manifest records it.

Index

Constants

View Source
const (
	StatusSuccess = "success"
	StatusFailed  = "failed"
	StatusSkipped = "skipped" // nothing to write; see RepoEntry.Reason for which case

	// The reasons a repository is skipped. Both mean "nothing was written and nothing was
	// lost", which is why neither fails the run, but they are different facts and an operator
	// reading a manifest is entitled to know which one applies.
	ReasonResume = "already backed up for this date"
	ReasonEmpty  = "repository has no commits"
)

Status values used in the manifest.

View Source
const ManifestSchema = "gitdr.manifest/v2"

ManifestSchema is the versioned identifier of the run-manifest contract. The manifest schema and the --output json shape are a STABLE PUBLIC CONTRACT: changing them requires a version bump and a note in SPEC.md.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArtifactInfo

type ArtifactInfo struct {
	Kind        string    `json:"kind"` // bundle | meta | sha256
	Key         string    `json:"key"`
	Size        int64     `json:"size"`
	SHA256      string    `json:"sha256"`
	RetainUntil time.Time `json:"retainUntil"`
}

ArtifactInfo is one stored object with its integrity data.

type BackupDeps

type BackupDeps struct {
	Config        *config.Config
	Source        source.Source
	Dest          dest.Destination
	Git           *gitexec.Git
	SigningKey    ed25519.PrivateKey
	EncryptionKey []byte // optional client-side envelope key; nil = off
	ToolVersion   string
	Logger        *slog.Logger
	Now           func() time.Time
	RequireWORM   bool // --require-worm / worm.require: fail closed if not immutable
}

BackupDeps are the inputs to a backup run.

type BackupResult

type BackupResult struct {
	Manifest    *Manifest
	ManifestKey string
}

BackupResult carries the run-manifest and where it was stored. It is returned even when the run fails, so callers can surface the recorded failure.

func Backup

func Backup(ctx context.Context, d BackupDeps) (*BackupResult, error)

Backup runs one backup. It returns a non-nil error on any failure (fail-closed); a BackupResult may still be returned to report what happened.

type DestInfo

type DestInfo struct {
	Type          string `json:"type"`
	Bucket        string `json:"bucket"`
	WormMode      string `json:"wormMode,omitempty"`    // configured retention mode
	WormImmutable bool   `json:"wormImmutable"`         // WORM check confirmed immutable
	WormDetails   string `json:"wormDetails,omitempty"` // observed immutability detail
}

DestInfo identifies where the data went and the immutability observed at write time. wormImmutable records whether the WORM check confirmed the destination immutable, the signed, tamper-evident answer to "was this backup on WORM storage?" (v2).

type Manifest

type Manifest struct {
	Schema      string      `json:"schema"`
	RunID       string      `json:"runId"`
	Tool        ToolInfo    `json:"tool"`
	Source      SourceInfo  `json:"source"`
	Destination DestInfo    `json:"destination"`
	StartedAt   time.Time   `json:"startedAt"`
	FinishedAt  time.Time   `json:"finishedAt"`
	Status      string      `json:"status"` // success | failed
	Repos       []RepoEntry `json:"repos"`
}

Manifest is the signed record of one backup run.

func (*Manifest) Canonical

func (m *Manifest) Canonical() ([]byte, error)

Canonical returns the deterministic bytes that get signed and stored. Struct field order makes encoding/json output stable, so the stored bytes are the signed bytes. Keep the schema map-free, map key order would break verification.

type RepoEntry

type RepoEntry struct {
	Slug   string `json:"slug"`
	Status string `json:"status"` // success | failed | skipped
	Error  string `json:"error,omitempty"`
	// Why a repository was skipped, in plain words. Additive to the manifest schema rather
	// than a new status value, because a consumer switching on `status` would break on an
	// unknown one and there is more than one reason to skip.
	Reason    string         `json:"reason,omitempty"`
	Artifacts []ArtifactInfo `json:"artifacts,omitempty"`
}

RepoEntry is the per-repository outcome.

type RestoreDeps

type RestoreDeps struct {
	Dest          dest.Destination
	Git           *gitexec.Git
	EncryptionKey []byte // optional; must match the backup's key
	// PublicKey is optional. When set, restore locates the signed run-manifest for the
	// requested date, verifies its signature, and checks every artifact it downloads
	// against the checksums the manifest records. The unsigned .sha256 sidecar catches
	// corruption but not tampering; the manifest catches both. Without a key restore
	// keeps the sidecar-only check and says so in RestoreResult.Verification.
	PublicKey ed25519.PublicKey
	Logger    *slog.Logger
}

RestoreDeps are the inputs to a restore.

type RestoreRequest

type RestoreRequest struct {
	Host   string // e.g. github.com
	Owner  string
	Name   string
	Date   string // YYYY-MM-DD
	OutDir string
}

RestoreRequest selects which dated bundle to restore and where to put it.

type RestoreResult

type RestoreResult struct {
	BundleKey string `json:"bundleKey"`
	SHA256    string `json:"sha256"`
	OutDir    string `json:"outDir"`
	Verified  bool   `json:"verified"`
	// Verification says in plain words which integrity checks this restore ran, so a
	// restore that was not checked against the signed manifest announces itself
	// instead of looking identical to one that was. Deliberately kept out of the JSON:
	// the --output json shape is a versioned public contract (SPEC §11), and widening
	// it is its own change, made on purpose, not as a side effect of a read-side fix.
	Verification string `json:"-"`
}

RestoreResult reports what was restored.

func Restore

Restore fetches a bundle, verifies its checksum against the stored sidecar (and, when a public key is configured, against the signed run-manifest), checks the bundle, and clones it into OutDir. Read-only against the destination.

type SourceInfo

type SourceInfo struct {
	Type string `json:"type"`
	Host string `json:"host"`
}

SourceInfo identifies where the data came from.

type ToolInfo

type ToolInfo struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

ToolInfo identifies the producer.

type VerifyDeps

type VerifyDeps struct {
	Dest      dest.Destination
	PublicKey ed25519.PublicKey
	Logger    *slog.Logger
}

VerifyDeps are the inputs to a verify.

type VerifyResult

type VerifyResult struct {
	ManifestKey      string   `json:"manifestKey"`
	SignatureValid   bool     `json:"signatureValid"`
	ArtifactsChecked int      `json:"artifactsChecked"`
	ArtifactsOK      int      `json:"artifactsOk"`
	Failures         []string `json:"failures,omitempty"`
}

VerifyResult reports signature and per-artifact checksum results.

func Verify

func Verify(ctx context.Context, d VerifyDeps, manifestKey string) (*VerifyResult, error)

Verify checks the manifest's Ed25519 signature, then re-reads every referenced artifact and recomputes its SHA-256 against the manifest. Read-only.

Jump to

Keyboard shortcuts

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