Watch
0
0
Fork
You've already forked hyperhive
0

an archetype carries its own notification-router flows for its agents

ArchetypeMeta gets flows, checked when the controller stores the record: every todo must go to the new members recipient, which the router expands to the agents of the archetype. The operator's flows document refuses members. The router reads the archetype records and each roster agent's archetype key, and its NATS grant gains read on both buckets.
This commit is contained in:
atlas 2026-11-11 04:36:25 +01:00 • committed by mara
commit 1efbb72fdd

View file

@ -82,13 +82,33 @@ pub fn reached<'f>(flow: &'f Flow, event_type: &str, fields: &Fields) -> Vec<&'f
ids
}
/// A flow an archetype carries, with the agents of that archetype: who a
/// `members` recipient expands to.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ArchetypeFlow {
pub flow: Flow,
pub members: Vec<String>,
}
/// Walk `flow` for one event of type `event_type` and return the todo ops it
/// emits. Assumes [`Flow::validate`] passed.
/// emits. Assumes [`Flow::validate`] passed, so it has no `members` recipient;
/// [`evaluate_for`] runs an archetype's flow.
pub fn evaluate(flow: &Flow, event_type: &str, fields: &Fields) -> Vec<Action> {
evaluate_for(flow, event_type, fields, &[])
}
/// [`evaluate`] for a flow that passed [`Flow::validate_archetype`]: a
/// `members` recipient expands to `members`.
pub fn evaluate_for(
flow: &Flow,
event_type: &str,
fields: &Fields,
members: &[String],
) -> Vec<Action> {
let mut actions = Vec::new();
walk(flow, event_type, fields, |node| {
if let NodeKind::Todo(sink) = &node.kind {
actions.extend(emit(flow, node, sink, fields));
actions.extend(emit(flow, node, sink, fields, members));
}
});
actions
@ -126,9 +146,16 @@ fn request(flow: &Flow, node: &Node, reviewer: &str, fields: &Fields) -> Option<
})
}
fn emit(flow: &Flow, node: &Node, sink: &TodoSink, fields: &Fields) -> Vec<Action> {
fn emit(
flow: &Flow,
node: &Node,
sink: &TodoSink,
fields: &Fields,
members: &[String],
) -> Vec<Action> {
let recipients = match &sink.to {
Recipients::Agent(agent) => vec![agent.clone()],
Recipients::Members => members.to_vec(),
Recipients::Field(name) => match fields.get(name.as_str()) {
Some(Value::List(items)) => items.clone(),
Some(Value::Text(one)) => vec![one.clone()],