feat(routes): author group route templates in manifest + reconcile (§11 tail R4)
Open the declarative path so a [group] can declare route TEMPLATES.
- manifest.rs: drop the blanket "[group] cannot declare [[routes]]"
rejection (routes join the event trigger templates a group may own).
- apply_service:
- validate_bundle_for: remove the group routes rejection. A group
route's `script` is validated as binding a group-owned ENDPOINT via
`resolve_inherited_targets_for(Group)`, now extended to scan
bundle.routes as well as bundle.triggers — so a template binding the
group's own (declared or pre-existing) endpoint resolves, and one
pointing at a module or a missing name is a 422.
- insert_bundle_route takes a ScriptOwner (was app-only): a group node
writes a group_id route TEMPLATE, an app node an app-owned route.
- load_current(Group) loads the group's own routes via list_for_group
so re-apply is a NoOp and the template is prune-able.
Host-claim validation stays App-only (already guarded) — a template has
no single app; a descendant serves it on whatever host it claims (so
templates use host_kind = any in practice).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -68,15 +68,11 @@ impl Manifest {
|
||||
}
|
||||
}
|
||||
// A group node owns scripts + vars (+ secret names) and, as of §11 tail,
|
||||
// EVENT trigger TEMPLATES (kv/docs/files/pubsub) that fan out live to
|
||||
// descendant apps. Routes stay app-only; so do the stateful trigger
|
||||
// kinds (cron/queue/email need per-app state/secrets → materialization).
|
||||
// ROUTE TEMPLATES + EVENT trigger TEMPLATES (kv/docs/files/pubsub) that
|
||||
// fan out live to descendant apps. The stateful trigger kinds
|
||||
// (cron/queue/email) stay app-only — they need per-app state/secrets →
|
||||
// materialization.
|
||||
if m.group.is_some() {
|
||||
if !m.routes.is_empty() {
|
||||
anyhow::bail!(
|
||||
"a [group] manifest cannot declare [[routes]] — routes bind to an app"
|
||||
);
|
||||
}
|
||||
let t = &m.triggers;
|
||||
if !t.cron.is_empty() || !t.queue.is_empty() || !t.email.is_empty() {
|
||||
anyhow::bail!(
|
||||
|
||||
Reference in New Issue
Block a user