config

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package config loads the user-global config (~/.config/notenv/config.toml, not committed) and merges it with the project contract into an effective configuration. A machine may define several named storages; the storage target is machine-only, and the contract contributes just the namespace.

Index

Constants

View Source
const (
	DefaultBase         = "notenv"
	DefaultStorage      = "default" // name of the storage setup creates first
	ModePass            = "passphrase"
	DefaultCacheTTL     = time.Hour // master-key keyring cache
	DefaultBlobCacheTTL = time.Hour // local ciphertext cache (matches key cache; --refresh forces fresh)
)
View Source
const LocalBindingFile = "notenv.local.toml"

LocalBindingFile is the per-checkout, git-ignored file that binds a project to a named storage and pins its namespace. It lives beside the contract and is never committed.

Variables

This section is empty.

Functions

func CacheScope

func CacheScope(remote, base string) string

CacheScope is the keyring cache key for a storage base. Length-prefixed on the remote so (remote, base) pairs can't alias: a plain "remote:base" join makes ("r","a:b") and ("r:a","b") collide.

func CheckPin added in v0.2.0

func CheckPin(stored Pin, have bool, obsRevision int, obsMasterPub string) (advance bool, err error)

CheckPin compares an observed header (revision, master public key) against the stored pin. It returns advance=true when the pin should move forward (or on first contact), or an actionable error on a rollback or unexpected master-change alarm.

func DeletePin added in v0.5.0

func DeletePin(scope string) error

DeletePin removes the pin for a storage scope (`notenv key forget`, after a deliberate vault reset). Removing an absent pin is a no-op.

func Dir

func Dir() (string, error)

Dir returns the user config directory, honoring XDG_CONFIG_HOME.

func Exists

func Exists() bool

Exists reports whether a user config file is present (the "is this machine set up" check).

func IdentityPath added in v0.2.0

func IdentityPath() (string, error)

IdentityPath returns the default age identity file location. It holds the private key a teammate unlocks their recipient slot with; the NOTENV_IDENTITY environment variable overrides it.

func MachineID added in v0.3.0

func MachineID() (string, error)

MachineID returns this machine's stable identifier, creating it on first use. It names and orders the segments this machine writes, so two machines never produce the same segment. It is random, not secret, and lives in local state.

func NextSeq added in v0.3.0

func NextSeq(scope, namespace string) (int, error)

NextSeq returns the next strictly-increasing sequence number for (scope, namespace) on this machine, persisting the counter. It orders this machine's segments even when a freshly listed remote is briefly stale, so two of its writes never share a sequence number. The read-modify-write is locked, so two concurrent processes on the machine can't read the same counter and collide.

func Path

func Path() (string, error)

func SetDefault added in v0.2.0

func SetDefault(name string) error

SetDefault changes which storage is the default.

func UpsertStorage added in v0.2.0

func UpsertStorage(name string, entry StorageEntry, makeDefault bool) (string, error)

UpsertStorage adds or replaces a named storage and writes the config. The storage becomes the default if it is the first one, if no default is set, or if makeDefault is true. Returns the config path.

func ValidStorageName added in v0.2.0

func ValidStorageName(name string) bool

ValidStorageName reports whether name is usable as a storage name.

func WriteLocalBinding added in v0.2.0

func WriteLocalBinding(dir string, b LocalBinding) (string, error)

WriteLocalBinding records the binding for the project in dir and returns the file path. The caller is responsible for git-ignoring it.

func WritePin added in v0.2.0

func WritePin(scope string, p Pin) error

WritePin records the pin for a storage scope.

Types

type Effective

type Effective struct {
	StorageName  string // the resolved storage name
	Remote       string // rclone remote name
	Base         string // path within the remote
	Versioned    bool   // remote retains versions on overwrite
	Namespace    string
	Mode         string        // crypto mode
	CacheTTL     time.Duration // master-key cache TTL; <= 0 disables caching
	BlobCacheTTL time.Duration // local ciphertext cache TTL; <= 0 disables
}

Effective is the merged result of the selected storage + contract.

func Resolve

func Resolve(u *User, f *contract.File, contractDir, storageName string) (Effective, error)

Resolve selects a storage (storageName empty means auto: default or sole) and combines it with the contract's namespace. Storage target is machine config only; the contract contributes the namespace (it cannot redirect where this machine reads/writes; see contract.Parse).

type LocalBinding added in v0.5.0

type LocalBinding struct {
	Storage   string `toml:"storage"`
	Namespace string `toml:"namespace"`
}

LocalBinding is what a checkout has locally agreed to: which configured storage it uses (empty means "resolve from the machine config") and which namespace it reads. The namespace pin is a security boundary, not a convenience: the committed contract chooses the namespace, so without a local pin a cloned repository could silently point a checkout at any other project's secrets in the bound vault.

func ReadLocalBinding added in v0.2.0

func ReadLocalBinding(dir string) (LocalBinding, error)

ReadLocalBinding returns the project's local binding in dir. A missing file is a zero binding, not an error.

type NamespaceDecision added in v0.5.0

type NamespaceDecision int

NamespaceDecision is CheckNamespacePin's verdict on using a contract's namespace in a checkout.

const (
	// NamespaceOK: the checkout already pinned this namespace; proceed.
	NamespaceOK NamespaceDecision = iota
	// NamespacePin: first use and the namespace is just the directory's name
	// (the obvious default); pin it without ceremony.
	NamespacePin
	// NamespaceConfirm: first use of an explicitly chosen namespace; pinning it
	// is a decision the user should see (confirm interactively, warn in CI).
	NamespaceConfirm
)

func CheckNamespacePin added in v0.5.0

func CheckNamespacePin(b LocalBinding, resolved, derived string) (NamespaceDecision, error)

CheckNamespacePin decides whether a checkout may use the contract's resolved namespace. derived is the namespace the directory name would yield. A pinned checkout whose contract now names a different namespace is refused: the committed contract selects which secrets reach a child process, so changing it underneath an existing checkout is either an attack or a rename the user must explicitly re-accept (`notenv init` re-pins).

type Pin added in v0.2.0

type Pin struct {
	Revision  int    `json:"revision"`
	MasterPub string `json:"master_pub"`
}

Pin is a per-vault rollback anchor: the highest header revision this machine has seen and the master public key it expects. It is not secret (the threat is storage write, not local read), so it lives in a plain local file.

func ReadPin added in v0.2.0

func ReadPin(scope string) (p Pin, have bool, err error)

ReadPin returns the stored pin for a storage scope (have=false if none).

type StorageEntry added in v0.2.0

type StorageEntry struct {
	Remote string `toml:"remote"`
	Base   string `toml:"base"`
	// Versioned: the remote retains old object versions on overwrite
	// (B2 does natively), so skip the ~3s server-side .prev backup copy.
	Versioned bool `toml:"versioned"`
	// CacheTTL bounds local ciphertext-cache lifetime for this storage
	// (Go duration; "0" disables). Default 1h.
	CacheTTL string `toml:"cache_ttl"`
}

StorageEntry is one named storage target.

type User

type User struct {
	Default string                  `toml:"default"`
	Storage map[string]StorageEntry `toml:"storage"`
	Crypto  struct {
		Mode string `toml:"mode"`
		// CacheTTL is how long the master-key cache may hold the key
		// (Go duration string; "0" disables caching). Default: 1h.
		CacheTTL string `toml:"cache_ttl"`
	} `toml:"crypto"`
}

User is the per-machine config. Storage targets are keyed by name so one machine can drive several vaults; Default names the one used when a project has no local binding.

func LoadUser

func LoadUser() (*User, error)

LoadUser reads the user config. A missing file is not an error: it returns a zero-value config (callers surface the "no storage" error later).

func (*User) MasterCacheTTL added in v0.2.0

func (u *User) MasterCacheTTL() (time.Duration, error)

MasterCacheTTL is the master-key cache lifetime (crypto.cache_ttl; default 1h, "0" disables caching).

func (*User) SelectStorage added in v0.2.0

func (u *User) SelectStorage(explicit string) (string, StorageEntry, error)

SelectStorage picks the storage to use, in precedence order: an explicit name (from --storage or a project's local binding) → the configured default → the sole storage when only one exists. It returns the resolved name and entry, or an actionable error.

func (*User) StorageNames added in v0.2.0

func (u *User) StorageNames() []string

StorageNames returns the configured storage names, sorted.

Jump to

Keyboard shortcuts

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