agent_first_http/cli/
token_source.rs1use agent_first_data::value_source::SecretString;
12use agent_first_data::{SourceSet, ValueSource};
13
14use crate::shared::error::{Error, ErrorCode};
15
16const CONTAINER: &str = "container";
19
20pub fn set() -> SourceSet {
26 SourceSet::config().host_scheme(CONTAINER, "container:NAME")
27}
28
29pub fn parse(raw: &str) -> Result<ValueSource, Error> {
32 set().parse(raw).map_err(|error| {
33 Error::new(
34 ErrorCode::InvalidArgument,
35 format!("--token-secret {error}"),
36 )
37 })
38}
39
40pub fn read(source: &ValueSource) -> Result<SecretString, Error> {
43 match source {
44 ValueSource::Host { scheme, value } if scheme == CONTAINER => {
45 crate::cli::cmd::container::read_host_token(value)
46 }
47 other => other.read_secret().map_err(|error| {
48 Error::new(
49 ErrorCode::InvalidArgument,
50 format!("--token-secret {error}"),
51 )
52 }),
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn the_container_scheme_is_afhttps_and_the_rest_is_afdatas() {
62 assert_eq!(
63 parse("container:afhttp-host").expect("container"),
64 ValueSource::Host {
65 scheme: CONTAINER.to_string(),
66 value: "afhttp-host".to_string(),
67 }
68 );
69 assert_eq!(
70 parse("env:AFHTTP_TOKEN_SECRET").expect("env"),
71 ValueSource::Env("AFHTTP_TOKEN_SECRET".to_string())
72 );
73 assert_eq!(
76 parse("t0ken").expect("bare"),
77 ValueSource::Literal("t0ken".to_string())
78 );
79 assert_eq!(
80 parse("literal:container:x").expect("escape hatch"),
81 ValueSource::Literal("container:x".to_string())
82 );
83 }
84
85 #[test]
87 fn a_token_does_not_come_from_a_stream() {
88 for raw in ["stdin", "fd:3", "prompt"] {
89 let error = parse(raw).expect_err(raw);
90 assert_eq!(error.error_code, ErrorCode::InvalidArgument, "{raw}");
91 assert!(error.detail.starts_with("--token-secret"), "{raw}");
92 }
93 }
94
95 #[test]
96 fn an_unreadable_source_names_the_flag_and_not_the_value() {
97 let error = read(&ValueSource::Env("AFHTTP_TEST_ABSENT_TOKEN".to_string()))
98 .expect_err("unset env source");
99 assert!(
100 error.detail.starts_with("--token-secret"),
101 "{}",
102 error.detail
103 );
104 assert!(
105 error.detail.contains("AFHTTP_TEST_ABSENT_TOKEN"),
106 "{}",
107 error.detail
108 );
109 }
110}