The runtime speaks the bus its credential names #14

Merged
mesh-admin merged 1 commits from feat/the-runtime-speaks-the-bus-its-credential-names into main 2026-09-28 00:42:29 +00:00
Showing only changes of commit 9e3ff6fa45 - Show all commits
+17 -2
View File
@@ -22,7 +22,8 @@
import { readFileSync } from "node:fs";
import { pathToFileURL } from "node:url";
import { connectAmqp, fatalBrokerReason } from "./broker-amqp.js";
import { connectAmqp, fatalBrokerReason as fatalAmqpReason } from "./broker-amqp.js";
import { connectNats, fatalBrokerReason as fatalNatsReason } from "./broker-nats.js";
import type { Credential } from "./broker-amqp.js";
import { runTools } from "./runtime.js";
import { invokeTool } from "@novox/mesh-sdk/tools";
@@ -35,6 +36,12 @@ import { emit } from "@novox/mesh-sdk/events";
* over the plain bootstrap URL otherwise. A scoped module assumes the foundation's exchanges exist —
* its account may not declare them (ADR 0043).
*/
// fatalBrokerReasonFor is the reason a connection failure is final rather than "not yet", for
// whichever bus this runtime is on — each transport knows its own refusals.
function fatalBrokerReasonFor(err: unknown): string | null {
return fatalNatsReason(err) ?? fatalAmqpReason(err);
}
async function connectBroker(): Promise<Broker> {
const file = process.env.MESH_BROKER_FILE;
if (file) {
@@ -54,6 +61,14 @@ async function connectBroker(): Promise<Broker> {
// what the environment says.
if (credential.node) process.env.MESH_NODE = credential.node;
if (credential.module) process.env.MESH_MODULE = credential.module;
// **The credential names the bus.** A module moved to the bus being built was handed a
// credential for it — `nats://…` with user, password and fingerprint beside the address — and
// nothing else in its environment changed (design 25; novox/hq design 28 task 5.2). The scheme
// is enough to know which bus to speak; a runtime that always dialled the old one would keep
// serving and answer nobody.
if (credential.url.startsWith("nats://")) {
return connectNats(credential);
}
return connectAmqp(credential, { assumeExchanges: true });
}
const url = process.env.MESH_BROKER_URL;
@@ -83,7 +98,7 @@ async function connectBrokerPatiently(): Promise<Broker> {
try {
return await connectBroker();
} catch (err) {
const fatal = fatalBrokerReason(err);
const fatal = fatalBrokerReasonFor(err);
if (fatal !== null) {
console.error(`mesh-tools: ${fatal} — waiting will not fix this; giving up`);
throw err;