mesh/merge-gate pass: builds claude-code, route-adapter, new: modules/mesh-cli → ace, g14, novox, shanks; no bus step; every machine composes with the chan…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
A line whose answer did not come in time is said as possibly run, with its call, never as nothing having run. A test holds the module to one archive resource unpacking one compiled Go bundle into /usr/local/bin. The README says the MESH_VERB refusal is a courtesy and the controller is the gate. SDK pinned at the go/cli branch's newest commit until go/v0.1.9.
87 lines
3.0 KiB
Go
87 lines
3.0 KiB
Go
// Command mesh-cli is the operator's command on every node (novox/hq ADR 0272): `mesh-cli <command line>` asks the
|
|
// controller to run one of its command lines, and prints what it said. In interactive zsh it is also `nox`.
|
|
//
|
|
// It holds no credential and reads no file of the mesh. It asks the node-engine on this machine over a local
|
|
// socket; the engine reads which account is asking from the kernel and asks the controller. The controller decides:
|
|
// on the control-node, from the operator's own account, the line runs as the controller's terminal; elsewhere it is
|
|
// an ordinary call, and a change made at the terminal alone is refused with the reason; from any other account
|
|
// nothing runs.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/cli"
|
|
)
|
|
|
|
// socket is where the node-engine answers; a variable so a test can name its own.
|
|
var socket = cli.Socket
|
|
|
|
const usage = `mesh-cli — the controller's command lines, from this node (novox/hq ADR 0272)
|
|
|
|
mesh-cli <command line> e.g. mesh-cli status, mesh-cli settings show zsh --node <node>
|
|
nox <command line> the same, in interactive zsh
|
|
|
|
Run it as yourself, never under sudo: the node-engine tells the controller which account asks.
|
|
On the control-node, from its operator's account, the line runs as the controller's terminal.
|
|
Anywhere else it is an ordinary call, and a terminal-only change is refused with the reason.
|
|
'mesh-cli help' asks the controller for its own list of command lines.
|
|
`
|
|
|
|
func main() {
|
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
code := run(ctx, os.Args[1:], os.Stdout, os.Stderr)
|
|
stop()
|
|
os.Exit(code)
|
|
}
|
|
|
|
func run(ctx context.Context, args []string, stdout, stderr io.Writer) int {
|
|
if len(args) == 0 || args[0] == "-h" || args[0] == "--help" {
|
|
fmt.Fprint(stderr, usage)
|
|
return 2
|
|
}
|
|
// A verb's own process carries the verb it runs for; a verb is never a person, so it is never the terminal.
|
|
if verb := os.Getenv("MESH_VERB"); verb != "" {
|
|
fmt.Fprintf(stderr, "mesh-cli: this process runs for the verb %q, and a verb is never the operator. "+
|
|
"Nothing was asked\n", verb)
|
|
return 1
|
|
}
|
|
a, err := cli.Ask(ctx, socket, args)
|
|
if err != nil {
|
|
if errors.Is(ctx.Err(), context.Canceled) {
|
|
fmt.Fprintln(stderr, "mesh-cli: stopped waiting; the line may still be running on the controller")
|
|
return 130
|
|
}
|
|
fmt.Fprintf(stderr, "mesh-cli: %v\n", err)
|
|
return 1
|
|
}
|
|
_, _ = stdout.Write(a.Stdout)
|
|
_, _ = stderr.Write(a.Stderr)
|
|
if a.Cut {
|
|
fmt.Fprintln(stderr, "mesh-cli: the output was longer than one bus message, and was cut there")
|
|
}
|
|
if !a.Terminal && a.Why != "" {
|
|
fmt.Fprintln(stderr, "mesh-cli: "+a.Why)
|
|
}
|
|
if a.Unknown != "" {
|
|
// Asked, and what came of it not known: never said as nothing having run.
|
|
fmt.Fprintln(stderr, "mesh-cli: "+a.Unknown)
|
|
if a.Exit == 0 {
|
|
return 1
|
|
}
|
|
}
|
|
if a.Refused != "" {
|
|
fmt.Fprintln(stderr, "mesh-cli: "+a.Refused)
|
|
if a.Exit == 0 {
|
|
return 1
|
|
}
|
|
}
|
|
return a.Exit
|
|
}
|