Skip to main content

rivet/config/
destination.rs

1//! Output destination: cloud-bucket / local-path / stdout, with per-cloud auth.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, Default)]
7#[serde(deny_unknown_fields)]
8pub struct DestinationConfig {
9    #[serde(rename = "type")]
10    pub destination_type: DestinationType,
11    pub bucket: Option<String>,
12    pub prefix: Option<String>,
13    pub path: Option<String>,
14    pub region: Option<String>,
15    pub endpoint: Option<String>,
16    pub credentials_file: Option<String>,
17    pub access_key_env: Option<String>,
18    pub secret_key_env: Option<String>,
19    /// Name of an env var holding an AWS STS session token, for use with
20    /// short-lived credentials issued by AWS IAM Identity Center / SSO,
21    /// `aws sts assume-role`, MFA-protected sessions, EKS IAM Roles for
22    /// Service Accounts, etc.  Pair with `access_key_env` + `secret_key_env`.
23    /// See `docs/cloud-auth.md` for the AWS auth-flow matrix.
24    pub session_token_env: Option<String>,
25    pub aws_profile: Option<String>,
26    /// Azure storage account name (the prefix in `<account>.blob.core.windows.net`).
27    /// Plain string — not a secret. Pair with `account_key_env`.
28    /// See `docs/cloud-auth.md` for the Azure auth-flow matrix.
29    pub account_name: Option<String>,
30    /// Name of an env var holding the Azure Storage account key.  Treated as
31    /// a credential and wiped from heap on drop — same SecOps treatment as
32    /// `access_key_env`.  Pair with `account_name`.  Mutually exclusive with
33    /// `sas_token_env`.
34    pub account_key_env: Option<String>,
35    /// Name of an env var holding an Azure Storage **SAS token** — typically
36    /// a short-lived, scope-limited credential issued out-of-band (Azure
37    /// portal / `az storage container generate-sas` / Azure SDK).  Use this
38    /// instead of `account_key_env` when the operator does not have the
39    /// long-lived account key or wants per-job scoped access.  Pair with
40    /// `account_name`.  Mutually exclusive with `account_key_env`.
41    ///
42    /// The token value is wiped from heap on drop via the same
43    /// `Zeroizing<String>` wrapper as `account_key_env`.  Leading `?` is
44    /// trimmed transparently so the operator can paste either the full
45    /// `?sv=…&sig=…` query string or the raw token body.
46    pub sas_token_env: Option<String>,
47    #[serde(default)]
48    pub allow_anonymous: bool,
49}
50
51#[derive(Debug, Deserialize, Serialize, JsonSchema, Clone, Copy, PartialEq, Eq, Default)]
52#[serde(rename_all = "lowercase")]
53pub enum DestinationType {
54    #[default]
55    Local,
56    S3,
57    Gcs,
58    Azure,
59    Stdout,
60}
61
62impl DestinationType {
63    /// Stable lowercase string label for persistence and display.
64    pub fn label(self) -> &'static str {
65        match self {
66            DestinationType::Local => "local",
67            DestinationType::S3 => "s3",
68            DestinationType::Gcs => "gcs",
69            DestinationType::Azure => "azure",
70            DestinationType::Stdout => "stdout",
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn destination_type_labels_stable() {
81        assert_eq!(DestinationType::Local.label(), "local");
82        assert_eq!(DestinationType::S3.label(), "s3");
83        assert_eq!(DestinationType::Gcs.label(), "gcs");
84        assert_eq!(DestinationType::Azure.label(), "azure");
85        assert_eq!(DestinationType::Stdout.label(), "stdout");
86    }
87}