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}