mesh-cli: carry what a pipe or a file gives standard input with the line, at most 64 KiB
mesh/merge-gate pass: builds mesh-cli → 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, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered

So a secret reaches the controller's terminal without standing on a command line:
mesh-cli secret accept <node> <module> <name> --from - < file. A terminal is never read, more than the
bound is refused before anything is asked, and nothing carried is printed. mesh-sdk moves to f047d0a.
This commit is contained in:
2026-10-09 16:50:46 +02:00
parent 954e3e2087
commit f3dcb9dc5a
4 changed files with 88 additions and 4 deletions
@@ -3,6 +3,7 @@ package main
import (
"bytes"
"context"
"io"
"net"
"path/filepath"
"strings"
@@ -11,6 +12,13 @@ import (
"git.novox.be/novox/mesh-sdk/go/cli"
)
// The tests' own standard input is the runner's, which may be a pipe nobody closes: read as a terminal unless a test
// says otherwise.
func init() { standardInput = func() (io.Reader, bool) { return nil, true } }
// lastStdin is the standard input the engine was last given.
var lastStdin []byte
// engine answers one connection on a socket of the test's own as the node-engine would, and says what it was asked.
func engine(t *testing.T, answer cli.Answer) <-chan []string {
t.Helper()
@@ -24,6 +32,7 @@ func engine(t *testing.T, answer cli.Answer) <-chan []string {
socket = path
t.Cleanup(func() { socket = before })
asked := make(chan []string, 1)
lastStdin = nil
go func() {
conn, err := l.Accept()
if err != nil {
@@ -34,6 +43,7 @@ func engine(t *testing.T, answer cli.Answer) <-chan []string {
if err != nil {
return
}
lastStdin = req.Stdin
asked <- req.Line
_ = cli.WriteAnswer(conn, answer)
}()
@@ -104,3 +114,42 @@ func TestAnOutcomeNotKnownIsSaid(t *testing.T) {
t.Fatalf("exit %d, said %q", code, errOut.String())
}
}
// A pipe's or a file's standard input goes with the line, whole; a terminal's is never read; more than the bound is
// refused and nothing is asked (novox/hq ADR 0259 §10).
func TestStandardInputGoesWithTheLineAndATerminalIsNeverRead(t *testing.T) {
t.Setenv("MESH_VERB", "")
was := standardInput
t.Cleanup(func() { standardInput = was })
secret := "123456789:the-bot-token\n"
standardInput = func() (io.Reader, bool) { return strings.NewReader(secret), false }
asked := engine(t, cli.Answer{Terminal: true})
var out, errOut bytes.Buffer
if code := run(context.Background(), []string{"secret", "accept", "anchor", "telegram", "telegram-token", "--from", "-"},
&out, &errOut); code != 0 {
t.Fatalf("exit %d: %s", code, errOut.String())
}
<-asked
if string(lastStdin) != secret {
t.Fatalf("the engine was given %q", lastStdin)
}
if strings.Contains(out.String()+errOut.String(), "bot-token") {
t.Fatal("mesh-cli printed what it carried")
}
standardInput = func() (io.Reader, bool) { return strings.NewReader("typed"), true }
asked = engine(t, cli.Answer{})
_ = run(context.Background(), []string{"status"}, &out, &errOut)
<-asked
if len(lastStdin) != 0 {
t.Fatalf("a terminal's input was read: %q", lastStdin)
}
standardInput = func() (io.Reader, bool) { return bytes.NewReader(make([]byte, cli.MaxStdin+1)), false }
errOut.Reset()
if code := run(context.Background(), []string{"secret", "accept", "a", "b", "c", "--from", "-"}, &out, &errOut); code == 0 ||
!strings.Contains(errOut.String(), "nothing was asked") {
t.Fatalf("more than the bound was asked: %d %s", code, errOut.String())
}
}