Skip to main content

Settings

Struct Settings 

Source
pub struct Settings {
    pub env: HashMap<String, String>,
    pub profiles: HashMap<String, Profile>,
    pub mcp: McpSettings,
    pub daemon: DaemonSettings,
    pub gmail: GmailSettings,
    pub drive: DriveSettings,
    pub lease: LeaseSettings,
}
Expand description

Settings loaded from $HOME/.omni-dev/settings.json.

Fields§

§env: HashMap<String, String>

Environment variable overrides — the default bundle, consulted only when no profile is active.

§profiles: HashMap<String, Profile>

Named profiles. Selecting one replaces the base env in the fallback chain (isolated / AWS-faithful); see Settings::resolve_with.

§mcp: McpSettings

MCP server defaults (issue #620); an absent block yields McpSettings::default.

§daemon: DaemonSettings

Daemon tracing defaults; an absent section preserves the built-in filter.

§gmail: GmailSettings

Named Gmail accounts (issue #1500); an absent block yields GmailSettings::default, which is an empty account map.

§drive: DriveSettings

Named Google Drive accounts (issue #1520); an absent block yields DriveSettings::default, which is an empty account map.

§lease: LeaseSettings

Global Drive lease policy (issue #1677); an absent block yields LeaseSettings::default.

Implementations§

Source§

impl Settings

Source

pub fn load() -> Result<Self>

Loads settings from the default location.

Source

pub fn load_or_warn_default() -> Self

Loads settings from the default location, warning and falling back to Settings::default if the file exists but fails to read or parse — the disk boundary every non-Result call site shares (issue #1744). A missing file is not an error and never warns (see Self::load_from_path).

The warning fires once per distinct failure per process, not once per call: a single command loads settings several times (client creation, then each account/lease helper), and repeating an identical warning for every read buried the refusal it explains. A successful load resets this, so a long-lived process warns again if the file breaks again.

Source

pub fn load_mcp() -> McpSettings

Loads just the mcp section, warning and falling back to its defaults when the settings file is absent or unreadable — so the MCP server always boots even with a malformed settings.json (issue #620), same warn-then-default contract as Self::load_or_warn_default (issue #1744).

Source

pub fn load_daemon() -> DaemonSettings

Loads daemon defaults with the shared warn-and-default contract.

Source

pub fn warn_bootstrap_failure(message: &str)

Records a bootstrap settings failure after tracing has been installed. Shares deduplication with later settings reads in the same process.

Source

pub fn load_from_path<P: AsRef<Path>>(path: P) -> Result<Self>

Loads settings from a specific path.

Source

pub fn get_settings_path() -> Result<PathBuf>

Returns the default settings path.

Source

pub fn get_env_var(&self, key: &str) -> Option<String>

Returns an environment variable with fallback to settings, honouring the active profile from OMNI_DEV_PROFILE.

Source

pub fn resolve_with<E: EnvSource>( &self, raw: &E, active: Option<&str>, key: &str, ) -> Option<String>

Isolated / AWS-faithful resolution: raw (the process environment) wins; then the active profile’s env if active is set, else the base env. The base map is not consulted when a profile is active, so a missing key fails loud rather than silently reusing a default credential against the wrong tenant.

This is the pure seam: production wrappers pass &SystemEnv; tests pass a MapEnv and an explicit active, mutating no process-global state.

Source

pub fn resolve_triple_with<E: EnvSource>( &self, raw: &E, active: Option<&str>, key: &str, file_key: &str, command_key: &str, ) -> SecretTriple

Resolves key, file_key and command_key as a triple from one layer, for the secret resolver (crate::utils::secret_env, ADR-0089, ADR-0090): the raw environment’s triple if it sets any member (even to an empty value, which neutralises the lower layers exactly as Settings::resolve_with does); otherwise the active profile’s env triple, or the base env triple when no profile is active. So NAME_FILE in the process env overrides NAME in settings.json, while two members in one layer are left for the resolver to reject.

Source

pub fn env_source(&self) -> SettingsEnvRef<'_>

An EnvSource over these settings with the process environment in front and the active profile read from OMNI_DEV_PROFILE — the borrowed form of SettingsEnv, for the secret resolver.

Source

pub fn resolve_with_source<E: EnvSource>( &self, raw: &E, active: Option<&str>, key: &str, ) -> Option<(String, EnvValueSource)>

Like Settings::resolve_with, but also reports which layer supplied the value: the raw process environment, the active profile’s env, or the base env (issue #1143). Same precedence, same profile isolation.

A EnvValueSource::CliFlag attribution is layered on top by get_env_var_sourced, which knows about flag exports; this resolver only distinguishes what it can see.

Source

pub fn upsert_env_vars(path: &Path, vars: &[(&str, &str)]) -> Result<()>

Merges the given key/value pairs into the base env object of the settings file at path — Settings::upsert_env_vars_in with no profile.

Source

pub fn upsert_env_vars_in( path: &Path, profile: Option<&str>, vars: &[(&str, &str)], ) -> Result<()>

Merges the given key/value pairs into the env object targeted by profile — profiles.<name>.env when Some, the base env when None — creating the file, its parent directory, and any missing intermediate objects as needed. Writes therefore land where Settings::resolve_with will look for them (issue #1116).

A profile absent from the file is created rather than rejected; the CLI validates the active profile before dispatch, so this only affects library callers.

The file is read and written as a generic JSON value, so every other field (other profiles, unknown keys) is preserved verbatim. Because the env maps hold credentials, the write is hardened: parent directory 0700, file 0600 (see [write_settings]).

Source

pub fn ensure_secrets_replaceable( path: &Path, profile: Option<&str>, keys: &[&str], raw: &impl EnvSource, ) -> Result<()>

Fails when any of the registered secrets in keys is fetched through a <NAME>_COMMAND, either in the env object targeted by profile (the check Settings::upsert_env_vars_in applies before writing) or in the process environment raw, which outranks whatever a login would write there and would silently shadow it. Exposed so an interactive login can refuse before it spends a browser flow on a token it would then be unable to use (ADR-0090). A missing file or map passes.

Source

pub fn remove_env_vars(path: &Path, keys: &[&str]) -> Result<bool>

Removes the given keys from the base env object of the settings file at path — Settings::remove_env_vars_in with no profile.

Source

pub fn remove_env_vars_in( path: &Path, profile: Option<&str>, keys: &[&str], ) -> Result<bool>

Removes the given keys from the env object targeted by profile (profiles.<name>.env when Some, the base env when None), leaving all other settings — including the same keys in other env maps — intact.

Returns true if any key was present in the targeted map and removed (the file is rewritten, hardened as in Settings::upsert_env_vars_in), false when the file did not exist, the targeted map was absent, or it contained none of the keys (the file is left untouched).

Source

pub fn validate_profile(&self, name: &str) -> Result<()>

Validates that name is a known profile, returning a hard error that lists the known profiles (sorted) otherwise. Called once at the CLI boundary so a typo never silently falls back to base credentials.

Source

pub fn upsert_gmail_account( path: &Path, account: &str, vars: &[(&str, Value)], ) -> Result<()>

Merges the given key/value pairs into gmail.accounts.<account>, creating the file, its parent directory, and any missing intermediate objects as needed (issue #1500, ADR-0066). Same hardening and unknown-field preservation as Settings::upsert_env_vars_in — no new file-handling code.

vars takes serde_json::Value rather than &str (widened in #1523, PR #1528 review) because GmailAccountSettings has non-string fields (chrome_profile_from_email: bool) — a hard-coded Value::String wrap would write the JSON string "true" into a bool field, and since Settings deserializes as one unit, the next Settings::load() would hard-fail parsing the entire file. Callers writing a string field pass serde_json::Value::String(...) explicitly.

Source

pub fn remove_gmail_account(path: &Path, account: &str) -> Result<bool>

Removes gmail.accounts.<account> entirely — an account is coherent as a unit, unlike the key-by-key removal Settings::remove_env_vars_in does. Also clears gmail.default_account if it named the removed account, so resolution (src/gmail/account.rs::resolve_default_account) falls back to the sole-remaining-account rule instead of hard-erroring on a dangling pointer (issue #1529). Returns true if the account was present and removed, false when the file, gmail, gmail.accounts, or the named account did not exist (the file is left untouched in that case).

Source

pub fn set_gmail_default_account( path: &Path, account: Option<&str>, ) -> Result<()>

Sets (Some) or clears (None) gmail.default_account. Always writes, mirroring Settings::upsert_env_vars_in’s unconditional-write semantics rather than Settings::remove_env_vars_in’s changed-only one, since this is fundamentally an upsert of a single scalar rather than a set of keys.

Source

pub fn upsert_drive_account( path: &Path, account: &str, vars: &[(&str, Value)], ) -> Result<()>

Merges the given key/value pairs into drive.accounts.<account>, creating the file, its parent directory, and any missing intermediate objects as needed (issue #1522, ADR-0069). Same hardening and unknown-field preservation as Settings::upsert_env_vars_in — no new file-handling code.

vars takes serde_json::Value, not &str — see Settings::upsert_gmail_account’s doc comment for why (this helper’s twin, and the write path the PR #1528 review comment flagged the bug against).

Source

pub fn remove_drive_account(path: &Path, account: &str) -> Result<bool>

Removes drive.accounts.<account> entirely — an account is coherent as a unit, exactly like Settings::remove_gmail_account. Also clears drive.default_account if it named the removed account, for the same dangling-pointer reason (issue #1529) — Drive has no legacy-credential fallback to soften a stale default the way Gmail’s resolution table can (ADR-0069 §3), so the failure would be total. Returns true if the account was present and removed, false when the file, drive, drive.accounts, or the named account did not exist (the file is left untouched in that case).

Source

pub fn set_drive_default_account( path: &Path, account: Option<&str>, ) -> Result<()>

Sets (Some) or clears (None) drive.default_account. Always writes, mirroring Settings::set_gmail_default_account’s unconditional-write semantics — fundamentally an upsert of a single scalar rather than a set of keys.

Trait Implementations§

Source§

impl Debug for Settings

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Settings

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Settings

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more