package catalogue import ( "regexp" "slices" ) // What a module may call an event, and what a consumer may ask for. // // A module names an event **locally**: `order.placed`, not a subject and not a routing key // (design 29 §1). A consumer names the emitter and the event: `billing.order.placed`. The mesh // derives the subject from those, so reorganising the subject space leaves every manifest correct. // // **Nothing checked this until every manifest in the catalogue was wrong the same way** // (novox/hq 04-ISSUES/127). All thirty-seven kept the old bus's routing key — // `module..` — which the derivation read as "a module called `module`", so every // cross-module subscription in the mesh pointed at a namespace nobody publishes to. Nothing failed: // the services started and none of them reacted. The documentation on these fields taught the old // form too, which is why the drift was uniform rather than scattered. // eventName is one name in a local event: lower-case, and no wildcard. var eventName = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`) // The wildcards a consumer may use, spelled the mesh's way and derived to whatever the transport // spells them as. // // **A manifest holds no transport token**, which is the whole point of naming locally: the bus the // mesh runs on today spells these `*` and `#`, and the one being built spells them `*` and `>`. A // manifest that said either would be a manifest that stopped being true when the wire changed. const ( // OneName stands for exactly one name. OneName = "*" // TheRest stands for one or more names, and may only come last. TheRest = "**" ) // The events a provider says about its consumers (novox/hq ADR 0224): a consumer it has failed // without one success for minutes, and that consumer succeeding again or being withdrawn. The // controller follows them from every module and `status` names a consumer failing until it recovers. // // **And what becomes of a consumer the mesh stopped asking for** (novox/hq ADR 0230): retired — its // access disabled and its data kept — after the same answer in five passes, waiting for a person when // more would go than the bound allows, re-enabled when asked for again, and deleted only by a person's // `cleanup delete`. One event, its `change` saying which. const ( ProvisionerFailing = "provisioner.failing" ProvisionerRecovered = "provisioner.recovered" ProvisionerRetirement = "provisioner.retirement" ) // ProvisionerEvents are all three, in the order they are said. var ProvisionerEvents = []string{ProvisionerFailing, ProvisionerRecovered, ProvisionerRetirement} // EmitsAll is every event a module may publish: what it declares and, for a module that receives // contributions — a provider, running a provisioner over them — the provider's standing events. // // **Derived, not declared**, because they are the mesh's rule about every provider rather than // anything one module chose to say: a provider whose manifest forgot them would fail its consumers // as silently as on 2026-10-05, with its announcement refused by the bus (novox/hq issue 179). Every // grant of a module's publishing reads this, never the declared list alone. func (m Manifest) EmitsAll() []string { out := append([]string(nil), m.Emits...) if len(m.Receives) == 0 { return out } for _, e := range ProvisionerEvents { if !slices.Contains(out, e) { out = append(out, e) } } return out }