Skip to main content

schema/
deployment.rs

1//! The assembled deployment configuration — a **composition** concern.
2//!
3//! [`Config`] names a source, the sinks, and the indexes to build. It sits
4//! *above* the backend crates: sources and sinks depend only on the
5//! `schema-core` vocabulary (`IndexSchema`, `IndexMapping`, the newtypes), never
6//! on this crate, so a backend can't reach the top-level config. The composition
7//! root (CLI/daemon) translates `Config` into the backend-facing subsets each
8//! side needs (a source spec, the per-sink configs).
9//!
10//! These types were lifted out of `schema-core` for exactly that reason —
11//! keeping the cross-cutting vocabulary at the bottom layer while the
12//! composition lives next to the daemon.
13
14mod conversion;
15mod projection;
16mod sink;
17mod source;
18
19pub use sink::Sink;
20pub use source::Source;
21
22use std::collections::BTreeMap;
23use std::net::SocketAddr;
24
25use schema_core::{FailurePolicy, IndexSchema, common};
26use serde::{Deserialize, Serialize};
27
28/// A whole deployment: where data comes from, where it goes, and what to build.
29///
30/// Secrets are deferred (a literal or an environment reference, see
31/// [`Secret`](schema_core::Secret)), so a serialized `Config` carries only the
32/// literals it was given and resolves the rest at runtime. Debug output redacts
33/// literal secrets either way.
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct Config {
36    pub source: Source,
37    pub sinks: BTreeMap<common::SinkName, Sink>,
38    pub indexes: BTreeMap<common::IndexName, Index>,
39    /// What to do when a sink rejects a document at the item level. The default
40    /// for every index; override per index with [`Index::on_error`].
41    #[serde(default)]
42    pub on_error: FailurePolicy,
43    /// Bind addresses for the operational HTTP surfaces. Read by the binary, not
44    /// the daemon — transport is the binary's concern. Env/flag overrides win;
45    /// see [`ServerConfig`].
46    #[serde(default)]
47    pub server: ServerConfig,
48    /// Literal prefix prepended to every index name flusso owns (indexes,
49    /// aliases, and the `flusso_meta` index), so several deployments can share
50    /// one OpenSearch cluster without colliding. Empty (the default) means no
51    /// prefix. The binary layers the `--index-prefix` flag / `FLUSSO_INDEX_PREFIX`
52    /// env var on top (which win); validated at resolution time with
53    /// [`validate_index_prefix`](schema_core::validate_index_prefix). The
54    /// `flusso-query` client must apply the same prefix at runtime to read back.
55    #[serde(default)]
56    pub prefix: String,
57}
58
59/// Bind addresses for the two operational HTTP surfaces, as configured in
60/// `flusso.toml`'s `[server]` table. Parsed and validated at config-read time
61/// (see `schema_config_toml`'s `BindAddress`), so these are real socket
62/// addresses by the time they reach the binary, which layers `FLUSSO_*` env vars
63/// and CLI flags on top (which win).
64#[derive(Debug, Clone, Default, Serialize, Deserialize)]
65pub struct ServerConfig {
66    /// Public, read-only surface (`/healthz`, `/readyz`, `/status`, `/metrics`).
67    #[serde(default, skip_serializing_if = "Option::is_none")]
68    pub public_address: Option<SocketAddr>,
69    /// Private, Basic-auth control surface (`/indexes`, `/reindex`).
70    #[serde(default, skip_serializing_if = "Option::is_none")]
71    pub private_address: Option<SocketAddr>,
72}
73
74/// One index in a [`Config`], paired with whether it is built on this run.
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Index {
77    pub enabled: bool,
78    pub schema: IndexSchema,
79    /// Per-index override of [`Config::on_error`]. `None` inherits the global
80    /// policy. Lives here (not in [`IndexSchema`]) on purpose: it's operational,
81    /// not part of the document shape, so changing it does not alter the index
82    /// mapping hash or trigger a reindex.
83    #[serde(default, skip_serializing_if = "Option::is_none")]
84    pub on_error: Option<FailurePolicy>,
85}