detached 52bb3d7

test(app): run broker mux tests against the production layout

commit
52bb3d7232f3f6bb9abd3aa220475c7a2c0d8bdd
author
brice · · 2026-09-23 15:10 UTC
parent
352658c
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +109 -106
M internal/app/broker_offline_mux_test.go +102 -105
@@ -21,6 +21,8 @@ import (
2121
2222 "github.com/bnema/vev/internal/adapters/brokerconfig"
2323 "github.com/bnema/vev/internal/adapters/brokeripc"
24+ "github.com/bnema/vev/internal/adapters/daemonmux"
25+ "github.com/bnema/vev/internal/adapters/ipc"
2426 "github.com/bnema/vev/internal/adapters/quic"
2527 "github.com/bnema/vev/internal/adapters/sshstdio"
2628 "github.com/bnema/vev/internal/ports"
@@ -37,20 +39,25 @@ import (
3739 // round trip proves pin, token, nonce, and daemonmux handshake all compose.
3840
3941 const (
40- fakeSSHArgsEnv = "VEV_TEST_SSH_ARGS"
41- fakeSSHReadyEnv = "VEV_TEST_SSH_READY"
42- fakeSSHPIDEnv = "VEV_TEST_SSH_PID"
43- fakeSSHBinEnv = "VEV_TEST_SSH_BIN"
44- fakeSSHModeEnv = "VEV_TEST_SSH_MODE"
45- fakeSSHRootEnv = "VEV_TEST_SSH_REMOTE_ROOT"
42+ fakeSSHArgsEnv = "VEV_TEST_SSH_ARGS"
43+ fakeSSHReadyEnv = "VEV_TEST_SSH_READY"
44+ fakeSSHPIDEnv = "VEV_TEST_SSH_PID"
45+ fakeSSHBinEnv = "VEV_TEST_SSH_BIN"
46+ fakeSSHModeEnv = "VEV_TEST_SSH_MODE"
47+ fakeSSHRuntimeEnv = "VEV_TEST_SSH_REMOTE_RUNTIME"
48+ fakeSSHStateEnv = "VEV_TEST_SSH_REMOTE_STATE"
49+ fakeSSHConfigEnv = "VEV_TEST_SSH_REMOTE_CONFIG"
4650 )
4751
4852 // fakeSSHExecHelper is an owned test ssh: it records its exact argv and then
4953 // re-executes this test binary as the named hidden mux helper against an
50-// isolated remote sandbox. Its stdin/stdout remain the carriage pipes.
54+// isolated remote production XDG layout. Its stdin/stdout remain the carriage pipes.
5155 const fakeSSHExecHelper = `#!/bin/sh
5256 printf '%s\n' "$@" > "$` + fakeSSHArgsEnv + `"
53-exec "$` + fakeSSHBinEnv + `" "$` + fakeSSHModeEnv + `" --offline-root "$` + fakeSSHRootEnv + `"
57+export XDG_RUNTIME_DIR="$` + fakeSSHRuntimeEnv + `"
58+export XDG_STATE_HOME="$` + fakeSSHStateEnv + `"
59+export XDG_CONFIG_HOME="$` + fakeSSHConfigEnv + `"
60+exec "$` + fakeSSHBinEnv + `" "$` + fakeSSHModeEnv + `" --production
5461 `
5562
5663 // fakeSSHEmitReadiness prints one controlled readiness line and exits, so a
@@ -111,23 +118,42 @@ func installFakeSSH(t *testing.T, script string) string {
111118 // muxTestEnv isolates production XDG roots and records every detached mux
112119 // helper so no test leaks a process.
113120 type muxTestEnv struct {
114- t *testing.T
115- prodRuntime, prodState string
116- recordDir string
121+ t *testing.T
122+ recordDir string
117123 }
118124
119125 func newMuxTestEnv(t *testing.T) *muxTestEnv {
120126 t.Helper()
121- _, prodRuntime, prodState := isolateSandboxEnv(t)
127+ emptyProductionBrokerLayout(t, "")
122128 recordDir := filepath.Join(shortTempDir(t, "vevm"), "r")
123129 require.NoError(t, os.MkdirAll(recordDir, 0o700))
124130 t.Setenv(brokerHelperEnv, "1")
125131 t.Setenv(brokerHelperRecordDirEnv, recordDir)
126- env := &muxTestEnv{t: t, prodRuntime: prodRuntime, prodState: prodState, recordDir: recordDir}
132+ env := &muxTestEnv{t: t, recordDir: recordDir}
127133 t.Cleanup(env.cleanup)
128134 return env
129135 }
130136
137+// remoteMuxFixture runs the SSH-side mux helper with a distinct production
138+// XDG environment and a fixture listening at that environment's daemon path.
139+func remoteMuxFixture(t *testing.T, policy ports.BrokerPolicy) *brokerMuxFixture {
140+ t.Helper()
141+ localRuntime, localState, localConfig := os.Getenv("XDG_RUNTIME_DIR"), os.Getenv("XDG_STATE_HOME"), os.Getenv("XDG_CONFIG_HOME")
142+ remoteRuntime, remoteState, remoteConfig := shortTempDir(t, "vb"), shortTempDir(t, "vb"), shortTempDir(t, "vb")
143+ t.Setenv("XDG_RUNTIME_DIR", remoteRuntime)
144+ t.Setenv("XDG_STATE_HOME", remoteState)
145+ t.Setenv("XDG_CONFIG_HOME", remoteConfig)
146+ path := daemonmux.SocketPath(ipc.SocketDir())
147+ fixture := newBrokerMuxFixtureAt(t, policy, path)
148+ t.Setenv("XDG_RUNTIME_DIR", localRuntime)
149+ t.Setenv("XDG_STATE_HOME", localState)
150+ t.Setenv("XDG_CONFIG_HOME", localConfig)
151+ t.Setenv(fakeSSHRuntimeEnv, remoteRuntime)
152+ t.Setenv(fakeSSHStateEnv, remoteState)
153+ t.Setenv(fakeSSHConfigEnv, remoteConfig)
154+ return fixture
155+}
156+
131157 // cleanup kills every recorded mux helper process.
132158 func (e *muxTestEnv) cleanup() {
133159 for _, role := range []string{brokerMuxStdioCommand, brokerMuxQUICBootstrapCommand, brokerMuxQUICProxyCommand} {
@@ -148,17 +174,16 @@ func (e *muxTestEnv) cleanup() {
148174 }
149175 }
150176
151-// writeMuxRoot writes one marker-valid sandbox root carrying a single
152-// registration with the supplied route object.
153-func writeMuxRoot(t *testing.T, route any) string {
177+// writeMuxRoot provisions one pinned host route in this test's production
178+// broker.json and returns the production layout for its reader.
179+func writeMuxRoot(t *testing.T, route any) brokerconfig.Layout {
154180 t.Helper()
155- root := filepath.Join(shortTempDir(t, "vevx"), "s")
156- require.NoError(t, os.MkdirAll(root, 0o700))
157- writeSandboxConfig(t, root, sandboxRegistrationDocument(route))
158- return root
181+ layout := emptyProductionBrokerLayout(t, "")
182+ writeProductionBrokerDocument(t, sandboxRegistrationDocument(route))
183+ return layout
159184 }
160185
161-// loadTestRoute loads one sandbox configuration and returns the route its
186+// loadTestRoute loads one production broker configuration and returns the route its
162187 // resolver publishes, so a test can inspect a parsed route without the
163188 // unexported brokerconfig fields.
164189 func loadTestRoute(t *testing.T, route any) brokerconfig.Route {
@@ -167,15 +192,13 @@ func loadTestRoute(t *testing.T, route any) brokerconfig.Route {
167192 return parsed
168193 }
169194
170-// loadTestRouteAndConfig loads one sandbox configuration and returns both the
195+// loadTestRouteAndConfig loads one production broker configuration and returns both the
171196 // immutable configuration and the route its resolver publishes, so a test can
172197 // dial the route the way the broker does: with the whole resolved target.
173198 func loadTestRouteAndConfig(t *testing.T, route any) (*brokerconfig.Config, brokerconfig.Route) {
174199 t.Helper()
175- root := writeMuxRoot(t, route)
176- layout, err := offlineLayout(root)
177- require.NoError(t, err)
178- config, err := brokerconfig.Load(layout)
200+ layout := writeMuxRoot(t, route)
201+ config, err := brokerconfig.LoadProduction(layout, productionBrokerConfigPath(), "", localDaemonPolicy(), daemonmux.SocketPath(ipc.SocketDir()))
179202 require.NoError(t, err)
180203 resolved, err := config.Resolver().ResolveDialTarget(context.Background(), ports.BrokerOpenStreamRequest{
181204 Purpose: ports.BrokerStreamControl,
@@ -209,7 +232,7 @@ func testMuxDialTarget(t *testing.T, config *brokerconfig.Config, route brokerco
209232 return resolved
210233 }
211234
212-// loadTestRouteTarget loads one sandbox configuration and returns both the
235+// loadTestRouteTarget loads one production broker configuration and returns both the
213236 // parsed route and the exact resolved dial target the broker would publish for
214237 // it, so a test can call dialBrokerRoute exactly as the pool does.
215238 func loadTestRouteTarget(t *testing.T, route any) (brokerconfig.Route, ports.BrokerDialTarget) {
@@ -226,17 +249,14 @@ func TestParseBrokerMuxArgs(t *testing.T) {
226249 wantErr string
227250 want brokerMuxOptions
228251 }{
229- {name: "valid", args: []string{"--offline-root", "/srv/sandbox"}, want: brokerMuxOptions{offlineRoot: "/srv/sandbox", startMode: ports.BrokerDaemonExistingOnly}},
230- {name: "explicit existing-only", args: []string{"--offline-root", "/srv/sandbox", brokerDaemonStartArg, "existing-only"}, want: brokerMuxOptions{offlineRoot: "/srv/sandbox", startMode: ports.BrokerDaemonExistingOnly}},
231- {name: "explicit if-needed", args: []string{"--offline-root", "/srv/sandbox", brokerDaemonStartArg, "if-needed"}, want: brokerMuxOptions{offlineRoot: "/srv/sandbox", startMode: ports.BrokerDaemonStartIfNeeded}},
232- {name: "missing root", args: nil, wantErr: "requires --offline-root"},
233- {name: "empty root", args: []string{"--offline-root", ""}, wantErr: "requires a path"},
234- {name: "duplicate root", args: []string{"--offline-root", "/a", "--offline-root", "/b"}, wantErr: "duplicate"},
235- {name: "unknown flag", args: []string{"--idle-grace", "1m"}, wantErr: "unknown flag"},
236- {name: "positional", args: []string{"--offline-root", "/a", "extra"}, wantErr: "positional"},
237- {name: "missing daemon-start value", args: []string{"--offline-root", "/a", brokerDaemonStartArg}, wantErr: "requires a value"},
238- {name: "duplicate daemon-start", args: []string{"--offline-root", "/a", brokerDaemonStartArg, "if-needed", brokerDaemonStartArg, "existing-only"}, wantErr: "duplicate"},
239- {name: "unknown daemon-start", args: []string{"--offline-root", "/a", brokerDaemonStartArg, "always"}, wantErr: "unknown daemon start mode"},
252+ {name: "valid", args: []string{"--production"}, want: brokerMuxOptions{production: true, startMode: ports.BrokerDaemonExistingOnly}},
253+ {name: "explicit existing-only", args: []string{"--production", brokerDaemonStartArg, "existing-only"}, want: brokerMuxOptions{production: true, startMode: ports.BrokerDaemonExistingOnly}},
254+ {name: "explicit if-needed", args: []string{"--production", brokerDaemonStartArg, "if-needed"}, want: brokerMuxOptions{production: true, startMode: ports.BrokerDaemonStartIfNeeded}},
255+ {name: "unknown flag", args: []string{"--production", "--idle-grace", "1m"}, wantErr: "unknown flag"},
256+ {name: "positional", args: []string{"--production", "extra"}, wantErr: "positional"},
257+ {name: "missing daemon-start value", args: []string{"--production", brokerDaemonStartArg}, wantErr: "requires a value"},
258+ {name: "duplicate daemon-start", args: []string{"--production", brokerDaemonStartArg, "if-needed", brokerDaemonStartArg, "existing-only"}, wantErr: "duplicate"},
259+ {name: "unknown daemon-start", args: []string{"--production", brokerDaemonStartArg, "always"}, wantErr: "unknown daemon start mode"},
240260 }
241261 for _, tt := range tests {
242262 t.Run(tt.name, func(t *testing.T) {
@@ -264,10 +284,10 @@ func TestBrokerMuxHelpersHiddenFromPublicHelp(t *testing.T) {
264284 {brokerMuxQUICProxyCommand, kindBrokerMuxQUICProxy},
265285 } {
266286 require.NotContains(t, usageText, tt.name)
267- command, err := parseArgs([]string{tt.name, "--offline-root", "/srv/sandbox"})
287+ command, err := parseArgs([]string{tt.name, "--production"})
268288 require.NoError(t, err)
269289 require.Equal(t, tt.kind, command.kind)
270- require.Equal(t, "/srv/sandbox", command.brokerMux.offlineRoot)
290+ require.True(t, command.brokerMux.production)
271291 }
272292 // Ordinary commands are untouched by the new hidden entries.
273293 attach, err := parseArgs(nil)
@@ -282,11 +302,11 @@ func TestBrokerMuxHelpersHiddenFromPublicHelp(t *testing.T) {
282302 // the option terminator, and the quoted remote argv, splices only the explicit
283303 // trust inputs, and never disables host-key verification.
284304 func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {
285- isolateSandboxEnv(t)
305+ emptyProductionBrokerLayout(t, "")
286306 route := loadTestRoute(t, map[string]any{
287307 "kind": "ssh-stdio",
288308 "target": "user@host:2222",
289- "argv": []any{"vev", brokerMuxStdioCommand, "--offline-root", "/srv/remote"},
309+ "argv": []any{"vev", brokerMuxStdioCommand, "--production"},
290310 "trust": map[string]any{"knownHostsFile": "/etc/ssh/known_hosts", "connectTimeout": "30s"},
291311 })
292312 spec, err := sshMuxCommandSpec(route, ports.BrokerDaemonStartIfNeeded)
@@ -314,7 +334,7 @@ func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {
314334 plain := loadTestRoute(t, map[string]any{
315335 "kind": "ssh-quic",
316336 "target": "host",
317- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},
337+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
318338 })
319339 plainSpec, err := sshMuxCommandSpec(plain, ports.BrokerDaemonExistingOnly)
320340 require.NoError(t, err)
@@ -327,11 +347,11 @@ func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {
327347 // unreadable start authorization: an unknown mode is refused instead of
328348 // defaulting the helper to a permissive one.
329349 func TestSSHMuxCommandSpecRefusesUnknownStartMode(t *testing.T) {
330- isolateSandboxEnv(t)
350+ emptyProductionBrokerLayout(t, "")
331351 route := loadTestRoute(t, map[string]any{
332352 "kind": "ssh-stdio",
333353 "target": "host",
334- "argv": []any{"vev", brokerMuxStdioCommand, "--offline-root", "/srv/remote"},
354+ "argv": []any{"vev", brokerMuxStdioCommand, "--production"},
335355 })
336356 _, err := sshMuxCommandSpec(route, ports.BrokerDaemonStartMode(0))
337357 require.Error(t, err)
@@ -340,17 +360,17 @@ func TestSSHMuxCommandSpecRefusesUnknownStartMode(t *testing.T) {
340360 // TestSSHMuxCommandSpecTargetQuotesSpacesInsideArgv proves a remote argv word
341361 // with a space stays one quoted word and never becomes a second option.
342362 func TestSSHMuxCommandSpecTargetQuotesSpacesInsideArgv(t *testing.T) {
343- isolateSandboxEnv(t)
363+ emptyProductionBrokerLayout(t, "")
344364 route := loadTestRoute(t, map[string]any{
345365 "kind": "ssh-stdio",
346366 "target": "host",
347- "argv": []any{"vev", "_broker-mux-stdio", "--offline-root", "/srv/with space"},
367+ "argv": []any{"vev", "_broker-mux-stdio", "--production", "with space"},
348368 })
349369 spec, err := sshMuxCommandSpec(route, ports.BrokerDaemonExistingOnly)
350370 require.NoError(t, err)
351371 // The whole remote command stays one quoted argv word, so the space-bearing
352372 // path is still one word and never becomes a second option.
353- require.Contains(t, spec.Args[len(spec.Args)-1], `'/srv/with space'`)
373+ require.Contains(t, spec.Args[len(spec.Args)-1], `'with space'`)
354374 require.Contains(t, spec.Args[len(spec.Args)-1], "'"+brokerDaemonStartArg+"' 'existing-only'")
355375 }
356376
@@ -382,9 +402,9 @@ func TestBrokerQUICPeerAddr(t *testing.T) {
382402 }
383403
384404 func TestBrokerMuxHelperReturnsTypedNoDaemonExit(t *testing.T) {
385- isolateSandboxEnv(t)
386- root := writeMuxRoot(t, map[string]any{"kind": "unix", "path": filepath.Join(t.TempDir(), "missing-mux.sock")})
387- parsed, err := parseBrokerMuxArgs(brokerMuxStdioCommand, kindBrokerMuxStdio, []string{"--offline-root", root})
405+ emptyProductionBrokerLayout(t, "")
406+ emptyProductionBrokerLayout(t, "")
407+ parsed, err := parseBrokerMuxArgs(brokerMuxStdioCommand, kindBrokerMuxStdio, []string{"--production"})
388408 require.NoError(t, err)
389409 err = runBrokerMuxStdioCommand(context.Background(), parsed.brokerMux)
390410 var coded *exitCoded
@@ -395,11 +415,9 @@ func TestBrokerMuxHelperReturnsTypedNoDaemonExit(t *testing.T) {
395415 // TestBrokerMuxConnectorRejectsUnknownAddress proves the transport selector
396416 // refuses any address the immutable configuration did not produce.
397417 func TestBrokerMuxConnectorRejectsUnknownAddress(t *testing.T) {
398- isolateSandboxEnv(t)
399- root := writeMuxRoot(t, map[string]any{"kind": "unix", "path": "/tmp/unused-mux.sock"})
400- layout, err := offlineLayout(root)
401- require.NoError(t, err)
402- config, err := brokerconfig.Load(layout)
418+ emptyProductionBrokerLayout(t, "")
419+ layout := writeMuxRoot(t, map[string]any{"kind": "unix", "path": "/tmp/unused-mux.sock"})
420+ config, err := brokerconfig.LoadProduction(layout, productionBrokerConfigPath(), "", localDaemonPolicy(), daemonmux.SocketPath(ipc.SocketDir()))
403421 require.NoError(t, err)
404422 connector, err := brokerMuxConnector(config, slog.New(slog.NewTextHandler(io.Discard, nil)))
405423 require.NoError(t, err)
@@ -415,70 +433,62 @@ func TestBrokerMuxConnectorRejectsUnknownAddress(t *testing.T) {
415433 // stdio route: the broker dials the fake ssh child, the hidden helper bridges
416434 // its stdio to a real unix daemonmux fixture, and a typed Ping returns a Pong.
417435 func TestBrokerServeSSHStdioRouteRoundTrip(t *testing.T) {
418- env := newMuxTestEnv(t)
436+ newMuxTestEnv(t)
419437 policy := brokerTestPolicy()
420- fixture := newBrokerMuxFixture(t, policy)
421- remoteRoot := writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
438+ fixture := remoteMuxFixture(t, policy)
422439 argsFile := installFakeSSH(t, fakeSSHExecHelper)
423440 t.Setenv(fakeSSHModeEnv, brokerMuxStdioCommand)
424- t.Setenv(fakeSSHRootEnv, remoteRoot)
425- localRoot := writeMuxRoot(t, map[string]any{
441+ writeMuxRoot(t, map[string]any{
426442 "kind": "ssh-stdio",
427443 "target": "user@muxhost:2222",
428- "argv": []any{"vev", brokerMuxStdioCommand, "--offline-root", remoteRoot},
429- "trust": map[string]any{"knownHostsFile": "/etc/ssh/known_hosts", "connectTimeout": "5s"},
444+ "argv": []any{"vev", brokerMuxStdioCommand, "--production"},
430445 })
431446
432- socketPath, stop := startMuxBrokerServe(t, localRoot)
447+ socketPath, stop := startMuxBrokerServe(t)
433448 defer stop()
434449 requireBrokerPing(t, socketPath)
435450 require.Positive(t, fixture.streams.Load())
436451
437- // The exact ssh argv was built by BuildCommandForMux plus the trust inputs.
452+ // The exact ssh argv was built by BuildCommandForMux with OpenSSH trust policy.
438453 argv := readFileString(t, argsFile)
439454 require.Contains(t, argv, "-T\n")
440455 require.Contains(t, argv, "--\nuser@muxhost:2222\n")
441456 require.Contains(t, argv, brokerMuxStdioCommand)
442- require.Contains(t, argv, "UserKnownHostsFile=/etc/ssh/known_hosts")
443- require.Contains(t, argv, "ConnectTimeout=5")
457+ require.NotContains(t, argv, "UserKnownHostsFile=")
444458 require.NotContains(t, argv, "StrictHostKeyChecking")
445459 require.NotContains(t, argv, "BatchMode")
446460
447461 stop()
448- env.requireProductionUntouched(t)
449462 }
450463
451464 // TestBrokerServeSSHQUICRouteRoundTrip drives the full broker path over an
452465 // SSH-authenticated QUIC route with a real loopback QUIC server and a real
453466 // one-time credential.
454467 func TestBrokerServeSSHQUICRouteRoundTrip(t *testing.T) {
455- env := newMuxTestEnv(t)
468+ newMuxTestEnv(t)
456469 policy := brokerTestPolicy()
457- fixture := newBrokerMuxFixture(t, policy)
458- remoteRoot := writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
470+ fixture := remoteMuxFixture(t, policy)
459471 installFakeSSH(t, fakeSSHExecHelper)
460472 t.Setenv(fakeSSHModeEnv, brokerMuxQUICBootstrapCommand)
461- t.Setenv(fakeSSHRootEnv, remoteRoot)
462- localRoot := writeMuxRoot(t, map[string]any{
473+ writeMuxRoot(t, map[string]any{
463474 "kind": "ssh-quic",
464475 "target": "127.0.0.1",
465- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", remoteRoot},
476+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
466477 })
467478
468- socketPath, stop := startMuxBrokerServe(t, localRoot)
479+ socketPath, stop := startMuxBrokerServe(t)
469480 defer stop()
470481 requireBrokerPing(t, socketPath)
471482 require.Positive(t, fixture.streams.Load())
472483
473484 stop()
474- env.requireProductionUntouched(t)
475485 }
476486
477487 // TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret proves the pinned dial
478488 // fails closed on a wrong certificate pin and that the one-time credential
479489 // never appears in the returned error.
480490 func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {
481- isolateSandboxEnv(t)
491+ emptyProductionBrokerLayout(t, "")
482492 installFakeSSH(t, fakeSSHEmitReadiness)
483493
484494 server, readiness, err := quic.NewServer()
@@ -492,7 +502,7 @@ func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {
492502 route, target := loadTestRouteTarget(t, map[string]any{
493503 "kind": "ssh-quic",
494504 "target": "127.0.0.1",
495- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},
505+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
496506 })
497507 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
498508 defer cancel()
@@ -504,7 +514,7 @@ func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {
504514 // TestBrokerMuxQUICRejectsExpiredReadiness proves client-side parsing refuses
505515 // an implausibly old credential before dialing and never echoes its secret.
506516 func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {
507- isolateSandboxEnv(t)
517+ emptyProductionBrokerLayout(t, "")
508518 installFakeSSH(t, fakeSSHEmitReadiness)
509519
510520 token := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("A", 32)))
@@ -522,7 +532,7 @@ func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {
522532 route, target := loadTestRouteTarget(t, map[string]any{
523533 "kind": "ssh-quic",
524534 "target": "127.0.0.1",
525- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},
535+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
526536 })
527537 _, err := dialBrokerRoute(context.Background(), route, target, slog.New(slog.NewTextHandler(io.Discard, nil)))
528538 require.Error(t, err)
@@ -534,7 +544,7 @@ func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {
534544 // the bootstrap wait, a cancellation returns promptly, and the bootstrap child
535545 // is killed and reaped rather than leaked.
536546 func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {
537- isolateSandboxEnv(t)
547+ emptyProductionBrokerLayout(t, "")
538548 installFakeSSH(t, fakeSSHSleep)
539549 pidFile := filepath.Join(t.TempDir(), "ssh.pid")
540550 t.Setenv(fakeSSHPIDEnv, pidFile)
@@ -542,7 +552,7 @@ func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {
542552 route, target := loadTestRouteTarget(t, map[string]any{
543553 "kind": "ssh-quic",
544554 "target": "127.0.0.1",
545- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},
555+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
546556 })
547557 ctx, cancel := context.WithTimeout(context.Background(), 150*time.Millisecond)
548558 defer cancel()
@@ -562,7 +572,7 @@ func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {
562572 // under -race with -count>1, this fails if the os/exec copy goroutine is ever
563573 // observed while it is still writing the sink.
564574 func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {
565- isolateSandboxEnv(t)
575+ emptyProductionBrokerLayout(t, "")
566576 installFakeSSH(t, fakeSSHFloodStderr)
567577 pidFile := filepath.Join(t.TempDir(), "ssh.pid")
568578 t.Setenv(fakeSSHPIDEnv, pidFile)
@@ -570,7 +580,7 @@ func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {
570580 route, target := loadTestRouteTarget(t, map[string]any{
571581 "kind": "ssh-quic",
572582 "target": "127.0.0.1",
573- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},
583+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
574584 })
575585
576586 var logs bytes.Buffer
@@ -602,7 +612,7 @@ func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {
602612 // bound, and its child is killed and reaped. It is deterministic because the
603613 // effective bound is narrowed to a test value instead of the production one.
604614 func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {
605- isolateSandboxEnv(t)
615+ emptyProductionBrokerLayout(t, "")
606616 installFakeSSH(t, fakeSSHStallNeverReady)
607617 pidFile := filepath.Join(t.TempDir(), "ssh.pid")
608618 t.Setenv(fakeSSHPIDEnv, pidFile)
@@ -614,7 +624,7 @@ func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {
614624 route, target := loadTestRouteTarget(t, map[string]any{
615625 "kind": "ssh-quic",
616626 "target": "127.0.0.1",
617- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},
627+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
618628 })
619629 start := time.Now()
620630 _, err := dialBrokerRoute(context.Background(), route, target, slog.New(slog.NewTextHandler(io.Discard, nil)))
@@ -631,26 +641,25 @@ func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {
631641 // TestBrokerServeUnixRouteRoundTrip proves the transport selector also handles
632642 // the explicit unix route variant, not just the legacy path string.
633643 func TestBrokerServeUnixRouteRoundTrip(t *testing.T) {
634- env := newMuxTestEnv(t)
644+ newMuxTestEnv(t)
635645 fixture := newBrokerMuxFixture(t, brokerTestPolicy())
636- localRoot := writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
646+ writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
637647
638- socketPath, stop := startMuxBrokerServe(t, localRoot)
648+ socketPath, stop := startMuxBrokerServe(t)
639649 defer stop()
640650 requireBrokerPing(t, socketPath)
641651 require.Positive(t, fixture.streams.Load())
642652
643653 stop()
644- env.requireProductionUntouched(t)
645654 }
646655
647-// startMuxBrokerServe starts one offline broker over localRoot and returns its
656+// startMuxBrokerServe starts one production broker and returns its
648657 // socket path plus an idempotent stop.
649-func startMuxBrokerServe(t *testing.T, localRoot string) (string, func()) {
658+func startMuxBrokerServe(t *testing.T) (string, func()) {
650659 t.Helper()
651660 deps, ready := testBrokerServeDeps(newSandboxClock())
652661 ctx, cancel := context.WithCancel(context.Background())
653- done := runSandbox(ctx, brokerServeOptions{offlineRoot: localRoot}, deps)
662+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
654663 socketPath := awaitSandboxReady(t, ready, done)
655664 var once bool
656665 stop := func() {
@@ -720,18 +729,6 @@ func requireBrokerErrorHasNoReadiness(t *testing.T, err error, readiness quic.Re
720729 require.NotContains(t, message, "nonce")
721730 }
722731
723-// requireProductionUntouched asserts no production runtime or state entry was
724-// created by the composition or its helpers.
725-func (e *muxTestEnv) requireProductionUntouched(t *testing.T) {
726- t.Helper()
727- requireProductionUntouched(t, e.prodRuntime, e.prodState)
728- entries, err := os.ReadDir(e.prodRuntime)
729- require.NoError(t, err)
730- for _, entry := range entries {
731- require.NotContains(t, entry.Name(), "daemon.sock", "helpers must never start an ordinary daemon")
732- }
733-}
734-
735732 func mustJSON(t *testing.T, value any) []byte {
736733 t.Helper()
737734 raw, err := json.Marshal(value)
@@ -21,6 +21,8 @@ import (
21 21
22 "github.com/bnema/vev/internal/adapters/brokerconfig"22 "github.com/bnema/vev/internal/adapters/brokerconfig"
23 "github.com/bnema/vev/internal/adapters/brokeripc"23 "github.com/bnema/vev/internal/adapters/brokeripc"
24+ "github.com/bnema/vev/internal/adapters/daemonmux"
25+ "github.com/bnema/vev/internal/adapters/ipc"
24 "github.com/bnema/vev/internal/adapters/quic"26 "github.com/bnema/vev/internal/adapters/quic"
25 "github.com/bnema/vev/internal/adapters/sshstdio"27 "github.com/bnema/vev/internal/adapters/sshstdio"
26 "github.com/bnema/vev/internal/ports"28 "github.com/bnema/vev/internal/ports"
@@ -37,20 +39,25 @@ import (
37 // round trip proves pin, token, nonce, and daemonmux handshake all compose.39 // round trip proves pin, token, nonce, and daemonmux handshake all compose.
38 40
39 const (41 const (
40- fakeSSHArgsEnv = "VEV_TEST_SSH_ARGS"42+ fakeSSHArgsEnv = "VEV_TEST_SSH_ARGS"
41- fakeSSHReadyEnv = "VEV_TEST_SSH_READY"43+ fakeSSHReadyEnv = "VEV_TEST_SSH_READY"
42- fakeSSHPIDEnv = "VEV_TEST_SSH_PID"44+ fakeSSHPIDEnv = "VEV_TEST_SSH_PID"
43- fakeSSHBinEnv = "VEV_TEST_SSH_BIN"45+ fakeSSHBinEnv = "VEV_TEST_SSH_BIN"
44- fakeSSHModeEnv = "VEV_TEST_SSH_MODE"46+ fakeSSHModeEnv = "VEV_TEST_SSH_MODE"
45- fakeSSHRootEnv = "VEV_TEST_SSH_REMOTE_ROOT"47+ fakeSSHRuntimeEnv = "VEV_TEST_SSH_REMOTE_RUNTIME"
48+ fakeSSHStateEnv = "VEV_TEST_SSH_REMOTE_STATE"
49+ fakeSSHConfigEnv = "VEV_TEST_SSH_REMOTE_CONFIG"
46 )50 )
47 51
48 // fakeSSHExecHelper is an owned test ssh: it records its exact argv and then52 // fakeSSHExecHelper is an owned test ssh: it records its exact argv and then
49 // re-executes this test binary as the named hidden mux helper against an53 // re-executes this test binary as the named hidden mux helper against an
50-// isolated remote sandbox. Its stdin/stdout remain the carriage pipes.54+// isolated remote production XDG layout. Its stdin/stdout remain the carriage pipes.
51 const fakeSSHExecHelper = `#!/bin/sh55 const fakeSSHExecHelper = `#!/bin/sh
52 printf '%s\n' "$@" > "$` + fakeSSHArgsEnv + `"56 printf '%s\n' "$@" > "$` + fakeSSHArgsEnv + `"
53-exec "$` + fakeSSHBinEnv + `" "$` + fakeSSHModeEnv + `" --offline-root "$` + fakeSSHRootEnv + `"57+export XDG_RUNTIME_DIR="$` + fakeSSHRuntimeEnv + `"
58+export XDG_STATE_HOME="$` + fakeSSHStateEnv + `"
59+export XDG_CONFIG_HOME="$` + fakeSSHConfigEnv + `"
60+exec "$` + fakeSSHBinEnv + `" "$` + fakeSSHModeEnv + `" --production
54 `61 `
55 62
56 // fakeSSHEmitReadiness prints one controlled readiness line and exits, so a63 // fakeSSHEmitReadiness prints one controlled readiness line and exits, so a
@@ -111,23 +118,42 @@ func installFakeSSH(t *testing.T, script string) string {
111 // muxTestEnv isolates production XDG roots and records every detached mux118 // muxTestEnv isolates production XDG roots and records every detached mux
112 // helper so no test leaks a process.119 // helper so no test leaks a process.
113 type muxTestEnv struct {120 type muxTestEnv struct {
114- t *testing.T121+ t *testing.T
115- prodRuntime, prodState string122+ recordDir string
116- recordDir string
117 }123 }
118 124
119 func newMuxTestEnv(t *testing.T) *muxTestEnv {125 func newMuxTestEnv(t *testing.T) *muxTestEnv {
120 t.Helper()126 t.Helper()
121- _, prodRuntime, prodState := isolateSandboxEnv(t)127+ emptyProductionBrokerLayout(t, "")
122 recordDir := filepath.Join(shortTempDir(t, "vevm"), "r")128 recordDir := filepath.Join(shortTempDir(t, "vevm"), "r")
123 require.NoError(t, os.MkdirAll(recordDir, 0o700))129 require.NoError(t, os.MkdirAll(recordDir, 0o700))
124 t.Setenv(brokerHelperEnv, "1")130 t.Setenv(brokerHelperEnv, "1")
125 t.Setenv(brokerHelperRecordDirEnv, recordDir)131 t.Setenv(brokerHelperRecordDirEnv, recordDir)
126- env := &muxTestEnv{t: t, prodRuntime: prodRuntime, prodState: prodState, recordDir: recordDir}132+ env := &muxTestEnv{t: t, recordDir: recordDir}
127 t.Cleanup(env.cleanup)133 t.Cleanup(env.cleanup)
128 return env134 return env
129 }135 }
130 136
137+// remoteMuxFixture runs the SSH-side mux helper with a distinct production
138+// XDG environment and a fixture listening at that environment's daemon path.
139+func remoteMuxFixture(t *testing.T, policy ports.BrokerPolicy) *brokerMuxFixture {
140+ t.Helper()
141+ localRuntime, localState, localConfig := os.Getenv("XDG_RUNTIME_DIR"), os.Getenv("XDG_STATE_HOME"), os.Getenv("XDG_CONFIG_HOME")
142+ remoteRuntime, remoteState, remoteConfig := shortTempDir(t, "vb"), shortTempDir(t, "vb"), shortTempDir(t, "vb")
143+ t.Setenv("XDG_RUNTIME_DIR", remoteRuntime)
144+ t.Setenv("XDG_STATE_HOME", remoteState)
145+ t.Setenv("XDG_CONFIG_HOME", remoteConfig)
146+ path := daemonmux.SocketPath(ipc.SocketDir())
147+ fixture := newBrokerMuxFixtureAt(t, policy, path)
148+ t.Setenv("XDG_RUNTIME_DIR", localRuntime)
149+ t.Setenv("XDG_STATE_HOME", localState)
150+ t.Setenv("XDG_CONFIG_HOME", localConfig)
151+ t.Setenv(fakeSSHRuntimeEnv, remoteRuntime)
152+ t.Setenv(fakeSSHStateEnv, remoteState)
153+ t.Setenv(fakeSSHConfigEnv, remoteConfig)
154+ return fixture
155+}
156+
131 // cleanup kills every recorded mux helper process.157 // cleanup kills every recorded mux helper process.
132 func (e *muxTestEnv) cleanup() {158 func (e *muxTestEnv) cleanup() {
133 for _, role := range []string{brokerMuxStdioCommand, brokerMuxQUICBootstrapCommand, brokerMuxQUICProxyCommand} {159 for _, role := range []string{brokerMuxStdioCommand, brokerMuxQUICBootstrapCommand, brokerMuxQUICProxyCommand} {
@@ -148,17 +174,16 @@ func (e *muxTestEnv) cleanup() {
148 }174 }
149 }175 }
150 176
151-// writeMuxRoot writes one marker-valid sandbox root carrying a single177+// writeMuxRoot provisions one pinned host route in this test's production
152-// registration with the supplied route object.178+// broker.json and returns the production layout for its reader.
153-func writeMuxRoot(t *testing.T, route any) string {179+func writeMuxRoot(t *testing.T, route any) brokerconfig.Layout {
154 t.Helper()180 t.Helper()
155- root := filepath.Join(shortTempDir(t, "vevx"), "s")181+ layout := emptyProductionBrokerLayout(t, "")
156- require.NoError(t, os.MkdirAll(root, 0o700))182+ writeProductionBrokerDocument(t, sandboxRegistrationDocument(route))
157- writeSandboxConfig(t, root, sandboxRegistrationDocument(route))183+ return layout
158- return root
159 }184 }
160 185
161-// loadTestRoute loads one sandbox configuration and returns the route its186+// loadTestRoute loads one production broker configuration and returns the route its
162 // resolver publishes, so a test can inspect a parsed route without the187 // resolver publishes, so a test can inspect a parsed route without the
163 // unexported brokerconfig fields.188 // unexported brokerconfig fields.
164 func loadTestRoute(t *testing.T, route any) brokerconfig.Route {189 func loadTestRoute(t *testing.T, route any) brokerconfig.Route {
@@ -167,15 +192,13 @@ func loadTestRoute(t *testing.T, route any) brokerconfig.Route {
167 return parsed192 return parsed
168 }193 }
169 194
170-// loadTestRouteAndConfig loads one sandbox configuration and returns both the195+// loadTestRouteAndConfig loads one production broker configuration and returns both the
171 // immutable configuration and the route its resolver publishes, so a test can196 // immutable configuration and the route its resolver publishes, so a test can
172 // dial the route the way the broker does: with the whole resolved target.197 // dial the route the way the broker does: with the whole resolved target.
173 func loadTestRouteAndConfig(t *testing.T, route any) (*brokerconfig.Config, brokerconfig.Route) {198 func loadTestRouteAndConfig(t *testing.T, route any) (*brokerconfig.Config, brokerconfig.Route) {
174 t.Helper()199 t.Helper()
175- root := writeMuxRoot(t, route)200+ layout := writeMuxRoot(t, route)
176- layout, err := offlineLayout(root)201+ config, err := brokerconfig.LoadProduction(layout, productionBrokerConfigPath(), "", localDaemonPolicy(), daemonmux.SocketPath(ipc.SocketDir()))
177- require.NoError(t, err)
178- config, err := brokerconfig.Load(layout)
179 require.NoError(t, err)202 require.NoError(t, err)
180 resolved, err := config.Resolver().ResolveDialTarget(context.Background(), ports.BrokerOpenStreamRequest{203 resolved, err := config.Resolver().ResolveDialTarget(context.Background(), ports.BrokerOpenStreamRequest{
181 Purpose: ports.BrokerStreamControl,204 Purpose: ports.BrokerStreamControl,
@@ -209,7 +232,7 @@ func testMuxDialTarget(t *testing.T, config *brokerconfig.Config, route brokerco
209 return resolved232 return resolved
210 }233 }
211 234
212-// loadTestRouteTarget loads one sandbox configuration and returns both the235+// loadTestRouteTarget loads one production broker configuration and returns both the
213 // parsed route and the exact resolved dial target the broker would publish for236 // parsed route and the exact resolved dial target the broker would publish for
214 // it, so a test can call dialBrokerRoute exactly as the pool does.237 // it, so a test can call dialBrokerRoute exactly as the pool does.
215 func loadTestRouteTarget(t *testing.T, route any) (brokerconfig.Route, ports.BrokerDialTarget) {238 func loadTestRouteTarget(t *testing.T, route any) (brokerconfig.Route, ports.BrokerDialTarget) {
@@ -226,17 +249,14 @@ func TestParseBrokerMuxArgs(t *testing.T) {
226 wantErr string249 wantErr string
227 want brokerMuxOptions250 want brokerMuxOptions
228 }{251 }{
229- {name: "valid", args: []string{"--offline-root", "/srv/sandbox"}, want: brokerMuxOptions{offlineRoot: "/srv/sandbox", startMode: ports.BrokerDaemonExistingOnly}},252+ {name: "valid", args: []string{"--production"}, want: brokerMuxOptions{production: true, startMode: ports.BrokerDaemonExistingOnly}},
230- {name: "explicit existing-only", args: []string{"--offline-root", "/srv/sandbox", brokerDaemonStartArg, "existing-only"}, want: brokerMuxOptions{offlineRoot: "/srv/sandbox", startMode: ports.BrokerDaemonExistingOnly}},253+ {name: "explicit existing-only", args: []string{"--production", brokerDaemonStartArg, "existing-only"}, want: brokerMuxOptions{production: true, startMode: ports.BrokerDaemonExistingOnly}},
231- {name: "explicit if-needed", args: []string{"--offline-root", "/srv/sandbox", brokerDaemonStartArg, "if-needed"}, want: brokerMuxOptions{offlineRoot: "/srv/sandbox", startMode: ports.BrokerDaemonStartIfNeeded}},254+ {name: "explicit if-needed", args: []string{"--production", brokerDaemonStartArg, "if-needed"}, want: brokerMuxOptions{production: true, startMode: ports.BrokerDaemonStartIfNeeded}},
232- {name: "missing root", args: nil, wantErr: "requires --offline-root"},255+ {name: "unknown flag", args: []string{"--production", "--idle-grace", "1m"}, wantErr: "unknown flag"},
233- {name: "empty root", args: []string{"--offline-root", ""}, wantErr: "requires a path"},256+ {name: "positional", args: []string{"--production", "extra"}, wantErr: "positional"},
234- {name: "duplicate root", args: []string{"--offline-root", "/a", "--offline-root", "/b"}, wantErr: "duplicate"},257+ {name: "missing daemon-start value", args: []string{"--production", brokerDaemonStartArg}, wantErr: "requires a value"},
235- {name: "unknown flag", args: []string{"--idle-grace", "1m"}, wantErr: "unknown flag"},258+ {name: "duplicate daemon-start", args: []string{"--production", brokerDaemonStartArg, "if-needed", brokerDaemonStartArg, "existing-only"}, wantErr: "duplicate"},
236- {name: "positional", args: []string{"--offline-root", "/a", "extra"}, wantErr: "positional"},259+ {name: "unknown daemon-start", args: []string{"--production", brokerDaemonStartArg, "always"}, wantErr: "unknown daemon start mode"},
237- {name: "missing daemon-start value", args: []string{"--offline-root", "/a", brokerDaemonStartArg}, wantErr: "requires a value"},
238- {name: "duplicate daemon-start", args: []string{"--offline-root", "/a", brokerDaemonStartArg, "if-needed", brokerDaemonStartArg, "existing-only"}, wantErr: "duplicate"},
239- {name: "unknown daemon-start", args: []string{"--offline-root", "/a", brokerDaemonStartArg, "always"}, wantErr: "unknown daemon start mode"},
240 }260 }
241 for _, tt := range tests {261 for _, tt := range tests {
242 t.Run(tt.name, func(t *testing.T) {262 t.Run(tt.name, func(t *testing.T) {
@@ -264,10 +284,10 @@ func TestBrokerMuxHelpersHiddenFromPublicHelp(t *testing.T) {
264 {brokerMuxQUICProxyCommand, kindBrokerMuxQUICProxy},284 {brokerMuxQUICProxyCommand, kindBrokerMuxQUICProxy},
265 } {285 } {
266 require.NotContains(t, usageText, tt.name)286 require.NotContains(t, usageText, tt.name)
267- command, err := parseArgs([]string{tt.name, "--offline-root", "/srv/sandbox"})287+ command, err := parseArgs([]string{tt.name, "--production"})
268 require.NoError(t, err)288 require.NoError(t, err)
269 require.Equal(t, tt.kind, command.kind)289 require.Equal(t, tt.kind, command.kind)
270- require.Equal(t, "/srv/sandbox", command.brokerMux.offlineRoot)290+ require.True(t, command.brokerMux.production)
271 }291 }
272 // Ordinary commands are untouched by the new hidden entries.292 // Ordinary commands are untouched by the new hidden entries.
273 attach, err := parseArgs(nil)293 attach, err := parseArgs(nil)
@@ -282,11 +302,11 @@ func TestBrokerMuxHelpersHiddenFromPublicHelp(t *testing.T) {
282 // the option terminator, and the quoted remote argv, splices only the explicit302 // the option terminator, and the quoted remote argv, splices only the explicit
283 // trust inputs, and never disables host-key verification.303 // trust inputs, and never disables host-key verification.
284 func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {304 func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {
285- isolateSandboxEnv(t)305+ emptyProductionBrokerLayout(t, "")
286 route := loadTestRoute(t, map[string]any{306 route := loadTestRoute(t, map[string]any{
287 "kind": "ssh-stdio",307 "kind": "ssh-stdio",
288 "target": "user@host:2222",308 "target": "user@host:2222",
289- "argv": []any{"vev", brokerMuxStdioCommand, "--offline-root", "/srv/remote"},309+ "argv": []any{"vev", brokerMuxStdioCommand, "--production"},
290 "trust": map[string]any{"knownHostsFile": "/etc/ssh/known_hosts", "connectTimeout": "30s"},310 "trust": map[string]any{"knownHostsFile": "/etc/ssh/known_hosts", "connectTimeout": "30s"},
291 })311 })
292 spec, err := sshMuxCommandSpec(route, ports.BrokerDaemonStartIfNeeded)312 spec, err := sshMuxCommandSpec(route, ports.BrokerDaemonStartIfNeeded)
@@ -314,7 +334,7 @@ func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {
314 plain := loadTestRoute(t, map[string]any{334 plain := loadTestRoute(t, map[string]any{
315 "kind": "ssh-quic",335 "kind": "ssh-quic",
316 "target": "host",336 "target": "host",
317- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},337+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
318 })338 })
319 plainSpec, err := sshMuxCommandSpec(plain, ports.BrokerDaemonExistingOnly)339 plainSpec, err := sshMuxCommandSpec(plain, ports.BrokerDaemonExistingOnly)
320 require.NoError(t, err)340 require.NoError(t, err)
@@ -327,11 +347,11 @@ func TestSSHMuxCommandSpecPreservesTrustAndNoPTY(t *testing.T) {
327 // unreadable start authorization: an unknown mode is refused instead of347 // unreadable start authorization: an unknown mode is refused instead of
328 // defaulting the helper to a permissive one.348 // defaulting the helper to a permissive one.
329 func TestSSHMuxCommandSpecRefusesUnknownStartMode(t *testing.T) {349 func TestSSHMuxCommandSpecRefusesUnknownStartMode(t *testing.T) {
330- isolateSandboxEnv(t)350+ emptyProductionBrokerLayout(t, "")
331 route := loadTestRoute(t, map[string]any{351 route := loadTestRoute(t, map[string]any{
332 "kind": "ssh-stdio",352 "kind": "ssh-stdio",
333 "target": "host",353 "target": "host",
334- "argv": []any{"vev", brokerMuxStdioCommand, "--offline-root", "/srv/remote"},354+ "argv": []any{"vev", brokerMuxStdioCommand, "--production"},
335 })355 })
336 _, err := sshMuxCommandSpec(route, ports.BrokerDaemonStartMode(0))356 _, err := sshMuxCommandSpec(route, ports.BrokerDaemonStartMode(0))
337 require.Error(t, err)357 require.Error(t, err)
@@ -340,17 +360,17 @@ func TestSSHMuxCommandSpecRefusesUnknownStartMode(t *testing.T) {
340 // TestSSHMuxCommandSpecTargetQuotesSpacesInsideArgv proves a remote argv word360 // TestSSHMuxCommandSpecTargetQuotesSpacesInsideArgv proves a remote argv word
341 // with a space stays one quoted word and never becomes a second option.361 // with a space stays one quoted word and never becomes a second option.
342 func TestSSHMuxCommandSpecTargetQuotesSpacesInsideArgv(t *testing.T) {362 func TestSSHMuxCommandSpecTargetQuotesSpacesInsideArgv(t *testing.T) {
343- isolateSandboxEnv(t)363+ emptyProductionBrokerLayout(t, "")
344 route := loadTestRoute(t, map[string]any{364 route := loadTestRoute(t, map[string]any{
345 "kind": "ssh-stdio",365 "kind": "ssh-stdio",
346 "target": "host",366 "target": "host",
347- "argv": []any{"vev", "_broker-mux-stdio", "--offline-root", "/srv/with space"},367+ "argv": []any{"vev", "_broker-mux-stdio", "--production", "with space"},
348 })368 })
349 spec, err := sshMuxCommandSpec(route, ports.BrokerDaemonExistingOnly)369 spec, err := sshMuxCommandSpec(route, ports.BrokerDaemonExistingOnly)
350 require.NoError(t, err)370 require.NoError(t, err)
351 // The whole remote command stays one quoted argv word, so the space-bearing371 // The whole remote command stays one quoted argv word, so the space-bearing
352 // path is still one word and never becomes a second option.372 // path is still one word and never becomes a second option.
353- require.Contains(t, spec.Args[len(spec.Args)-1], `'/srv/with space'`)373+ require.Contains(t, spec.Args[len(spec.Args)-1], `'with space'`)
354 require.Contains(t, spec.Args[len(spec.Args)-1], "'"+brokerDaemonStartArg+"' 'existing-only'")374 require.Contains(t, spec.Args[len(spec.Args)-1], "'"+brokerDaemonStartArg+"' 'existing-only'")
355 }375 }
356 376
@@ -382,9 +402,9 @@ func TestBrokerQUICPeerAddr(t *testing.T) {
382 }402 }
383 403
384 func TestBrokerMuxHelperReturnsTypedNoDaemonExit(t *testing.T) {404 func TestBrokerMuxHelperReturnsTypedNoDaemonExit(t *testing.T) {
385- isolateSandboxEnv(t)405+ emptyProductionBrokerLayout(t, "")
386- root := writeMuxRoot(t, map[string]any{"kind": "unix", "path": filepath.Join(t.TempDir(), "missing-mux.sock")})406+ emptyProductionBrokerLayout(t, "")
387- parsed, err := parseBrokerMuxArgs(brokerMuxStdioCommand, kindBrokerMuxStdio, []string{"--offline-root", root})407+ parsed, err := parseBrokerMuxArgs(brokerMuxStdioCommand, kindBrokerMuxStdio, []string{"--production"})
388 require.NoError(t, err)408 require.NoError(t, err)
389 err = runBrokerMuxStdioCommand(context.Background(), parsed.brokerMux)409 err = runBrokerMuxStdioCommand(context.Background(), parsed.brokerMux)
390 var coded *exitCoded410 var coded *exitCoded
@@ -395,11 +415,9 @@ func TestBrokerMuxHelperReturnsTypedNoDaemonExit(t *testing.T) {
395 // TestBrokerMuxConnectorRejectsUnknownAddress proves the transport selector415 // TestBrokerMuxConnectorRejectsUnknownAddress proves the transport selector
396 // refuses any address the immutable configuration did not produce.416 // refuses any address the immutable configuration did not produce.
397 func TestBrokerMuxConnectorRejectsUnknownAddress(t *testing.T) {417 func TestBrokerMuxConnectorRejectsUnknownAddress(t *testing.T) {
398- isolateSandboxEnv(t)418+ emptyProductionBrokerLayout(t, "")
399- root := writeMuxRoot(t, map[string]any{"kind": "unix", "path": "/tmp/unused-mux.sock"})419+ layout := writeMuxRoot(t, map[string]any{"kind": "unix", "path": "/tmp/unused-mux.sock"})
400- layout, err := offlineLayout(root)420+ config, err := brokerconfig.LoadProduction(layout, productionBrokerConfigPath(), "", localDaemonPolicy(), daemonmux.SocketPath(ipc.SocketDir()))
401- require.NoError(t, err)
402- config, err := brokerconfig.Load(layout)
403 require.NoError(t, err)421 require.NoError(t, err)
404 connector, err := brokerMuxConnector(config, slog.New(slog.NewTextHandler(io.Discard, nil)))422 connector, err := brokerMuxConnector(config, slog.New(slog.NewTextHandler(io.Discard, nil)))
405 require.NoError(t, err)423 require.NoError(t, err)
@@ -415,70 +433,62 @@ func TestBrokerMuxConnectorRejectsUnknownAddress(t *testing.T) {
415 // stdio route: the broker dials the fake ssh child, the hidden helper bridges433 // stdio route: the broker dials the fake ssh child, the hidden helper bridges
416 // its stdio to a real unix daemonmux fixture, and a typed Ping returns a Pong.434 // its stdio to a real unix daemonmux fixture, and a typed Ping returns a Pong.
417 func TestBrokerServeSSHStdioRouteRoundTrip(t *testing.T) {435 func TestBrokerServeSSHStdioRouteRoundTrip(t *testing.T) {
418- env := newMuxTestEnv(t)436+ newMuxTestEnv(t)
419 policy := brokerTestPolicy()437 policy := brokerTestPolicy()
420- fixture := newBrokerMuxFixture(t, policy)438+ fixture := remoteMuxFixture(t, policy)
421- remoteRoot := writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
422 argsFile := installFakeSSH(t, fakeSSHExecHelper)439 argsFile := installFakeSSH(t, fakeSSHExecHelper)
423 t.Setenv(fakeSSHModeEnv, brokerMuxStdioCommand)440 t.Setenv(fakeSSHModeEnv, brokerMuxStdioCommand)
424- t.Setenv(fakeSSHRootEnv, remoteRoot)441+ writeMuxRoot(t, map[string]any{
425- localRoot := writeMuxRoot(t, map[string]any{
426 "kind": "ssh-stdio",442 "kind": "ssh-stdio",
427 "target": "user@muxhost:2222",443 "target": "user@muxhost:2222",
428- "argv": []any{"vev", brokerMuxStdioCommand, "--offline-root", remoteRoot},444+ "argv": []any{"vev", brokerMuxStdioCommand, "--production"},
429- "trust": map[string]any{"knownHostsFile": "/etc/ssh/known_hosts", "connectTimeout": "5s"},
430 })445 })
431 446
432- socketPath, stop := startMuxBrokerServe(t, localRoot)447+ socketPath, stop := startMuxBrokerServe(t)
433 defer stop()448 defer stop()
434 requireBrokerPing(t, socketPath)449 requireBrokerPing(t, socketPath)
435 require.Positive(t, fixture.streams.Load())450 require.Positive(t, fixture.streams.Load())
436 451
437- // The exact ssh argv was built by BuildCommandForMux plus the trust inputs.452+ // The exact ssh argv was built by BuildCommandForMux with OpenSSH trust policy.
438 argv := readFileString(t, argsFile)453 argv := readFileString(t, argsFile)
439 require.Contains(t, argv, "-T\n")454 require.Contains(t, argv, "-T\n")
440 require.Contains(t, argv, "--\nuser@muxhost:2222\n")455 require.Contains(t, argv, "--\nuser@muxhost:2222\n")
441 require.Contains(t, argv, brokerMuxStdioCommand)456 require.Contains(t, argv, brokerMuxStdioCommand)
442- require.Contains(t, argv, "UserKnownHostsFile=/etc/ssh/known_hosts")457+ require.NotContains(t, argv, "UserKnownHostsFile=")
443- require.Contains(t, argv, "ConnectTimeout=5")
444 require.NotContains(t, argv, "StrictHostKeyChecking")458 require.NotContains(t, argv, "StrictHostKeyChecking")
445 require.NotContains(t, argv, "BatchMode")459 require.NotContains(t, argv, "BatchMode")
446 460
447 stop()461 stop()
448- env.requireProductionUntouched(t)
449 }462 }
450 463
451 // TestBrokerServeSSHQUICRouteRoundTrip drives the full broker path over an464 // TestBrokerServeSSHQUICRouteRoundTrip drives the full broker path over an
452 // SSH-authenticated QUIC route with a real loopback QUIC server and a real465 // SSH-authenticated QUIC route with a real loopback QUIC server and a real
453 // one-time credential.466 // one-time credential.
454 func TestBrokerServeSSHQUICRouteRoundTrip(t *testing.T) {467 func TestBrokerServeSSHQUICRouteRoundTrip(t *testing.T) {
455- env := newMuxTestEnv(t)468+ newMuxTestEnv(t)
456 policy := brokerTestPolicy()469 policy := brokerTestPolicy()
457- fixture := newBrokerMuxFixture(t, policy)470+ fixture := remoteMuxFixture(t, policy)
458- remoteRoot := writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
459 installFakeSSH(t, fakeSSHExecHelper)471 installFakeSSH(t, fakeSSHExecHelper)
460 t.Setenv(fakeSSHModeEnv, brokerMuxQUICBootstrapCommand)472 t.Setenv(fakeSSHModeEnv, brokerMuxQUICBootstrapCommand)
461- t.Setenv(fakeSSHRootEnv, remoteRoot)473+ writeMuxRoot(t, map[string]any{
462- localRoot := writeMuxRoot(t, map[string]any{
463 "kind": "ssh-quic",474 "kind": "ssh-quic",
464 "target": "127.0.0.1",475 "target": "127.0.0.1",
465- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", remoteRoot},476+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
466 })477 })
467 478
468- socketPath, stop := startMuxBrokerServe(t, localRoot)479+ socketPath, stop := startMuxBrokerServe(t)
469 defer stop()480 defer stop()
470 requireBrokerPing(t, socketPath)481 requireBrokerPing(t, socketPath)
471 require.Positive(t, fixture.streams.Load())482 require.Positive(t, fixture.streams.Load())
472 483
473 stop()484 stop()
474- env.requireProductionUntouched(t)
475 }485 }
476 486
477 // TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret proves the pinned dial487 // TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret proves the pinned dial
478 // fails closed on a wrong certificate pin and that the one-time credential488 // fails closed on a wrong certificate pin and that the one-time credential
479 // never appears in the returned error.489 // never appears in the returned error.
480 func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {490 func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {
481- isolateSandboxEnv(t)491+ emptyProductionBrokerLayout(t, "")
482 installFakeSSH(t, fakeSSHEmitReadiness)492 installFakeSSH(t, fakeSSHEmitReadiness)
483 493
484 server, readiness, err := quic.NewServer()494 server, readiness, err := quic.NewServer()
@@ -492,7 +502,7 @@ func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {
492 route, target := loadTestRouteTarget(t, map[string]any{502 route, target := loadTestRouteTarget(t, map[string]any{
493 "kind": "ssh-quic",503 "kind": "ssh-quic",
494 "target": "127.0.0.1",504 "target": "127.0.0.1",
495- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},505+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
496 })506 })
497 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)507 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
498 defer cancel()508 defer cancel()
@@ -504,7 +514,7 @@ func TestBrokerMuxQUICRejectsBadPinWithoutLeakingSecret(t *testing.T) {
504 // TestBrokerMuxQUICRejectsExpiredReadiness proves client-side parsing refuses514 // TestBrokerMuxQUICRejectsExpiredReadiness proves client-side parsing refuses
505 // an implausibly old credential before dialing and never echoes its secret.515 // an implausibly old credential before dialing and never echoes its secret.
506 func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {516 func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {
507- isolateSandboxEnv(t)517+ emptyProductionBrokerLayout(t, "")
508 installFakeSSH(t, fakeSSHEmitReadiness)518 installFakeSSH(t, fakeSSHEmitReadiness)
509 519
510 token := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("A", 32)))520 token := base64.StdEncoding.EncodeToString([]byte(strings.Repeat("A", 32)))
@@ -522,7 +532,7 @@ func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {
522 route, target := loadTestRouteTarget(t, map[string]any{532 route, target := loadTestRouteTarget(t, map[string]any{
523 "kind": "ssh-quic",533 "kind": "ssh-quic",
524 "target": "127.0.0.1",534 "target": "127.0.0.1",
525- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},535+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
526 })536 })
527 _, err := dialBrokerRoute(context.Background(), route, target, slog.New(slog.NewTextHandler(io.Discard, nil)))537 _, err := dialBrokerRoute(context.Background(), route, target, slog.New(slog.NewTextHandler(io.Discard, nil)))
528 require.Error(t, err)538 require.Error(t, err)
@@ -534,7 +544,7 @@ func TestBrokerMuxQUICRejectsExpiredReadiness(t *testing.T) {
534 // the bootstrap wait, a cancellation returns promptly, and the bootstrap child544 // the bootstrap wait, a cancellation returns promptly, and the bootstrap child
535 // is killed and reaped rather than leaked.545 // is killed and reaped rather than leaked.
536 func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {546 func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {
537- isolateSandboxEnv(t)547+ emptyProductionBrokerLayout(t, "")
538 installFakeSSH(t, fakeSSHSleep)548 installFakeSSH(t, fakeSSHSleep)
539 pidFile := filepath.Join(t.TempDir(), "ssh.pid")549 pidFile := filepath.Join(t.TempDir(), "ssh.pid")
540 t.Setenv(fakeSSHPIDEnv, pidFile)550 t.Setenv(fakeSSHPIDEnv, pidFile)
@@ -542,7 +552,7 @@ func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {
542 route, target := loadTestRouteTarget(t, map[string]any{552 route, target := loadTestRouteTarget(t, map[string]any{
543 "kind": "ssh-quic",553 "kind": "ssh-quic",
544 "target": "127.0.0.1",554 "target": "127.0.0.1",
545- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},555+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
546 })556 })
547 ctx, cancel := context.WithTimeout(context.Background(), 150*time.Millisecond)557 ctx, cancel := context.WithTimeout(context.Background(), 150*time.Millisecond)
548 defer cancel()558 defer cancel()
@@ -562,7 +572,7 @@ func TestBrokerMuxDialCancellationReapsBootstrap(t *testing.T) {
562 // under -race with -count>1, this fails if the os/exec copy goroutine is ever572 // under -race with -count>1, this fails if the os/exec copy goroutine is ever
563 // observed while it is still writing the sink.573 // observed while it is still writing the sink.
564 func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {574 func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {
565- isolateSandboxEnv(t)575+ emptyProductionBrokerLayout(t, "")
566 installFakeSSH(t, fakeSSHFloodStderr)576 installFakeSSH(t, fakeSSHFloodStderr)
567 pidFile := filepath.Join(t.TempDir(), "ssh.pid")577 pidFile := filepath.Join(t.TempDir(), "ssh.pid")
568 t.Setenv(fakeSSHPIDEnv, pidFile)578 t.Setenv(fakeSSHPIDEnv, pidFile)
@@ -570,7 +580,7 @@ func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {
570 route, target := loadTestRouteTarget(t, map[string]any{580 route, target := loadTestRouteTarget(t, map[string]any{
571 "kind": "ssh-quic",581 "kind": "ssh-quic",
572 "target": "127.0.0.1",582 "target": "127.0.0.1",
573- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},583+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
574 })584 })
575 585
576 var logs bytes.Buffer586 var logs bytes.Buffer
@@ -602,7 +612,7 @@ func TestBrokerMuxDialFloodedStderrIsReapedAndSanitized(t *testing.T) {
602 // bound, and its child is killed and reaped. It is deterministic because the612 // bound, and its child is killed and reaped. It is deterministic because the
603 // effective bound is narrowed to a test value instead of the production one.613 // effective bound is narrowed to a test value instead of the production one.
604 func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {614 func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {
605- isolateSandboxEnv(t)615+ emptyProductionBrokerLayout(t, "")
606 installFakeSSH(t, fakeSSHStallNeverReady)616 installFakeSSH(t, fakeSSHStallNeverReady)
607 pidFile := filepath.Join(t.TempDir(), "ssh.pid")617 pidFile := filepath.Join(t.TempDir(), "ssh.pid")
608 t.Setenv(fakeSSHPIDEnv, pidFile)618 t.Setenv(fakeSSHPIDEnv, pidFile)
@@ -614,7 +624,7 @@ func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {
614 route, target := loadTestRouteTarget(t, map[string]any{624 route, target := loadTestRouteTarget(t, map[string]any{
615 "kind": "ssh-quic",625 "kind": "ssh-quic",
616 "target": "127.0.0.1",626 "target": "127.0.0.1",
617- "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--offline-root", "/srv/remote"},627+ "argv": []any{"vev", brokerMuxQUICBootstrapCommand, "--production"},
618 })628 })
619 start := time.Now()629 start := time.Now()
620 _, err := dialBrokerRoute(context.Background(), route, target, slog.New(slog.NewTextHandler(io.Discard, nil)))630 _, err := dialBrokerRoute(context.Background(), route, target, slog.New(slog.NewTextHandler(io.Discard, nil)))
@@ -631,26 +641,25 @@ func TestBrokerMuxDialStalledBootstrapUsesSetupTimeout(t *testing.T) {
631 // TestBrokerServeUnixRouteRoundTrip proves the transport selector also handles641 // TestBrokerServeUnixRouteRoundTrip proves the transport selector also handles
632 // the explicit unix route variant, not just the legacy path string.642 // the explicit unix route variant, not just the legacy path string.
633 func TestBrokerServeUnixRouteRoundTrip(t *testing.T) {643 func TestBrokerServeUnixRouteRoundTrip(t *testing.T) {
634- env := newMuxTestEnv(t)644+ newMuxTestEnv(t)
635 fixture := newBrokerMuxFixture(t, brokerTestPolicy())645 fixture := newBrokerMuxFixture(t, brokerTestPolicy())
636- localRoot := writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})646+ writeMuxRoot(t, map[string]any{"kind": "unix", "path": fixture.route})
637 647
638- socketPath, stop := startMuxBrokerServe(t, localRoot)648+ socketPath, stop := startMuxBrokerServe(t)
639 defer stop()649 defer stop()
640 requireBrokerPing(t, socketPath)650 requireBrokerPing(t, socketPath)
641 require.Positive(t, fixture.streams.Load())651 require.Positive(t, fixture.streams.Load())
642 652
643 stop()653 stop()
644- env.requireProductionUntouched(t)
645 }654 }
646 655
647-// startMuxBrokerServe starts one offline broker over localRoot and returns its656+// startMuxBrokerServe starts one production broker and returns its
648 // socket path plus an idempotent stop.657 // socket path plus an idempotent stop.
649-func startMuxBrokerServe(t *testing.T, localRoot string) (string, func()) {658+func startMuxBrokerServe(t *testing.T) (string, func()) {
650 t.Helper()659 t.Helper()
651 deps, ready := testBrokerServeDeps(newSandboxClock())660 deps, ready := testBrokerServeDeps(newSandboxClock())
652 ctx, cancel := context.WithCancel(context.Background())661 ctx, cancel := context.WithCancel(context.Background())
653- done := runSandbox(ctx, brokerServeOptions{offlineRoot: localRoot}, deps)662+ done := runSandbox(ctx, brokerServeOptions{production: true}, deps)
654 socketPath := awaitSandboxReady(t, ready, done)663 socketPath := awaitSandboxReady(t, ready, done)
655 var once bool664 var once bool
656 stop := func() {665 stop := func() {
@@ -720,18 +729,6 @@ func requireBrokerErrorHasNoReadiness(t *testing.T, err error, readiness quic.Re
720 require.NotContains(t, message, "nonce")729 require.NotContains(t, message, "nonce")
721 }730 }
722 731
723-// requireProductionUntouched asserts no production runtime or state entry was
724-// created by the composition or its helpers.
725-func (e *muxTestEnv) requireProductionUntouched(t *testing.T) {
726- t.Helper()
727- requireProductionUntouched(t, e.prodRuntime, e.prodState)
728- entries, err := os.ReadDir(e.prodRuntime)
729- require.NoError(t, err)
730- for _, entry := range entries {
731- require.NotContains(t, entry.Name(), "daemon.sock", "helpers must never start an ordinary daemon")
732- }
733-}
734-
735 func mustJSON(t *testing.T, value any) []byte {732 func mustJSON(t *testing.T, value any) []byte {
736 t.Helper()733 t.Helper()
737 raw, err := json.Marshal(value)734 raw, err := json.Marshal(value)
M internal/app/broker_offline_test.go +7 -1
@@ -478,7 +478,13 @@ func newBrokerMuxFixture(t *testing.T, policy ports.BrokerPolicy) *brokerMuxFixt
478478 t.Helper()
479479 routeDir := t.TempDir()
480480 require.NoError(t, os.Chmod(routeDir, 0o700))
481- route := filepath.Join(routeDir, "mux.sock")
481+ return newBrokerMuxFixtureAt(t, policy, filepath.Join(routeDir, "mux.sock"))
482+}
483+
484+// newBrokerMuxFixtureAt binds at a caller-chosen production daemonmux path.
485+func newBrokerMuxFixtureAt(t *testing.T, policy ports.BrokerPolicy, route string) *brokerMuxFixture {
486+ t.Helper()
487+ require.NoError(t, os.MkdirAll(filepath.Dir(route), 0o700))
482488 listener, err := ipc.ListenMux(route)
483489 require.NoError(t, err)
484490
@@ -478,7 +478,13 @@ func newBrokerMuxFixture(t *testing.T, policy ports.BrokerPolicy) *brokerMuxFixt
478 t.Helper()478 t.Helper()
479 routeDir := t.TempDir()479 routeDir := t.TempDir()
480 require.NoError(t, os.Chmod(routeDir, 0o700))480 require.NoError(t, os.Chmod(routeDir, 0o700))
481- route := filepath.Join(routeDir, "mux.sock")481+ return newBrokerMuxFixtureAt(t, policy, filepath.Join(routeDir, "mux.sock"))
482+}
483+
484+// newBrokerMuxFixtureAt binds at a caller-chosen production daemonmux path.
485+func newBrokerMuxFixtureAt(t *testing.T, policy ports.BrokerPolicy, route string) *brokerMuxFixture {
486+ t.Helper()
487+ require.NoError(t, os.MkdirAll(filepath.Dir(route), 0o700))
482 listener, err := ipc.ListenMux(route)488 listener, err := ipc.ListenMux(route)
483 require.NoError(t, err)489 require.NoError(t, err)
484 490

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close