Add edge routing and health check RPCs (Phase 2)

New agent RPCs for v2 multi-node orchestration:

- SetupEdgeRoute: provisions TLS cert from Metacrypt, resolves backend
  hostname to Tailnet IP, validates it's in 100.64.0.0/10, registers
  L7 route in mc-proxy. Rejects backend_tls=false.
- RemoveEdgeRoute: removes mc-proxy route, cleans up TLS cert, removes
  registry entry.
- ListEdgeRoutes: returns all edge routes with cert serial/expiry.
- HealthCheck: returns agent health and container count.

New database table (migration 4): edge_routes stores hostname, backend
info, and cert paths for persistence across agent restarts.

ProxyRouter gains CertPath/KeyPath helpers for consistent cert path
construction.

Security:
- Backend hostname must resolve to a Tailnet IP (100.64.0.0/10)
- backend_tls=false is rejected (no cleartext to backends)
- Cert provisioning failure fails the setup (no route to missing cert)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 13:13:10 -07:00
parent fa8ba6fac1
commit 714320c018
7 changed files with 1069 additions and 56 deletions

View File

@@ -42,6 +42,14 @@ service McpAgentService {
rpc AddProxyRoute(AddProxyRouteRequest) returns (AddProxyRouteResponse);
rpc RemoveProxyRoute(RemoveProxyRouteRequest) returns (RemoveProxyRouteResponse);
// Edge routing (called by master on edge nodes)
rpc SetupEdgeRoute(SetupEdgeRouteRequest) returns (SetupEdgeRouteResponse);
rpc RemoveEdgeRoute(RemoveEdgeRouteRequest) returns (RemoveEdgeRouteResponse);
rpc ListEdgeRoutes(ListEdgeRoutesRequest) returns (ListEdgeRoutesResponse);
// Health (called by master on missed heartbeats)
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
// Logs
rpc Logs(LogsRequest) returns (stream LogsResponse);
}
@@ -72,6 +80,7 @@ message ServiceSpec {
string name = 1;
bool active = 2;
repeated ComponentSpec components = 3;
string comment = 4;
}
message DeployRequest {
@@ -151,6 +160,7 @@ message ServiceInfo {
string name = 1;
bool active = 2;
repeated ComponentInfo components = 3;
string comment = 4;
}
message ComponentInfo {
@@ -377,3 +387,43 @@ message RemoveProxyRouteRequest {
}
message RemoveProxyRouteResponse {}
// --- Edge routes (v2) ---
message SetupEdgeRouteRequest {
string hostname = 1; // public hostname (e.g. "mcq.metacircular.net")
string backend_hostname = 2; // internal .svc.mcp hostname
int32 backend_port = 3; // port on worker's mc-proxy
bool backend_tls = 4; // MUST be true; agent rejects false
}
message SetupEdgeRouteResponse {}
message RemoveEdgeRouteRequest {
string hostname = 1;
}
message RemoveEdgeRouteResponse {}
message ListEdgeRoutesRequest {}
message ListEdgeRoutesResponse {
repeated EdgeRoute routes = 1;
}
message EdgeRoute {
string hostname = 1;
string backend_hostname = 2;
int32 backend_port = 3;
string cert_serial = 4;
string cert_expires = 5; // RFC3339
}
// --- Health check (v2) ---
message HealthCheckRequest {}
message HealthCheckResponse {
string status = 1; // "healthy" or "degraded"
int32 containers = 2;
}