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 ¶
- func FetchGitHubKeys(username string) ([]string, error)
- type Cell
- type CellResult
- type Check
- type Direction
- type Engine
- func (e *Engine) AddRecipientKeys(name string, newKeys []string) error
- func (e *Engine) Apply(plan []CellResult, dir Direction) (conflicts int, err error)
- func (e *Engine) CellPlaintext(c Cell) (map[string]string, error)
- func (e *Engine) DEK() []byte
- func (e *Engine) DecryptStore() (store.Plaintext, error)
- func (e *Engine) Doctor() []Check
- func (e *Engine) HooksDir() (string, error)
- func (e *Engine) Ignore(c Cell, key string) error
- func (e *Engine) IgnoredKeys(c Cell) []string
- func (e *Engine) Init(recipients map[string][]string, passphrase string) error
- func (e *Engine) Initialized() bool
- func (e *Engine) InstallHooks() error
- func (e *Engine) LoadBase() (store.Plaintext, error)
- func (e *Engine) Plan() ([]CellResult, error)
- func (e *Engine) ReadLeaf(basepath string, tier store.Tier, env string) (map[string]string, bool, error)
- func (e *Engine) Recipients() (map[string][]string, bool)
- func (e *Engine) Register(rel string) (int, error)
- func (e *Engine) RemoveRecipient(name string) (bool, error)
- func (e *Engine) ResolveKey(c Cell, key, value string, del bool) error
- func (e *Engine) RewrapDEK(recipients map[string][]string, passphrase string) error
- func (e *Engine) SaveBase(data store.Plaintext) error
- func (e *Engine) SaveStore() error
- func (e *Engine) ScanLeaves(rel string) ([]discovered, error)
- func (e *Engine) SetCellPlaintext(c Cell, vals map[string]string) error
- func (e *Engine) SetDEK(dek []byte)
- func (e *Engine) StageStore() error
- func (e *Engine) Unignore(c Cell, key string) error
- func (e *Engine) WriteLeaf(basepath string, tier store.Tier, env string, vals map[string]string) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FetchGitHubKeys ¶
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 ¶
Cell identifies one (path, env, tier) location.
func ParseCellArgs ¶
ParseCellArgs validates and builds a Cell from path/env/tier CLI arguments.
type CellResult ¶
CellResult pairs a cell with its per-key merge results.
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 ¶
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
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 ¶
CellPlaintext returns the decrypted values for a single cell.
func (*Engine) DecryptStore ¶
DecryptStore returns the fully decrypted plaintext view of the store.
func (*Engine) Doctor ¶
Doctor runs health checks over the store, hooks, recipients, store-entry well-formedness, and .example coverage.
func (*Engine) HooksDir ¶
HooksDir returns git's effective hooks directory for this repo, honoring core.hooksPath.
func (*Engine) Ignore ¶ added in v0.0.4
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
IgnoredKeys returns the sorted ignored names for the cell.
func (*Engine) Init ¶
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 ¶
Initialized reports whether the store has any key material.
func (*Engine) InstallHooks ¶
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 ¶
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 ¶
Recipients returns a copy of the current name -> keys map and whether the shared passphrase wrap is present.
func (*Engine) Register ¶
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 ¶
RemoveRecipient removes an entire named recipient and rewraps. Returns false if the name was not present.
func (*Engine) ResolveKey ¶
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 ¶
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) ScanLeaves ¶
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 ¶
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) StageStore ¶
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
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.