notify router: read custom flows and disabled built-ins from a stored document
This commit is contained in:
parent
03fc548b0a
commit
bb08fac33c
11 changed files with 1418 additions and 342 deletions
|
|
@ -317,7 +317,7 @@ impl Policy {
|
|||
|
||||
/// What the notification router may do: drain its own consumer on the
|
||||
/// forge events stream, queue todo ops for any agent, keep its own state
|
||||
/// bucket, and list which agents exist.
|
||||
/// bucket, read the flows document, and list which agents exist.
|
||||
///
|
||||
/// - **Forge events.** Open or create the stream, create its one durable
|
||||
/// in the extended form whose last tokens are the filter (the server
|
||||
|
|
@ -330,14 +330,18 @@ impl Policy {
|
|||
/// subjects, which is what makes the router their sole writer.
|
||||
/// - **Its state bucket.** Create, look up, read and write
|
||||
/// `notify-router-state`, and no other bucket.
|
||||
/// - **The flows document.** `STREAM.INFO` and `DIRECT.GET` on
|
||||
/// `notify-flows`, which it reads and never creates or writes: the
|
||||
/// controller creates the bucket and is its one writer.
|
||||
/// - **The roster.** `STREAM.INFO` on the agent-status bucket, which lists
|
||||
/// its keys (`<hive>.<agent>`) and writes none.
|
||||
fn notify_router_permissions(client_id: &str) -> Permissions {
|
||||
use swarm_wire::{forge_events, notify_router, router_todo};
|
||||
use swarm_wire::{forge_events, notify_flows, notify_router, router_todo};
|
||||
|
||||
let events = forge_events::STREAM;
|
||||
let consumer = forge_events::ROUTER_CONSUMER;
|
||||
let state = format!("KV_{}", notify_router::STATE_BUCKET);
|
||||
let flows = format!("KV_{}", notify_flows::BUCKET);
|
||||
let mut publish = Self::jetstream_minimum().to_vec();
|
||||
publish.extend([
|
||||
format!("$JS.API.STREAM.INFO.{events}"),
|
||||
|
|
@ -355,6 +359,8 @@ impl Policy {
|
|||
format!("$JS.API.STREAM.CREATE.{state}"),
|
||||
format!("$JS.API.DIRECT.GET.{state}.>"),
|
||||
format!("$KV.{}.>", notify_router::STATE_BUCKET),
|
||||
format!("$JS.API.STREAM.INFO.{flows}"),
|
||||
format!("$JS.API.DIRECT.GET.{flows}.>"),
|
||||
format!("$JS.API.STREAM.INFO.{}", Self::agent_status_stream()),
|
||||
Self::inbox(client_id),
|
||||
]);
|
||||
|
|
@ -1799,7 +1805,7 @@ mod tests {
|
|||
#[test]
|
||||
fn the_notify_router_drains_its_own_consumer_and_writes_only_its_own_state() {
|
||||
use swarm_queue_client::client_inbox_prefix;
|
||||
use swarm_wire::{forge_events, notify_router, router_todo};
|
||||
use swarm_wire::{forge_events, notify_flows, notify_router, router_todo};
|
||||
|
||||
let p = with_router()
|
||||
.permissions(NOTIFY_ROUTER)
|
||||
|
|
@ -1807,6 +1813,7 @@ mod tests {
|
|||
let may = |subject: &str| p.publish.iter().any(|g| covers(g, subject));
|
||||
let events = forge_events::STREAM;
|
||||
let state = notify_router::STATE_BUCKET;
|
||||
let flows = notify_flows::BUCKET;
|
||||
for allowed in [
|
||||
format!(
|
||||
"$JS.API.CONSUMER.CREATE.{events}.notify-router.{}",
|
||||
|
|
@ -1820,6 +1827,9 @@ mod tests {
|
|||
format!("$KV.{state}.42.5571"),
|
||||
format!("$JS.API.DIRECT.GET.KV_{state}.$KV.{state}.42.5571"),
|
||||
"$JS.API.STREAM.INFO.KV_agent-status".to_owned(),
|
||||
// The flows document: read it.
|
||||
format!("$JS.API.STREAM.INFO.KV_{flows}"),
|
||||
format!("$JS.API.DIRECT.GET.KV_{flows}.$KV.{flows}.{}", notify_flows::KEY),
|
||||
] {
|
||||
assert!(may(&allowed), "the router may not reach {allowed}");
|
||||
}
|
||||
|
|
@ -1838,6 +1848,10 @@ mod tests {
|
|||
forge_events::subject("issues"),
|
||||
"$KV.agent-status.alpha.atlas".to_owned(),
|
||||
"$KV.agent-schedules.atlas".to_owned(),
|
||||
// The flows document: not write it, nor make the bucket.
|
||||
format!("$KV.{flows}.{}", notify_flows::KEY),
|
||||
format!("$JS.API.STREAM.CREATE.KV_{flows}"),
|
||||
format!("$JS.API.STREAM.DELETE.KV_{flows}"),
|
||||
swarm_queue_client::agent_input_subject("atlas"),
|
||||
"$JS.API.STREAM.CREATE.KV_agent-status".to_owned(),
|
||||
] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue