Vouch for the account that runs mesh-cli, and ask the controller its line (hq ADR 0272)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

The records send the operator to "the controller's terminal", and nothing
reaches it (hq issue 343). mesh-cli holds no credential: it asks the engine
on its own machine over a socket. The engine reads the asking account from
the kernel (SO_PEERCRED), never from the program, and asks the controller on
mesh.control.<node>.cli, its own node's subject, so the bus server says which
node asked. The controller decides what the line may do; nothing received
on the socket is run or applied here, and the socket has no network address
(ADR 0004 stands).

The local protocol is the SDK's go/cli package, at a pseudo-version of its
branch until that merges and is tagged go/v0.1.8.
This commit is contained in:
jochen
2026-10-09 12:05:53 +02:00
parent a390bce5f2
commit 021d860ca4
10 changed files with 469 additions and 0 deletions
+5
View File
@@ -1218,6 +1218,9 @@ func runLink(ctx context.Context, opts options) error {
}
// And the core builds this host placed are judged, whichever host placed them (to-be 45 §8).
go watchWhatThisHostPlaced(aside, mine.Node, queue, say)
// And mesh-cli is answered on this machine: the account from the kernel, the line asked of the controller
// (novox/hq ADR 0272).
go serveMeshCLI(aside, queue, say)
held := link.HoldRoused(aside, membership, queue, say, opts.timeout, rousedBySignal(ctx))
// The act in hand finishes and is kept before this process exits: an apply that stood aside with
@@ -1364,6 +1367,8 @@ func (w *adoptionWatch) changed(r link.Report) bool {
// be a control surface on every machine, reachable by anything that can reach the machine, in
// exchange for saving twenty seconds — and the whole security argument rests on there not being
// one. A signal is delivered by the service manager to a process it already supervises.
// (mesh-cli's socket is no such surface: it has no network address and nothing sent to it acts on
// the machine — it is asked of the controller, novox/hq ADR 0272 §3.)
//
// SIGHUP, because that is the signal a long-running program conventionally reads as *look again*,
// and nothing here is being reloaded from a file that a different signal would suit better.
+39
View File
@@ -0,0 +1,39 @@
package main
import (
"context"
"encoding/json"
"fmt"
"git.novox.be/novox/mesh-sdk/go/cli"
"github.com/novox/mesh-host/internal/link"
"github.com/novox/mesh-host/internal/meshcli"
)
// serveMeshCLI answers mesh-cli on this machine for as long as this engine serves (novox/hq ADR 0272): the account
// from the kernel, the line asked of the controller over the link open at the time. A socket that cannot be served
// is said once, and this engine goes on applying; mesh-cli then says the engine does not answer.
func serveMeshCLI(ctx context.Context, queue *link.Queue, say func(string)) {
if err := meshcli.Serve(ctx, cli.Socket, forwardOver(queue), say); err != nil {
say("mesh-cli is not answered on this machine: " + err.Error())
}
}
// forwardOver asks the controller over the queue's link, and reads its answer as mesh-cli's.
func forwardOver(queue *link.Queue) meshcli.Forward {
return func(ctx context.Context, asked meshcli.Asked) (cli.Answer, error) {
body, err := json.Marshal(asked)
if err != nil {
return cli.Answer{}, err
}
reply, err := queue.AskController(ctx, body)
if err != nil {
return cli.Answer{}, err
}
var a cli.Answer
if err := json.Unmarshal(reply, &a); err != nil {
return cli.Answer{}, fmt.Errorf("the controller's answer is not one: %w", err)
}
return a, nil
}
}