mesh: carry gateway_domain so peers can launch remote apps

The mesh payload didn't include a node's acme domain, so a peer had no way
to build launch URLs for another machine's exposed apps. Publish
gateway_domain in the MQTT registry payload and surface it per-deployment on
/mesh/deployments as `domain`. The dashboard palette and System Map now build
`https://<subdomain>.<domain>` for remote http-exposed apps (references use
their base_url), making primer's apps launchable from civil.
This commit is contained in:
2026-07-06 21:07:10 -07:00
parent 25bc8a8ab1
commit b28645f2f4
5 changed files with 49 additions and 6 deletions

View File

@@ -37,6 +37,9 @@ def _registry_to_json(registry: NodeRegistry) -> str:
"node": {
"hostname": registry.node.hostname,
"gateway_port": registry.node.gateway_port,
# acme domain — lets peers build launch URLs (<subdomain>.<gateway_domain>)
# for this node's exposed apps. Omitted when the node has no domain.
"gateway_domain": registry.node.gateway_domain,
},
"deployed": {},
}
@@ -83,6 +86,7 @@ def _json_to_registry(payload: str) -> NodeRegistry:
hostname=node_data.get("hostname", ""),
castle_root=node_data.get("castle_root"),
gateway_port=node_data.get("gateway_port", 9000),
gateway_domain=node_data.get("gateway_domain"),
)
deployed: dict[str, Deployment] = {}
for key, comp_data in data.get("deployed", {}).items():

View File

@@ -115,16 +115,18 @@ def _endpoints_of_registry(d: object) -> list[dict]:
def mesh_deployments() -> dict:
"""Flattened remote (mesh-discovered) deployments with derived endpoints — the
data the System Map needs to render other machines. Local node excluded (it's
already in /graph). Cross-node dependency *edges* need `requires` in the mesh
payload, which the registry doesn't carry yet."""
already in /graph). Each entry carries its node's `domain` (gateway acme domain)
so peers can build launch URLs `<subdomain>.<domain>` for exposed apps."""
out: list[dict] = []
for hostname, remote in mesh_state.all_nodes(include_stale=True).items():
domain = getattr(remote.registry.node, "gateway_domain", None)
for _kind, name, d in remote.registry.all():
out.append(
{
"name": name,
"kind": d.kind,
"node": hostname,
"domain": domain,
"port": d.port,
"base_url": getattr(d, "base_url", None),
"subdomain": d.subdomain,