feat(stateful-templates): materialize group email templates (M5.5)
Close the last M5 gap: a [group] may now declare an email trigger template, materialized into a per-descendant-app row like cron/queue. Uses the shared-group-secret model: the template resolves its inbound_secret_ref against the GROUP's own secret store once at apply and seals it (resolve_and_seal + insert_email_trigger_tx generalized to a SecretOwner / ScriptOwner). Email secrets are v0/no-AAD, so the sealed blob is portable across rows — materialize copies the bytes verbatim into each descendant (no master key, no reseal, no new schema column, no threading into the CRUD hooks). Each copy has its own trigger_id / inbound webhook URL. - apply_service/manifest: drop the two group-email rejections; a group email template with an unset group secret still fails apply hard. - materialize: add "email" to MATERIALIZED_KINDS + a byte-copy detail arm. - trigger_repo: email_inbound_target gains AND t.app_id IS NOT NULL so a group TEMPLATE row is never directly invocable via its own webhook URL (mirrors the cron/queue app_id guards). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -75,19 +75,12 @@ impl Manifest {
|
||||
// ROUTE TEMPLATES + EVENT trigger TEMPLATES (kv/docs/files/pubsub) that
|
||||
// fan out live to descendant apps. As of §11 tail M1 a group may also
|
||||
// declare `[suppress]` to decline a template it inherits from a higher
|
||||
// ancestor, for its whole subtree. The stateful trigger kinds
|
||||
// (cron/queue/email) stay app-only — they need per-app state/secrets →
|
||||
// materialization.
|
||||
// §4.5 M5: a group may declare STATEFUL trigger templates too — cron and
|
||||
// queue materialize a per-descendant-app row (email lands with its
|
||||
// per-app inbound-secret handling). Only the app-specific `email` kind
|
||||
// is still rejected on a group here.
|
||||
if m.group.is_some() && !m.triggers.email.is_empty() {
|
||||
anyhow::bail!(
|
||||
"a [group] email trigger template is not yet supported \
|
||||
(per-app inbound secret); cron/queue/event kinds are allowed"
|
||||
);
|
||||
}
|
||||
// ancestor, for its whole subtree.
|
||||
// §4.5 M5: a group may declare STATEFUL trigger templates too — cron,
|
||||
// queue, and email materialize a per-descendant-app row. An email
|
||||
// template resolves its `inbound_secret_ref` against the GROUP's own
|
||||
// secret store once at apply (shared-group-secret model); the server
|
||||
// rejects it there if the secret is unset.
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user