engine

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: 0BSD Imports: 17 Imported by: 0

Documentation

Overview

Package engine ties the store, crypto, leaf, and merge packages together into the operations the CLI and git hooks invoke: loading and decrypting the store, reading leaf files, running the 3-way merge against the base snapshot, and applying the results in either direction.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FetchGitHubKeys

func FetchGitHubKeys(username string) ([]string, error)

FetchGitHubKeys downloads a user's public SSH keys from https://github.com/<user>.keys and returns the ssh-ed25519 / ssh-rsa lines, suitable as age recipients. Network failures are returned so the caller can decide whether to proceed.

Types

type Cell

type Cell struct {
	Path string
	Env  string
	Tier store.Tier
}

Cell identifies one (path, env, tier) location.

func ParseCellArgs

func ParseCellArgs(path, env, tier string) (Cell, error)

ParseCellArgs validates and builds a Cell from path/env/tier CLI arguments.

func (Cell) String

func (c Cell) String() string

type CellResult

type CellResult struct {
	Cell    Cell
	Results []merge.Result
}

CellResult pairs a cell with its per-key merge results.

type Check

type Check struct {
	Name string
	OK   bool
	Info string
}

Check is a single doctor finding.

type Direction

type Direction int

Direction selects how non-conflicting results are applied.

const (
	// StoreToLeaf regenerates leaf files from the store (post-checkout/merge).
	StoreToLeaf Direction = iota
	// LeafToStore captures leaf edits into the store (pre-commit).
	LeafToStore
	// Both applies incoming updates to leaves and local edits to the store.
	Both
)

type Engine

type Engine struct {
	Root   string
	GitDir string
	Store  *store.Store
	// contains filtered or unexported fields
}

Engine holds resolved paths and the decrypted data key for a repo.

func Open

func Open(sshKeyPath string) (*Engine, error)

Open locates the repo, loads the store (creating an empty one if absent), and recovers the data key. sshKeyPath may be empty to use default ssh key discovery.

func (*Engine) AddRecipientKeys added in v0.0.3

func (e *Engine) AddRecipientKeys(name string, newKeys []string) error

AddRecipientKeys adds one or more keys under a recipient name (creating the entry if needed), de-duplicates, and rewraps. Keys may be ssh/age lines or gpg fingerprints.

func (*Engine) Apply

func (e *Engine) Apply(plan []CellResult, dir Direction) (conflicts int, err error)

Apply resolves the plan in the requested direction. It returns the number of conflicts encountered; when conflicts>0 no side effects that would lose data are performed for those cells, and the caller decides whether to block.

func (*Engine) CellPlaintext

func (e *Engine) CellPlaintext(c Cell) (map[string]string, error)

CellPlaintext returns the decrypted values for a single cell.

func (*Engine) DEK

func (e *Engine) DEK() []byte

DEK exposes the data key for operations that need to (re)wrap it.

func (*Engine) DecryptStore

func (e *Engine) DecryptStore() (store.Plaintext, error)

DecryptStore returns the fully decrypted plaintext view of the store.

func (*Engine) Doctor

func (e *Engine) Doctor() []Check

Doctor runs health checks over the store, hooks, recipients, store-entry well-formedness, and .example coverage.

func (*Engine) HooksDir

func (e *Engine) HooksDir() (string, error)

HooksDir returns git's effective hooks directory for this repo, honoring core.hooksPath.

func (*Engine) Ignore added in v0.0.4

func (e *Engine) Ignore(c Cell, key string) error

Ignore marks key as ward-ignored for the cell (path, env, tier): a marker is recorded in the store (no value), the key is evicted from the store and base snapshot, and the leaf is regenerated so the variable moves into the trailing ignored block (preserved, never managed again). Ignoring is per-env.

func (*Engine) IgnoredKeys added in v0.0.4

func (e *Engine) IgnoredKeys(c Cell) []string

IgnoredKeys returns the sorted ignored names for the cell.

func (*Engine) Init

func (e *Engine) Init(recipients map[string][]string, passphrase string) error

Init creates a fresh store with a new data key wrapped to the given recipients (name -> keys) and, optionally, the shared passphrase. It fails if the store already has key material.

func (*Engine) Initialized

func (e *Engine) Initialized() bool

Initialized reports whether the store has any key material.

func (*Engine) InstallHooks

func (e *Engine) InstallHooks() error

InstallHooks writes (or updates) the git hooks that keep leaf files and the store in sync. Each hook simply invokes `ward hook <name>`. Installation is idempotent and preserves any pre-existing non-ward hook body by appending the ward invocation, so it is safe to run from a bun postinstall.

Hooks are written to git's effective hooks directory, honoring core.hooksPath (e.g. husky's .husky), not just .git/hooks.

The hooks never fail the git operation: `ward hook` exits 0 on recoverable problems (missing key, uninitialized store) after printing a warning, except pre-commit which exits non-zero only on an unresolved conflict.

func (*Engine) LoadBase

func (e *Engine) LoadBase() (store.Plaintext, error)

LoadBase reads the plaintext base snapshot, returning an empty one if absent.

func (*Engine) Plan

func (e *Engine) Plan() ([]CellResult, error)

Plan computes merge results for every registered cell by combining the decrypted store, the leaf files on disk, and the base snapshot.

func (*Engine) ReadLeaf

func (e *Engine) ReadLeaf(basepath string, tier store.Tier, env string) (map[string]string, bool, error)

ReadLeaf reads and parses a leaf file, returning nil (not an error) when it does not exist.

func (*Engine) Recipients

func (e *Engine) Recipients() (map[string][]string, bool)

Recipients returns a copy of the current name -> keys map and whether the shared passphrase wrap is present.

func (*Engine) Register

func (e *Engine) Register(rel string) (int, error)

Register scans for leaf files and adds any keys not already in the store, returning the number of keys newly registered. New cells and new keys are added; existing keys are left to the normal sync/merge path.

func (*Engine) RemoveRecipient

func (e *Engine) RemoveRecipient(name string) (bool, error)

RemoveRecipient removes an entire named recipient and rewraps. Returns false if the name was not present.

func (*Engine) ResolveKey

func (e *Engine) ResolveKey(c Cell, key, value string, del bool) error

ResolveKey records a human decision for one conflicting key: it sets both the store and the leaf to value (or deletes the key when del is true), then advances the base for that key. This clears the conflict.

func (*Engine) RewrapDEK

func (e *Engine) RewrapDEK(recipients map[string][]string, passphrase string) error

RewrapDEK re-wraps the current data key to the supplied recipients (name -> keys), replacing the store's key material. Keys are classified into age (ssh/age lines) and gpg (fingerprints) at wrap time. Values are not touched, so this is cheap and produces a small diff. An empty passphrase preserves an existing passphrase wrap (or picks up GITWARD_PASSPHRASE if set).

func (*Engine) SaveBase

func (e *Engine) SaveBase(data store.Plaintext) error

SaveBase writes the plaintext base snapshot into .git/gitward.

func (*Engine) SaveStore

func (e *Engine) SaveStore() error

SaveStore writes the store back to disk with stable, indented JSON.

func (*Engine) ScanLeaves

func (e *Engine) ScanLeaves(rel string) ([]discovered, error)

ScanLeaves walks the repo (starting at rel, or the whole repo when empty) for leaf dotfiles and returns the cells and parsed values found. Directories commonly excluded from secret scanning are skipped.

func (*Engine) SetCellPlaintext

func (e *Engine) SetCellPlaintext(c Cell, vals map[string]string) error

SetCellPlaintext replaces a single cell's values in the store, re-encrypts, writes the store, regenerates the corresponding leaf, and advances the base so the edit is not seen as drift.

func (*Engine) SetDEK

func (e *Engine) SetDEK(dek []byte)

SetDEK installs a freshly generated data key (used by init).

func (*Engine) StageStore

func (e *Engine) StageStore() error

StageStore adds the store file to the git index so pre-commit-captured edits are included in the in-flight commit.

func (*Engine) Unignore added in v0.0.4

func (e *Engine) Unignore(c Cell, key string) error

Unignore clears the ignore marker for the cell key. The variable, if still present in a leaf file, is captured back into the store on the next sync.

func (*Engine) WriteLeaf

func (e *Engine) WriteLeaf(basepath string, tier store.Tier, env string, vals map[string]string) error

WriteLeaf serializes vals (the managed values) to the leaf file. Any ward-ignored variables already present in the on-disk file are preserved verbatim in a trailing block so store->leaf regeneration never drops platform-injected or otherwise unmanaged variables. When both the managed and ignored sets are empty the file is removed so a fully-deleted tier leaves no stale file.

Jump to

Keyboard shortcuts

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