secrets

package
v0.1.76 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Discover

func Discover(sources []string) ([]string, error)

Discover returns all *.ward files found recursively under each source path. Order within each source is deterministic (lexicographic).

func Exists added in v0.1.76

func Exists(k NodeKind) bool

Exists accepts any present node (leaf or group).

func FileKey added in v0.1.76

func FileKey(filename string) string

FileKey converts a filename to a YAML key: "service-account.json" → "service_account_json"

func FilesMatching added in v0.1.76

func FilesMatching(files []ParsedFile, dotPath string, match func(NodeKind) bool) []string

FilesMatching returns the files whose decoded data satisfies match at dotPath. It centralises the "scan every parsed file for a dot-path" loop so callers only supply the acceptance rule as a predicate over the node kind.

func IsAncestorOf

func IsAncestorOf(candidate, anchor ParsedFile) bool

isAncestorOf returns true if every map-valued key in candidate exists in anchor recursively. Leaf-valued keys in candidate are ignored — an ancestor may declare attributes that the anchor doesn't have. What matters is that the anchor covers all structural branches the candidate declares.

Example: candidate has company.sectors.one.name (leaf) → ancestor of staging.ward Example: candidate has company.production (map) → NOT ancestor of staging.ward IsAncestorOf is the exported version of isAncestorOf.

func IsLeaf added in v0.1.76

func IsLeaf(k NodeKind) bool

IsLeaf accepts only a scalar leaf. Used to locate where a secret is defined.

func LeafKey

func LeafKey(dotPath string) string

LeafKey returns the last segment of a dot-path.

func MapDepth

func MapDepth(data map[string]interface{}) int

MapDepth returns the maximum depth of nested maps in data.

func MarkShadowed

func MarkShadowed(tree map[string]*Node)

MarkShadowed walks the tree and sets Overrides=true on any leaf that would be shadowed by a deeper leaf with the same key name (same as shadow rule in ToFlatEnvEntries). This lets view display shadowed leafs in orange.

func Merge

func Merge(files []ParsedFile, mode config.MergeMode, scopePrefix string) (map[string]*Node, error)

Merge merges a sequence of ParsedFiles in config order (index 0 = first vault, last = last vault). Conflict rule: if two files define the exact same leaf dot-path → conflict (in MergeModeError). If they define different dot-paths they coexist in the tree regardless of depth. When scopePrefix is non-empty, conflicts outside that dot-path prefix are silently overridden.

func OriginalFilename added in v0.1.76

func OriginalFilename(wardFile string) (string, bool)

OriginalFilename returns the original filename from a file-secret .ward path. Returns "", false for plain .ward files (e.g. "main.ward" has no inner extension).

func ToEnvEntries

func ToEnvEntries(tree map[string]*Node) map[string]EnvEntry

ToEnvEntries is like ToEnvVars but preserves origin information.

func ToEnvEntriesFromAnchor

func ToEnvEntriesFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]EnvEntry

ToEnvEntriesFromAnchor is like ToEnvVarsFromAnchor but preserves origin information.

func ToEnvVars

func ToEnvVars(tree map[string]*Node) map[string]string

ToEnvVars converts all leaf nodes of a merged tree into env var pairs with full path. Example: company.sectors.one.staging.database_url → COMPANY_SECTORS_ONE_STAGING_DATABASE_URL

func ToEnvVarsFromAnchor

func ToEnvVarsFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]string

ToEnvVarsFromAnchor returns env vars scoped to the anchor's container level, using relative names (stripping the common ancestor prefix). Example: anchor at company.sectors.one → NAME, STAGING_DATABASE_URL, etc.

func ToFlatEnvEntries

func ToFlatEnvEntries(tree map[string]*Node, preferPrefix string) (map[string]EnvEntry, error)

ToFlatEnvEntries returns only the leaf values as env vars using just the leaf key name (uppercased), without any path prefix. Used by ward envs/exec without --prefixed.

Shadow rule: when two dot-paths share the same leaf key name and one is a descendant of the other (e.g. app.log_level and app.config.log_level), the deeper one wins silently — the shallower is shadowed (dropped). This is NOT a conflict.

Collision: same leaf key name at unrelated dot-paths → EnvConflictError, unless preferPrefix is set — then the entry whose dot-path is under preferPrefix wins, and all other entries for that env key are discarded. Other (non-colliding) vars from the full tree are still included.

func WardFilename added in v0.1.76

func WardFilename(filename string) string

WardFilename appends .ward to the basename: "service-account.json" → "service-account.json.ward"

Types

type Conflict

type Conflict struct {
	Key     string
	Sources []Origin
}

Conflict holds a single key conflict between two or more origins.

type ConflictError

type ConflictError struct {
	Conflicts []Conflict
}

ConflictError is returned when one or more keys are defined in multiple files at the same level.

func (*ConflictError) Error

func (e *ConflictError) Error() string

type EnvConflict

type EnvConflict struct {
	EnvKey        string
	DotPaths      [2]string
	CaseCollision bool // true when keys are the same name but different case
}

EnvConflict holds a single env var name collision between two dot-paths.

type EnvConflictError

type EnvConflictError struct {
	Conflicts []EnvConflict

	// Cmd is the ward command that surfaced the collision ("exec", "envs",
	// "inspect"). It only shapes the resolution examples. The empty value is
	// treated as "exec" so an un-stamped error still reads sensibly.
	Cmd string
}

EnvConflictError is returned when flat env var names collide across different dot-paths.

func (*EnvConflictError) Error

func (e *EnvConflictError) Error() string

type EnvEntry

type EnvEntry struct {
	Value     string
	Origin    Origin
	Overrides bool // true when this value replaced a value from an ancestor file
}

EnvEntry holds an env var's value and the origin node it came from.

type KeyNotFoundError added in v0.1.76

type KeyNotFoundError struct {
	DotPath   string   // the full path the user asked for
	AtPath    string   // the resolved prefix where the walk broke ("" = top level)
	Available []string // keys available at that level, sorted
}

KeyNotFoundError describes a dot-path that could not be resolved in a merged tree, naming where the walk broke and which keys were available there.

func (*KeyNotFoundError) Error added in v0.1.76

func (e *KeyNotFoundError) Error() string

type LineMap

type LineMap map[string]int

LineMap maps dot-path → line number in the source file.

type Node

type Node struct {
	Value     interface{}
	Origin    Origin
	Overrides bool // true when this value replaced a value from a less-specific (ancestor) file
	Children  map[string]*Node
}

Node is either a leaf value with an origin, or a nested map.

func Lookup added in v0.1.76

func Lookup(tree map[string]*Node, dotPath string) (*Node, error)

Lookup navigates tree by dot-path and returns the node found there, or a *KeyNotFoundError that reports the level where the path broke and the keys available at that level.

type NodeKind added in v0.1.76

type NodeKind int

NodeKind classifies what lives at a dot-path within a decrypted YAML tree.

const (
	// KindAbsent means nothing exists at the path.
	KindAbsent NodeKind = iota
	// KindLeaf means the path holds a scalar value.
	KindLeaf
	// KindGroup means the path holds a nested map (has children).
	KindGroup
)

type Origin

type Origin struct {
	File    string
	Line    int
	Snippet string
}

Origin tracks where a leaf value came from.

type ParsedFile

type ParsedFile struct {
	File     string
	Data     map[string]interface{}
	Lines    LineMap  // dot-path → line number
	RawLines []string // source lines for snippet display
}

ParsedFile holds the decoded content of a .ward file before merging.

func FilterByAnchor

func FilterByAnchor(anchor ParsedFile, all []ParsedFile) []ParsedFile

FilterByAnchor returns files that share at least one root key with the anchor, plus the anchor itself, ordered from least specific to most specific. A file is only included as an ancestor if it is strictly less deep than the anchor (its map-branch depth is shallower than the anchor's deepest map branch).

func Load

func Load(path, vaultName, vaultRoot string, dec sops.Decryptor) (ParsedFile, error)

Load decrypts and parses a .ward file into a ParsedFile. vaultName and vaultRoot identify the vault; used to derive the key prefix for file-secrets so they merge at the correct dot-path.

func LoadAll

func LoadAll(paths []string, vaultFor func(path string) (string, string), dec sops.Decryptor) ([]ParsedFile, error)

LoadAll loads all files using the given decryptor. vaultFor maps each file path to its (vaultName, vaultRoot) for file-secret prefix derivation.

func SortBySpecificity

func SortBySpecificity(files []ParsedFile) []ParsedFile

SortBySpecificity sorts files from least specific to most specific. Specificity = total number of dot-paths across all keys (more = more specific).

func TrimToScope

func TrimToScope(ancestor ParsedFile, dirFiles []ParsedFile) ParsedFile

TrimToScope removes from ancestor's data any map branches that do not exist in any of the dir files. This prevents sibling-sector data from leaking into an unrelated dir anchor scope. Example: company.ward has sectors.one and sectors.two — when used as ancestor of a dir anchor for sectors/two, sectors.one should be stripped.

type Tree added in v0.1.76

type Tree struct {
	// contains filtered or unexported fields
}

Tree is a mutable view over a decrypted YAML document. It owns all dot-path traversal so callers never re-implement the "walk maps segment by segment" loop. The zero value is not usable; build one with NewTree.

func NewTree added in v0.1.76

func NewTree(root map[string]interface{}) *Tree

NewTree wraps an existing decoded YAML map. A nil map is treated as empty.

func (*Tree) Children added in v0.1.76

func (t *Tree) Children(dotPath string) []string

Children returns the immediate child key names at dotPath, or nil if the path is absent or is a leaf.

func (*Tree) Kind added in v0.1.76

func (t *Tree) Kind(dotPath string) NodeKind

Kind reports what lives at the dot-path.

func (*Tree) Root added in v0.1.76

func (t *Tree) Root() map[string]interface{}

Root returns the underlying map so it can be re-marshalled.

func (*Tree) Set added in v0.1.76

func (t *Tree) Set(dotPath, value string)

Set writes value at the dot-path, creating intermediate groups as needed.

func (*Tree) Unset added in v0.1.76

func (t *Tree) Unset(dotPath string) UnsetOutcome

Unset removes the leaf at the dot-path, leaving surrounding scaffold groups in place. It never removes a whole branch: a group path yields UnsetGroup.

type UnsetOutcome added in v0.1.76

type UnsetOutcome int

UnsetOutcome is the result of removing a leaf.

const (
	// UnsetAbsent means there was nothing to remove.
	UnsetAbsent UnsetOutcome = iota
	// UnsetGroup means the path is a group; nothing is removed.
	UnsetGroup
	// UnsetDone means a leaf was removed.
	UnsetDone
)

Jump to

Keyboard shortcuts

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