secrets

package
v0.1.68 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2026 License: MIT Imports: 7 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 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 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 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.

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
}

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 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.

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 string, dec sops.Decryptor) (ParsedFile, error)

Load decrypts and parses a .ward file into a ParsedFile.

func LoadAll

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

LoadAll loads all files using the given decryptor.

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.

Jump to

Keyboard shortcuts

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