alien_core/secret_delivery.rs
1//! How a compute resource's Secret-typed env vars reach the running workload.
2//!
3//! The deployment layer injects Secret-typed env vars one of two ways, and the
4//! choice depends on the platform and the compute kind. Modeling both as typed
5//! enums keeps the decision in one exhaustive `match` — a new [`Platform`] or
6//! [`ComputeKind`] variant fails to compile until it picks a delivery — instead
7//! of stringly-typed `matches!(resource_type, "container" | "daemon")` checks
8//! scattered across crates.
9
10use crate::Platform;
11
12/// A compute resource kind that receives injected environment variables.
13///
14/// Only the three compute kinds are represented; storage/queue/etc. resources
15/// never carry an app env and are not part of secret delivery.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum ComputeKind {
18 Worker,
19 Container,
20 Daemon,
21}
22
23impl ComputeKind {
24 /// The resource-type string this kind serializes as (matches each
25 /// resource's `RESOURCE_TYPE`). Handy for logs and diagnostics.
26 pub fn as_str(self) -> &'static str {
27 match self {
28 ComputeKind::Worker => "worker",
29 ComputeKind::Container => "container",
30 ComputeKind::Daemon => "daemon",
31 }
32 }
33}
34
35/// The mechanism by which Secret-typed env vars are delivered to a workload.
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum SecretDelivery {
38 /// Inject the `ALIEN_SECRETS` vault-load pointer (the secret keys plus a
39 /// values hash). At startup the workload loads the actual values from the
40 /// "secrets" vault through the Worker runtime wrapper. Worker-only:
41 /// runtime-less workloads have nothing that could consume the pointer.
42 VaultPointer,
43 /// The hosting layer delivers each applicable secret natively before the
44 /// process starts — Kubernetes `valueFrom.secretKeyRef`, the local
45 /// supervisor's resolved plain env, or the cloud container host's native
46 /// secret projection — so no
47 /// vault-load pointer is ever injected.
48 NativeProjection,
49}
50
51impl SecretDelivery {
52 /// Resolves how a compute kind's secrets are delivered.
53 ///
54 /// - Kubernetes and Machines hosting layers project Worker secrets before
55 /// process start. Other Worker hosts use the runtime vault pointer.
56 /// - Containers and Daemons are runtime-less on every platform:
57 /// nothing in the workload can load a vault pointer, so
58 /// the hosting layer projects secrets natively before process start
59 /// (Kubernetes secretKeyRef, local supervisor plain env, or native cloud
60 /// container secret injection) and the pointer must never be minted for them.
61 ///
62 /// The match is exhaustive over both enums so a new platform or compute
63 /// kind forces an explicit delivery choice here.
64 pub fn resolve(platform: Platform, kind: ComputeKind) -> Self {
65 match (platform, kind) {
66 (_, ComputeKind::Container | ComputeKind::Daemon) => SecretDelivery::NativeProjection,
67 (Platform::Kubernetes | Platform::Machines, ComputeKind::Worker) => {
68 SecretDelivery::NativeProjection
69 }
70 (
71 Platform::Aws | Platform::Gcp | Platform::Azure | Platform::Local | Platform::Test,
72 ComputeKind::Worker,
73 ) => SecretDelivery::VaultPointer,
74 }
75 }
76
77 /// Whether the platform projects this kind's secrets natively (no pointer).
78 pub fn is_native_projection(self) -> bool {
79 matches!(self, SecretDelivery::NativeProjection)
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 /// A runtime-less Container/Daemon has nothing that could consume a vault
88 /// pointer on any platform.
89 #[test]
90 fn containers_and_daemons_always_project_natively() {
91 for kind in [ComputeKind::Container, ComputeKind::Daemon] {
92 assert_eq!(
93 SecretDelivery::resolve(Platform::Aws, kind),
94 SecretDelivery::NativeProjection,
95 "{} must never receive the vault pointer",
96 kind.as_str()
97 );
98 }
99 }
100
101 #[test]
102 fn worker_delivery_depends_on_host_capability() {
103 for platform in [Platform::Kubernetes, Platform::Machines] {
104 assert_eq!(
105 SecretDelivery::resolve(platform, ComputeKind::Worker),
106 SecretDelivery::NativeProjection,
107 "{platform:?} projects Worker secrets"
108 );
109 }
110 for platform in [
111 Platform::Aws,
112 Platform::Gcp,
113 Platform::Azure,
114 Platform::Local,
115 Platform::Test,
116 ] {
117 assert_eq!(
118 SecretDelivery::resolve(platform, ComputeKind::Worker),
119 SecretDelivery::VaultPointer,
120 "{platform:?} Worker uses the runtime vault pointer"
121 );
122 }
123 }
124}