diff --git a/crates/picloud-cli/src/manifest.rs b/crates/picloud-cli/src/manifest.rs index 1ccad2f..e82ff8c 100644 --- a/crates/picloud-cli/src/manifest.rs +++ b/crates/picloud-cli/src/manifest.rs @@ -904,13 +904,16 @@ mod tests { ) .expect("group cron template parses"); assert_eq!(cron.triggers.cron.len(), 1); - // ...but an email template on a group is still rejected (per-app secret). - let err = Manifest::parse( + // §4.5 M5.5: a group email template is now ALLOWED too — it materializes + // per descendant app and resolves its `inbound_secret_ref` against the + // GROUP's own secret store at apply (the server rejects it there if the + // secret is unset). Parse no longer refuses it. + let email = Manifest::parse( "[group]\nslug = \"acme\"\nname = \"ACME\"\n\n\ [[triggers.email]]\nscript = \"shared\"\ninbound_secret_ref = \"sig\"\n", ) - .expect_err("group email template is rejected"); - assert!(err.to_string().contains("email"), "got: {err}"); + .expect("group email template parses"); + assert_eq!(email.triggers.email.len(), 1); // Neither / both is rejected. Manifest::parse("[vars]\nx = 1\n").expect_err("no [app] or [group]");