Documentation
¶
Index ¶
- Constants
- func ApplyPartial(base *Config, p *Partial)
- func ParseDuration(s string) (time.Duration, error)
- func SystemConfigBypass(systemPath string) (bool, error)
- type APIConfig
- type APIUnixConfig
- type AgentConfig
- type AgentKeySource
- type AgentUnixConfig
- type AgentWindowsConfig
- type Config
- type Enrolment
- type MTLSBYO
- type MTLSConfig
- type OAuthConfig
- type ObservabilityConfig
- type Partial
- type RemoteConfig
- type Rule
- type SyncConfig
- type Target
- type VaultConfig
- type WebConfig
Constants ¶
const ( DefaultKVMount = "kv" DefaultUserPrefix = "users/" // mTLS / cert-auth defaults applied by validate() when auth_method is // "mtls" or "mtls+tpm". DefaultCertMount = "cert" DefaultPKIMount = "pki" DefaultMTLSKeyType = "ec" DefaultMTLSCommonName = "{{.user}}" DefaultReissueBefore = 168 * time.Hour // 7d // DefaultAgentPipe is the Windows named pipe the SSH agent listens on // when agent.windows.pipe is unset. dotvault claims its own pipe rather // than the well-known \\.\pipe\openssh-ssh-agent so it never contends // with the built-in ssh-agent service. DefaultAgentPipe = `\\.\pipe\dotvault-agent` )
Default connectivity values applied by validate(). Exported so the public client facade (client/config.go) can apply the same defaults to a hand-constructed config without re-typing the literals — keeping the two from silently drifting.
Variables ¶
This section is empty.
Functions ¶
func ApplyPartial ¶ added in v0.22.0
ApplyPartial merges a partial configuration document over a base config: rules merge by name (a same-named rule replaces the base rule wholesale, keeping the base's position; new names append in document order), enrolments merge by map key (an entry replaces the base entry wholesale), and a non-empty sync interval overrides. A rule or enrolment is treated as an atomic unit — field-level splicing across layers would be unreadable in practice.
Merging is additive-only: there are no deletion tombstones. Callers recompute base ⊕ overlay from a freshly loaded base on every refresh, so an entry removed from the overlay disappears naturally; removing an entry the base itself defines requires editing the base.
The base is mutated in place. The overlay is not retained or mutated, though map-valued fields (enrolment Settings) are shared rather than deep-copied — both sides treat them as immutable after the merge.
func ParseDuration ¶
ParseDuration extends time.ParseDuration with a standalone "Nd" suffix representing whole days (N × 24h). It is a thin wrapper: anything other than a bare Nd is delegated to the stdlib parser, so "6h", "30m", "1h30m" etc. continue to work as normal.
Accepts:
- bare "Nd" where N is a non-negative integer ("60d" → 1440h, "1d" → 24h)
- anything time.ParseDuration accepts ("6h", "30m", "1h30m", "45s")
Rejects:
- empty string
- negative bare "Nd" (e.g. "-5d"): kept out as a guard-rail for settings like token_ttl where negative values never make sense. Note that stdlib forms like "-5m" are still parseable by time.ParseDuration and pass through unchanged — callers that need a "must be positive" invariant should enforce it at the validation site (e.g. the 10-min floor check for token_ttl)
- mixed forms combining days with other units ("1d12h" is rejected because "d" is not understood by time.ParseDuration; if this ever becomes load-bearing we can extend the parser)
- non-integer days ("1.5d") and unsupported suffixes ("w", "y")
func SystemConfigBypass ¶ added in v0.20.0
SystemConfigBypass reports whether the system-wide configuration permits a command-line --config override to replace it.
The rule is identical on every platform: a --config override is allowed when there is no system-wide configuration at all, or when the system-wide configuration explicitly opts in via `bypass_system_config: true`. A machine carrying a system config that does not set the flag refuses the override, so a managed deployment (Windows Group Policy, or a system config file shipped by configuration management) cannot be sidestepped from the command line.
"System-wide configuration" means the Windows GPO registry policy when present — it wins exactly as LoadSystem treats it — otherwise the YAML file at systemPath. systemPath should be paths.SystemConfigPath().
Returns true when no system-wide config exists; otherwise returns the bypass flag read from whichever source is authoritative. A registry read error, or a system config file that exists but cannot be read or parsed, is surfaced as an error rather than silently allowing the override.
Types ¶
type APIConfig ¶ added in v0.30.0
type APIConfig struct {
Enabled bool `yaml:"enabled"`
Unix APIUnixConfig `yaml:"unix"`
}
APIConfig configures the local API socket: the daemon's web API served over a per-user Unix domain socket in addition to (or instead of) the loopback TCP listener that web.enabled controls.
It exists for the dotvault-to-dotvault token borrow. A workstation forwards its web API to a remote host over an SSH RemoteForward, and processes on that host borrow the live token via vault.token_socket — but the forwarded socket dies with the SSH session, so a long-running process (a tmux job that outlives the connection) loses its only source of tokens. Enabling this makes the long-lived per-user daemon serve the same borrow endpoint from a stable path that no disconnect can take away: the daemon keeps its own token alive (re-borrowing across the forwarded socket when the SSH session returns) and local clients borrow from it instead.
Deliberately separate from web.enabled. The two surfaces have different audiences and different exposure: the TCP listener is a browser UI reachable by every uid on the box, while this socket is owner-only (0600 in a 0700 directory) and carries no SPA. An operator who wants the borrow endpoint on a headless host should not have to stand up a web UI to get it, and enabling it does not widen what web.enabled already exposes.
Unix only for now. Windows has no equivalent surface yet — the analogue would be a named pipe with a protected DACL, mirroring the SSH agent's listener — so enabling this on Windows logs a warning and serves nothing. The nested `unix:` block (rather than a flat `path:`) is what leaves room for a sibling `windows:` block to be added without reshaping the section across YAML, the registry, and .reg.
The inner fields deliberately omit `omitempty` for the same round-trip reason as AgentConfig: an exported config must re-emit cleared optional values so a re-import can blank a previously-set path. The top-level API field keeps `omitempty` so operators who don't use the socket see no empty block in downloads.
type APIUnixConfig ¶ added in v0.30.0
type APIUnixConfig struct {
// Path is the socket path. Empty resolves to the per-user runtime path
// at daemon-start time (see paths.DefaultAPISocket). A leading ~ is
// expanded, as it is for vault.token_socket.
Path string `yaml:"path"`
}
APIUnixConfig holds the Unix-domain-socket transport settings for the local API surface.
type AgentConfig ¶ added in v0.19.0
type AgentConfig struct {
Enabled bool `yaml:"enabled"`
Unix AgentUnixConfig `yaml:"unix"`
Windows AgentWindowsConfig `yaml:"windows"`
Keys []AgentKeySource `yaml:"keys"`
}
AgentConfig configures the SSH agent surface. Disabled by default; when enabled the daemon serves an agent.ExtendedAgent over a Unix domain socket (Linux/macOS) or a named pipe (Windows), backed by the live Vault token.
The inner fields deliberately omit `omitempty` for the same round-trip reason as ObservabilityConfig: an exported config must re-emit cleared optional values so a re-import can blank a previously-set path or pipe. The top-level Agent field keeps `omitempty` so operators who don't use the agent see no empty block in downloads.
type AgentKeySource ¶ added in v0.19.0
type AgentKeySource struct {
// Source selects the engine: "kv" or "vault-ca".
Source string `yaml:"source"`
// PathPrefix (kv) is resolved under kv/data/{user_prefix}{you}/; every
// secret beneath it is treated as an SSH key (public_key/private_key
// fields). Empty means the whole per-user prefix.
PathPrefix string `yaml:"path_prefix,omitempty"`
// Mount, Role, Principals, TTL, EphemeralKey (vault-ca) describe the SSH
// CA secrets engine and the certificate to mint. Principals are Go
// templates evaluated against {vault_username}.
Mount string `yaml:"mount,omitempty"`
Role string `yaml:"role,omitempty"`
Principals []string `yaml:"principals,omitempty"`
TTL string `yaml:"ttl,omitempty"`
EphemeralKey bool `yaml:"ephemeral_key,omitempty"`
}
AgentKeySource is one ordered origin of signing identities: either raw keys discovered under a KV path prefix, or short-lived certificates minted by a Vault SSH CA.
type AgentUnixConfig ¶ added in v0.19.0
type AgentUnixConfig struct {
// Path is the socket path. Empty resolves to the per-user runtime path
// at agent-construction time (see paths.DefaultAgentSocket).
Path string `yaml:"path"`
}
AgentUnixConfig holds the Unix-domain-socket transport settings.
type AgentWindowsConfig ¶ added in v0.19.0
type AgentWindowsConfig struct {
// Pipe is the pipe name. Empty resolves to DefaultAgentPipe.
Pipe string `yaml:"pipe"`
// Putty controls whether a second named pipe following the PuTTY/Pageant
// naming convention (\\.\pipe\pageant.<user>.<hash>) is served alongside
// Pipe, so PuTTY-family clients (PuTTY, WinSCP, FileZilla, …) that speak
// the Pageant protocol over a named pipe find the agent without any
// client-side configuration. A Windows named pipe carries exactly one
// name, so this is an additional parallel listener, not an alias of Pipe.
// Defaults to true; only takes effect when the agent is enabled and only
// on Windows.
//
// A pointer (unlike the surrounding fields) so an unset value defaults to
// true while an explicit `putty: false` stays distinguishable and
// round-trips. `omitempty` is therefore correct here — a nil pointer is
// the default, not a "cleared" value that must be re-emitted, so it does
// not share the round-trip rationale documented on AgentConfig for the
// string fields.
Putty *bool `yaml:"putty,omitempty"`
}
AgentWindowsConfig holds the named-pipe transport settings.
func (AgentWindowsConfig) PuttyEnabled ¶ added in v0.19.0
func (w AgentWindowsConfig) PuttyEnabled() bool
PuttyEnabled reports whether the Pageant-compatible named pipe should be served. An unset value (nil) defaults to true.
type Config ¶
type Config struct {
Vault VaultConfig `yaml:"vault"`
Sync SyncConfig `yaml:"sync"`
Web WebConfig `yaml:"web"`
Observability ObservabilityConfig `yaml:"observability,omitempty"`
Agent AgentConfig `yaml:"agent,omitempty"`
API APIConfig `yaml:"api,omitempty"`
RemoteConfig RemoteConfig `yaml:"remote_config,omitempty"`
Rules []Rule `yaml:"rules"`
Enrolments map[string]Enrolment `yaml:"enrolments"`
// BypassSystemConfig, when set in the system-wide configuration (the
// YAML at paths.SystemConfigPath(), or the Windows Group Policy
// registry), permits this machine to honour a --config command-line
// override instead of the system config. Default false: with a
// system-wide config present and this flag unset, --config is refused.
// The intent is that an admin normally pins the system config but can
// flip this flag to trial a hand-edited config without un-deploying the
// policy. Enforcement lives in cmd/dotvault (resolveConfigSource +
// SystemConfigBypass); the value itself is just data and behaves the
// same on every platform.
BypassSystemConfig bool `yaml:"bypass_system_config"`
// Managed is set by LoadSystem when the config originated from the
// Windows Registry (Group Policy) rather than the YAML file. The
// daemon uses it to emit a one-shot WARN OTel log record after
// observability.Init runs; deliberately not serialised so an
// exported YAML/.reg artefact never carries the flag back in.
Managed bool `yaml:"-"`
}
Config is the top-level system configuration.
func LoadRaw ¶ added in v0.22.0
LoadRaw reads and parses a config file without validating it (the group/world-writable permission warning is still emitted). See LoadSystemRaw for why the parse/validate seam exists.
func LoadSystem ¶
LoadSystem loads configuration using the platform-appropriate source. On Windows, if Group Policy registry keys exist under HKLM\SOFTWARE\Policies\goodtune\dotvault, configuration is loaded from the registry and the file-based config at path is ignored. Only machine-level (HKLM) policy is read; HKCU is intentionally skipped because it is user-writable and cannot be treated as a trusted policy boundary on unmanaged machines. On non-Windows platforms this falls back to Load(path).
When the registry path wins, the returned Config has Managed=true so the caller can emit a deployment-fact notification (today: a WARN-severity OTel log record via observability.LogRegistryConfigManaged) after the OTel logger provider is wired up. Doing so here would either spam stdout on every CLI invocation under GPO or vanish into the no-op logger that exists before observability.Init runs.
func LoadSystemRaw ¶ added in v0.22.0
LoadSystemRaw is LoadSystem without the final validation pass: it resolves the platform-appropriate source (registry vs YAML file, with Managed set exactly as LoadSystem does) and parses it, but leaves validation to the caller. The remote-config overlay needs this seam: a base that declares remote_config may legitimately fail full validation on its own (e.g. zero rules), so the loader parses the base, merges the fetched overlay, then runs Validate on the merged result.
func (*Config) APISocketPath ¶ added in v0.30.0
APISocketPath resolves the local API socket path the daemon should bind, with a leading ~ expanded. It returns "" when no local API socket applies (disabled, or an unsupported platform), so callers can treat "no path" and "not enabled" identically.
func (*Config) TokenBorrowSockets ¶ added in v0.30.0
TokenBorrowSockets returns the ordered list of peer dotvault sockets a client should try when borrowing a Vault token, most-stable first.
The local API socket comes first deliberately. Both sockets speak the same endpoint, but they differ in how long they survive: the local socket is served by the long-lived per-user daemon and outlives any SSH session, while vault.token_socket is typically an SSH RemoteForward that disappears the moment the connection drops. Preferring the local one means a process started inside an SSH session keeps borrowing successfully after that session ends — the whole point of the local socket.
Paths are returned unexpanded; FetchTokenFromSocket expands a leading ~ at fetch time.
This is the borrow direction only. It is NOT the right order for the peer actions (browse / notify / clipboard), which must reach the workstation where a human is looking — posting those to the local daemon would open a browser on the headless host nobody is sitting at. Those keep using vault.token_socket directly.
func (*Config) Validate ¶ added in v0.22.0
Validate validates the configuration and applies defaults in place. It is the exported counterpart of the validation Load/LoadSystem run internally, for callers that assemble a Config from raw parts — the remote-config overlay parses the base via LoadRaw/LoadSystemRaw, merges the fetched Partial, then validates the merged result here.
type Enrolment ¶
type Enrolment struct {
Engine string `yaml:"engine"`
Settings map[string]any `yaml:"settings"`
// HelpText is optional admin-authored markdown, rendered to HTML and
// shown alongside this enrolment in the web UI to explain what the
// engine does for the user before they run it.
HelpText string `yaml:"help_text,omitempty"`
}
Enrolment declares a credential acquisition flow for a Vault KV key.
type MTLSBYO ¶ added in v0.23.0
MTLSBYO points at an existing certificate and key on disk (the bring-your-own seeding path). Both must be set together, or neither.
type MTLSConfig ¶ added in v0.23.0
type MTLSConfig struct {
// BootstrapMethod is the human-credential method used only to mint the
// first certificate ("ldap" or "oidc"). Default "oidc".
BootstrapMethod string `yaml:"bootstrap_method"`
// BootstrapMount overrides the auth mount for the bootstrap login.
// Default: the method name (the same default the bootstrap flow applies).
BootstrapMount string `yaml:"bootstrap_mount"`
// CertMount is the Vault cert auth mount. Default "cert".
CertMount string `yaml:"cert_mount"`
// CertRole is the cert auth role name presented at login. Required.
CertRole string `yaml:"cert_role"`
// PKIMount is the PKI secrets engine used to issue/sign. Default "pki".
PKIMount string `yaml:"pki_mount"`
// PKIRole is the PKI role. Required when issuance is possible (no BYO).
PKIRole string `yaml:"pki_role"`
// KeyType is "ec" (P-256) or "rsa" (2048). Default "ec". The mtls+tpm
// backend supports "ec" only.
KeyType string `yaml:"key_type"`
// CommonName is a Go template (over {{.user}}) for the certificate CN.
// Default "{{.user}}".
CommonName string `yaml:"common_name"`
// TTL is an optional client-side TTL hint passed to issue/sign; the PKI
// role's TTL remains authoritative.
TTL string `yaml:"ttl"`
// ReissueBefore is how long before expiry to rotate the certificate.
// Default 168h (7d).
ReissueBefore string `yaml:"reissue_before"`
ReissueBeforeDur time.Duration `yaml:"-"`
// SealToPCRs binds the TPM unseal to the current boot (PCR) state.
// mtls+tpm only.
SealToPCRs bool `yaml:"seal_to_pcrs"`
// StorageDir holds the credential envelope. Default {cache_dir}/mtls.
StorageDir string `yaml:"storage_dir"`
// BYO supplies an existing certificate, skipping bootstrap.
BYO MTLSBYO `yaml:"byo"`
}
MTLSConfig configures certificate-based Vault authentication (the "mtls" and "mtls+tpm" auth methods). A TLS client certificate authenticates instead of a human credential; LDAP/OIDC is demoted to a one-time bootstrap that mints the first certificate via the Vault PKI engine.
type OAuthConfig ¶
type OAuthConfig struct {
EnginePath string `yaml:"engine_path"`
Provider string `yaml:"provider"`
Scopes []string `yaml:"scopes"`
}
OAuthConfig holds optional OAuth2 settings for a rule.
type ObservabilityConfig ¶
type ObservabilityConfig struct {
Enabled bool `yaml:"enabled"`
Endpoint string `yaml:"endpoint"`
Protocol string `yaml:"protocol"`
Insecure bool `yaml:"insecure"`
Headers map[string]string `yaml:"headers"`
RawInterval string `yaml:"export_interval"`
ExportInterval time.Duration `yaml:"-"`
}
ObservabilityConfig configures the OpenTelemetry metric and log exporters. A single block drives both signals against the same collector — Endpoint / Protocol / Insecure / Headers are shared. Disabled by default — set Enabled and Endpoint (or the standard OTEL_* env vars) to point the daemon at a local OTel collector.
The inner fields deliberately do NOT carry `omitempty`. The project's YAML/regfile round-trip contract (see internal/regfile/yaml.go) emits empty optional fields explicitly so a re-import can clear previously-set values; omitempty here would let a cleared endpoint or protocol silently persist its previous value across an export → re-import cycle. The top-level Observability field on Config keeps `omitempty` so operators who don't use observability at all don't see a noisy empty block in their downloads.
Headers (which may hold OTLP bearer tokens) are emitted verbatim on export. dotvault treats config conversion as lossless in every direction — YAML <-> in-memory <-> .reg/registry — so no serialiser strips them. The trade-off is deliberate: an exported config artefact (the web download endpoint, a reg-export, a YAML round-trip) carries the live header values. Operators who want to keep tokens out of checked-in config should set them via OTEL_EXPORTER_OTLP_HEADERS in the per-user EnvironmentFile and leave Headers empty; the SDK falls through to those env vars when the field is unset.
type Partial ¶ added in v0.22.0
type Partial struct {
Sync *SyncConfig `yaml:"sync,omitempty"`
Rules []Rule `yaml:"rules,omitempty"`
Enrolments map[string]Enrolment `yaml:"enrolments,omitempty"`
}
Partial is the restricted configuration document a remote configuration service delivers: the dynamic sections only. It is both the client-side wire format (fetched and merged over the local base via ApplyPartial) and the service-side layer format (global / os / group / user layers are Partials composed with MergePartial).
func MergePartial ¶ added in v0.22.0
MergePartial folds src onto dst with the same semantics as ApplyPartial and returns dst (allocating it when nil, so layer composition can fold from a nil accumulator). The dotvault-config service composes its layer documents with this; keeping it beside ApplyPartial guarantees the service composes exactly the way clients merge.
func ParsePartial ¶ added in v0.22.0
ParsePartial parses a partial configuration document, enforcing the wire contract: static sections are a hard error; unknown sections are ignored with a warning (forward compatibility — a newer server may serve sections an older daemon doesn't know about). Section matching is case-aware: yaml.v3 decodes keys case-sensitively, so a mis-cased known section ("Rules:") would be silently dropped by the typed decode — that is a hard error naming the correct spelling, and the static-section ban matches case-insensitively so "Vault:" can't slip past as merely unknown. The result is NOT validated; callers either run (*Partial).Validate (the service, at layer write/serve time) or merge into a Config and validate the merged result (the client).
type RemoteConfig ¶ added in v0.22.0
type RemoteConfig struct {
// URL is the remote configuration endpoint (e.g.
// https://dotvault-config.example.com/v1/config). Empty disables the
// overlay entirely. https is required unless the host is loopback /
// localhost (local development).
URL string `yaml:"url"`
// RawRefreshInterval is how often a running daemon re-fetches the
// document, as a duration string ("Nd" day shorthand accepted). Empty
// defaults to the sync interval. Floor 1m. The parsed RefreshInterval
// is populated only when URL is set — an inactive overlay never
// influences the daemon's refresh cadence.
RawRefreshInterval string `yaml:"refresh_interval"`
RefreshInterval time.Duration `yaml:"-"`
// CACert optionally pins the CA bundle used to verify the remote
// service's TLS certificate. There is deliberately no skip-verify
// option: configuration is not secret, but TLS integrity is the only
// guarantee the client has that it is talking to the real service.
CACert string `yaml:"ca_cert"`
// Headers are extra dimension headers sent with every fetch (e.g.
// X-Dotvault-Env: production). They cannot override the built-in
// X-Dotvault-* identity headers.
Headers map[string]string `yaml:"headers"`
}
RemoteConfig configures the optional remote configuration overlay. When URL is set, the daemon (and the one-shot sync/status/enrol commands) fetch a partial configuration document — dynamic sections only: rules, enrolments, sync — from the remote service and merge it over the locally loaded base before validation. The section itself is local-only: ParsePartial rejects it inside a remote document, so a remote service can never re-point where configuration comes from.
The inner fields deliberately do NOT carry `omitempty`, matching the round-trip contract documented on ObservabilityConfig: an exported config must re-emit cleared optional values so a re-import can blank them. The top-level RemoteConfig field on Config keeps `omitempty` so configs that don't use the overlay see no empty block in downloads.
func (*RemoteConfig) Validate ¶ added in v0.22.0
func (r *RemoteConfig) Validate() error
Validate validates the section in place — an exported wrapper over the internal check so the config loader can enforce the trust-boundary rules (https-unless-loopback, no userinfo, header hygiene) *before* any network I/O, ahead of full-config validation. Idempotent: derived fields are recomputed from scratch on every call.
type Rule ¶
type Rule struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
VaultKey string `yaml:"vault_key"`
OAuth *OAuthConfig `yaml:"oauth"`
Target Target `yaml:"target"`
}
Rule defines a single sync rule.
type SyncConfig ¶
SyncConfig holds sync settings.
type Target ¶
type Target struct {
Path string `yaml:"path"`
Format string `yaml:"format"`
Template string `yaml:"template"`
Merge string `yaml:"merge"`
}
Target defines where and how a secret is written.
type VaultConfig ¶
type VaultConfig struct {
Address string `yaml:"address"`
CACert string `yaml:"ca_cert"`
TLSSkipVerify bool `yaml:"tls_skip_verify"`
KVMount string `yaml:"kv_mount"`
UserPrefix string `yaml:"user_prefix"`
AuthMethod string `yaml:"auth_method"`
AuthRole string `yaml:"auth_role"`
AuthMount string `yaml:"auth_mount"`
// OIDCCallbackPort is the fixed local TCP port the "oidc"/"oidc+tpm" CLI
// flow (dotvault login, and the mtls bootstrap sub-login) binds for the
// OAuth redirect_uri, so operators can register one predictable
// http://127.0.0.1:<port>/oidc/callback URI with both the Vault auth
// role's allowed_redirect_uris and the identity provider, instead of
// depending on RFC 8252 loopback (port-agnostic) redirect matching that
// not every IdP implements. Zero (the default) resolves to 8250, the
// same default the `vault` CLI itself uses, so a role/IdP already
// configured for `vault login -method=oidc` typically works for
// dotvault without any change. If the configured (or default) port is
// already in use, dotvault falls back to an OS-assigned random port and
// logs why. Not consulted by the daemon's web UI flow, which always
// binds web.listen. See docs/authentication/oidc.md.
OIDCCallbackPort int `yaml:"oidc_callback_port"`
// Policies is the least-privilege set of Vault policies the working token
// should carry. When non-empty, dotvault does not run with the token its
// auth role grants directly; instead it exchanges that login token for a
// child token restricted to exactly these policies (Vault enforces that the
// requested set is a subset of the login token's own policies). Empty — the
// default — keeps today's behaviour: the token carries every policy the
// auth role granted, which over-provisions a credential that could leak.
//
// This is a per-deployment concern; dotvault ships no default policy list
// because the right set is specific to each operator's Vault policy layout.
// See docs/configuration/config-reference.md for the staged rollout — a
// future release defaults NoDefaultPolicy to true, and 1.0 will make it
// impossible to run a token carrying the implicit `default` policy.
Policies []string `yaml:"policies"`
// NoDefaultPolicy, when true, strips the implicit `default` policy from the
// working token (it sets no_default_policy on the downscoped child token).
// Default false today for backwards compatibility; a future release flips
// the default to true and 1.0 removes the ability to set it false. Combine
// with Policies to pin a token to exactly the capabilities dotvault needs.
NoDefaultPolicy bool `yaml:"no_default_policy"`
DisableTokenRenewal bool `yaml:"disable_token_renewal"`
// TokenSocket is an optional path to a Unix-domain socket served by a
// peer dotvault daemon's web API. When set, dotvault tries to borrow a
// live Vault token from the peer via `GET http://localhost/api/v1/token`
// over this socket — the equivalent of
// `curl --unix-socket <path> http://localhost/api/v1/token` — before
// falling back to its own authentication. The borrow runs where dotvault
// would otherwise authenticate interactively: on a fresh login (Manager
// .Login, after Authenticate finds no usable cached token) and on the
// lifecycle recovery path after a cached token goes invalid; a healthy
// RenewSelf renewal does not borrow. This is the dotvault-to-dotvault
// token-sharing seam: a machine with no interactive login facility (no
// browser, no TTY) borrows the token from a peer that has one, reached
// over an SSH RemoteForward'd socket. A leading ~ is expanded to the
// user's home. A missing or stale socket is ignored — the normal auth
// flow proceeds — so the field is purely additive and needs no validation.
TokenSocket string `yaml:"token_socket"`
// MTLS configures the cert auth methods. It is consulted only when
// AuthMethod is "mtls" or "mtls+tpm".
MTLS MTLSConfig `yaml:"mtls"`
}
VaultConfig holds Vault connection settings.