Skip to main content

Config

Struct Config 

Source
#[non_exhaustive]
pub struct Config {
Show 15 fields pub service_did: String, pub service_endpoint: String, pub bind_addr: SocketAddr, pub db_path: PathBuf, pub signing_key_path: PathBuf, pub admin: AdminConfigToml, pub labeler: Option<LabelerConfigToml>, pub operator: Option<OperatorConfigToml>, pub retention: RetentionConfigToml, pub moderation_reasons: Option<BTreeMap<String, ReasonDefToml>>, pub strike_policy: Option<StrikePolicyToml>, pub label_emission: Option<LabelEmissionPolicyToml>, pub policy_automation: Option<PolicyAutomationPolicyToml>, pub pds_admin: Option<PdsAdminConfigToml>, pub xrpc_gateway: Option<XrpcGatewayConfigToml>,
}
Expand description

Top-level Cairn configuration.

Fields grow with features; the struct is non_exhaustive so additions are not a breaking change for downstream crates.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§service_did: String

The service DID Cairn runs as (§5.1).

§service_endpoint: String

Publicly-reachable base URL where this Cairn instance serves HTTP and WebSocket endpoints (e.g., https://labeler.example). Emitted as the serviceEndpoint value in the AtprotoLabeler entry of /.well-known/did.json so consumers can discover where to call.

This is distinct from Self::bind_addr — typical production deployments bind 127.0.0.1:3000 behind a reverse proxy but advertise the public https://labeler.example URL here. Validated at load time as a URL.

§bind_addr: SocketAddr

Where cairn serve binds its HTTP listener. Defaults to DEFAULT_BIND_ADDR (127.0.0.1:3000) if omitted.

§db_path: PathBuf

SQLite database file. Parent directory must exist; the file itself is created on first run by crate::storage::open alongside embedded migrations.

§signing_key_path: PathBuf

Signing key file (§5.1). Mode 0600, owned by the running user, hex-encoded 32-byte secp256k1 private key. Env-var delivery of the key material is explicitly rejected — see crate::signing_key::SIGNING_KEY_ENV_REJECTED.

§admin: AdminConfigToml

Admin-endpoint policy (§F12). Defaults to an empty table, meaning admin.applyLabel accepts any label value ≤128 bytes (matches the existing crate::AdminConfig default).

§labeler: Option<LabelerConfigToml>

Labeler policy (§F1) — the app.bsky.labeler.service record content. Required for cairn publish-service-record; other subcommands don’t consume it, so it’s optional at load time. When absent, publish-service-record surfaces a clear error.

§operator: Option<OperatorConfigToml>

Operator PDS auth surface (§F1 service record publishing). The operator’s identity is the DID that OWNS the labeler account — distinct from moderators who authenticate to Cairn (§5.2) and distinct from Cairn’s own signing key (§5.1).

§retention: RetentionConfigToml

Retention sweep execution policy (§F4 sweep task). Holds schedule + batching knobs only — the cutoff itself (retention_days) is owned by crate::SubscribeConfig so the read-side floor and the sweep cutoff stay tied to a single source of truth. Defaults match §F4 prose: enabled, 04:00 UTC, 1000-row batches.

§moderation_reasons: Option<BTreeMap<String, ReasonDefToml>>

Reason vocabulary for the v1.4 graduated-action moderation model (§F20, #47). TOML projection of the operator’s [moderation_reasons.<identifier>] blocks; resolve to a runtime crate::moderation::reasons::ReasonVocabulary via ReasonVocabulary::from_config.

Three states:

  • None — operator declared no blocks; the resolver loads shipped defaults (eight reasons covering common categories).
  • Some(empty) — operator wrote a bare [moderation_reasons] header with no sub-blocks; rejected at validate time as a probable typo.
  • Some(non_empty) — operator’s vocabulary is the complete set; defaults are NOT merged in.
§strike_policy: Option<StrikePolicyToml>

Strike policy for the v1.4 graduated-action moderation model (§F20, #48). TOML projection of the operator’s [strike_policy] block; resolve to a runtime crate::moderation::policy::StrikePolicy via StrikePolicy::from_config.

Two states:

  • None — operator declared no block; the resolver returns shipped defaults (threshold 3, curve [1, 2], linear decay over 90 days, suspensions freeze decay).
  • Some(_) — partial or full operator declaration. Per-field serde defaults fill any unspecified sub-fields; the resolved values are validated together (curve length convention, strict-ascending curve, positive decay window).
§label_emission: Option<LabelEmissionPolicyToml>

Label-emission policy for the v1.5 graduated-action moderation model (§F21, #58). TOML projection of the operator’s [label_emission] block; resolve to a runtime crate::labels::policy::LabelEmissionPolicy via LabelEmissionPolicy::from_config.

Two states:

  • None — operator declared no block; the resolver returns shipped defaults (emission enabled, reason labels emitted, warnings not emitted, default per-action mappings — !takedown, !hide, !warn).
  • Some(_) — partial or full operator declaration. Per-field serde defaults fill any unspecified sub-fields; the resolved values are validated together (label-value naming conventions, no-collision across action_type overrides, valid action_type keys in override maps).
§policy_automation: Option<PolicyAutomationPolicyToml>

[policy_automation] block (§F22, #71). TOML projection of the operator’s policy-automation surface; resolve to a runtime crate::policy::automation::PolicyAutomationPolicy via PolicyAutomationPolicy::from_config. Cross-validation against [moderation_reasons] (rule reason_codes must exist in the operator’s vocabulary) lives at the Config::validate level, not on the resolver, mirroring the v1.4 / v1.5 per-block-resolver convention.

Two states:

  • None — operator declared no block; the resolver returns shipped defaults (engine enabled, empty rule set — the engine evaluates each recordAction and finds nothing to fire).
  • Some(_) — operator-declared rules. Each rule gets per-field validation (positive threshold, valid action_type, valid mode, duration only on temp_suspension, reason_codes match the [moderation_reasons] vocabulary).
§pds_admin: Option<PdsAdminConfigToml>

[pds_admin] block (§F23, #83, v1.7). TOML projection of the operator’s PDS-admin outbound bridge config; resolves to a runtime crate::pds_admin::PdsAdminPolicy via PdsAdminPolicy::from_config.

Two states:

  • None — operator declared no block; the resolver returns the disabled default (engine off; backend unconfigured; action_map empty).
  • Some(_) — partial or full operator declaration. When enabled = true, exactly one backend subsection must be present (v1.7 supports [pds_admin.ozone] only); the [pds_admin.action_map] table must cover every cairn-mod action type. When enabled = false, subsections may be present (forward-compat) but are not cross-validated.

Cross-block validation against crate::moderation::types::ActionType’s vocabulary lives in Config::validate (every action_map key must parse via ActionType::from_db_str); the resolver in crate::pds_admin::PdsAdminPolicy::from_config handles per-block validation (URL scheme, env-var resolution, allowed-method set, with_lift_after gating).

§xrpc_gateway: Option<XrpcGatewayConfigToml>

[xrpc_gateway] block (§F23 inbound surface, #91, v1.7). Operator-config-gated inbound XRPC listener for proxied Ozone moderation calls + forwarded createReport calls. Resolves to a runtime crate::xrpc_gateway::XrpcGatewayConfig via crate::xrpc_gateway::XrpcGatewayConfig::from_config; absence (the v1.6-shape default) leaves the gateway off and the listener does not mount.

Implementations§

Source§

impl Config

Source

pub fn validate(&self) -> Result<()>

Post-load validation run by Config::load. Exposed so call sites that construct a Config directly (e.g., tests) can share the same rule set.

Source

pub fn load() -> Result<Self>

Load configuration from the default TOML location + env overrides (see Self::load_from for the full precedence rules). The default location is CAIRN_CONFIG env var, or /etc/cairn/cairn.toml if unset.

Source

pub fn load_from(toml_path: Option<&Path>) -> Result<Self>

Load configuration with an explicit TOML path (or None to skip the file layer entirely and rely on env overrides).

Sources, low to high precedence:

  1. Compiled-in defaults (bind_addr if unset, empty admin table).
  2. toml_path if Some and the file exists.
  3. Environment variables prefixed CAIRN_ (e.g. CAIRN_SERVICE_DID).

cairn serve --config <path> routes through this without mutating process env (which is unsafe under Rust 2024 and blocked by the crate’s #![forbid(unsafe_code)]).

Trait Implementations§

Source§

impl Clone for Config

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Config

Source§

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

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

impl<'de> Deserialize<'de> for Config

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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> Paint for T
where T: ?Sized,

Source§

fn fg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the foreground set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like red() and green(), which have the same functionality but are pithier.

§Example

Set foreground color to white using fg():

use yansi::{Paint, Color};

painted.fg(Color::White);

Set foreground color to white using white().

use yansi::Paint;

painted.white();
Source§

fn primary(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Primary].

§Example
println!("{}", value.primary());
Source§

fn fixed(&self, color: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Fixed].

§Example
println!("{}", value.fixed(color));
Source§

fn rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the fg() set to [Color :: Rgb].

§Example
println!("{}", value.rgb(r, g, b));
Source§

fn black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Black].

§Example
println!("{}", value.black());
Source§

fn red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Red].

§Example
println!("{}", value.red());
Source§

fn green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Green].

§Example
println!("{}", value.green());
Source§

fn yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Yellow].

§Example
println!("{}", value.yellow());
Source§

fn blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Blue].

§Example
println!("{}", value.blue());
Source§

fn magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Magenta].

§Example
println!("{}", value.magenta());
Source§

fn cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: Cyan].

§Example
println!("{}", value.cyan());
Source§

fn white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: White].

§Example
println!("{}", value.white());
Source§

fn bright_black(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlack].

§Example
println!("{}", value.bright_black());
Source§

fn bright_red(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightRed].

§Example
println!("{}", value.bright_red());
Source§

fn bright_green(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightGreen].

§Example
println!("{}", value.bright_green());
Source§

fn bright_yellow(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightYellow].

§Example
println!("{}", value.bright_yellow());
Source§

fn bright_blue(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightBlue].

§Example
println!("{}", value.bright_blue());
Source§

fn bright_magenta(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.bright_magenta());
Source§

fn bright_cyan(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightCyan].

§Example
println!("{}", value.bright_cyan());
Source§

fn bright_white(&self) -> Painted<&T>

Returns self with the fg() set to [Color :: BrightWhite].

§Example
println!("{}", value.bright_white());
Source§

fn bg(&self, value: Color) -> Painted<&T>

Returns a styled value derived from self with the background set to value.

This method should be used rarely. Instead, prefer to use color-specific builder methods like on_red() and on_green(), which have the same functionality but are pithier.

§Example

Set background color to red using fg():

use yansi::{Paint, Color};

painted.bg(Color::Red);

Set background color to red using on_red().

use yansi::Paint;

painted.on_red();
Source§

fn on_primary(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Primary].

§Example
println!("{}", value.on_primary());
Source§

fn on_fixed(&self, color: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Fixed].

§Example
println!("{}", value.on_fixed(color));
Source§

fn on_rgb(&self, r: u8, g: u8, b: u8) -> Painted<&T>

Returns self with the bg() set to [Color :: Rgb].

§Example
println!("{}", value.on_rgb(r, g, b));
Source§

fn on_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Black].

§Example
println!("{}", value.on_black());
Source§

fn on_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Red].

§Example
println!("{}", value.on_red());
Source§

fn on_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Green].

§Example
println!("{}", value.on_green());
Source§

fn on_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Yellow].

§Example
println!("{}", value.on_yellow());
Source§

fn on_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Blue].

§Example
println!("{}", value.on_blue());
Source§

fn on_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Magenta].

§Example
println!("{}", value.on_magenta());
Source§

fn on_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: Cyan].

§Example
println!("{}", value.on_cyan());
Source§

fn on_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: White].

§Example
println!("{}", value.on_white());
Source§

fn on_bright_black(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlack].

§Example
println!("{}", value.on_bright_black());
Source§

fn on_bright_red(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightRed].

§Example
println!("{}", value.on_bright_red());
Source§

fn on_bright_green(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightGreen].

§Example
println!("{}", value.on_bright_green());
Source§

fn on_bright_yellow(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightYellow].

§Example
println!("{}", value.on_bright_yellow());
Source§

fn on_bright_blue(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightBlue].

§Example
println!("{}", value.on_bright_blue());
Source§

fn on_bright_magenta(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightMagenta].

§Example
println!("{}", value.on_bright_magenta());
Source§

fn on_bright_cyan(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightCyan].

§Example
println!("{}", value.on_bright_cyan());
Source§

fn on_bright_white(&self) -> Painted<&T>

Returns self with the bg() set to [Color :: BrightWhite].

§Example
println!("{}", value.on_bright_white());
Source§

fn attr(&self, value: Attribute) -> Painted<&T>

Enables the styling Attribute value.

This method should be used rarely. Instead, prefer to use attribute-specific builder methods like bold() and underline(), which have the same functionality but are pithier.

§Example

Make text bold using attr():

use yansi::{Paint, Attribute};

painted.attr(Attribute::Bold);

Make text bold using using bold().

use yansi::Paint;

painted.bold();
Source§

fn bold(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Bold].

§Example
println!("{}", value.bold());
Source§

fn dim(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Dim].

§Example
println!("{}", value.dim());
Source§

fn italic(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Italic].

§Example
println!("{}", value.italic());
Source§

fn underline(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Underline].

§Example
println!("{}", value.underline());

Returns self with the attr() set to [Attribute :: Blink].

§Example
println!("{}", value.blink());

Returns self with the attr() set to [Attribute :: RapidBlink].

§Example
println!("{}", value.rapid_blink());
Source§

fn invert(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Invert].

§Example
println!("{}", value.invert());
Source§

fn conceal(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Conceal].

§Example
println!("{}", value.conceal());
Source§

fn strike(&self) -> Painted<&T>

Returns self with the attr() set to [Attribute :: Strike].

§Example
println!("{}", value.strike());
Source§

fn quirk(&self, value: Quirk) -> Painted<&T>

Enables the yansi Quirk value.

This method should be used rarely. Instead, prefer to use quirk-specific builder methods like mask() and wrap(), which have the same functionality but are pithier.

§Example

Enable wrapping using .quirk():

use yansi::{Paint, Quirk};

painted.quirk(Quirk::Wrap);

Enable wrapping using wrap().

use yansi::Paint;

painted.wrap();
Source§

fn mask(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Mask].

§Example
println!("{}", value.mask());
Source§

fn wrap(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Wrap].

§Example
println!("{}", value.wrap());
Source§

fn linger(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Linger].

§Example
println!("{}", value.linger());
Source§

fn clear(&self) -> Painted<&T>

👎Deprecated since 1.0.1:

renamed to resetting() due to conflicts with Vec::clear(). The clear() method will be removed in a future release.

Returns self with the quirk() set to [Quirk :: Clear].

§Example
println!("{}", value.clear());
Source§

fn resetting(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Resetting].

§Example
println!("{}", value.resetting());
Source§

fn bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: Bright].

§Example
println!("{}", value.bright());
Source§

fn on_bright(&self) -> Painted<&T>

Returns self with the quirk() set to [Quirk :: OnBright].

§Example
println!("{}", value.on_bright());
Source§

fn whenever(&self, value: Condition) -> Painted<&T>

Conditionally enable styling based on whether the Condition value applies. Replaces any previous condition.

See the crate level docs for more details.

§Example

Enable styling painted only when both stdout and stderr are TTYs:

use yansi::{Paint, Condition};

painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
Source§

fn new(self) -> Painted<Self>
where Self: Sized,

Create a new Painted with a default Style. Read more
Source§

fn paint<S>(&self, style: S) -> Painted<&Self>
where S: Into<Style>,

Apply a style wholesale to self. Any previous style is replaced. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

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