fix(sessions): keep named-pipe socket paths inside the macOS sun_path limit (NEXT-01)

The pipe name mxaccess-gateway-{pid}-session-{32hex} plus .NET's
CoreFxPipe_ prefix overflowed the 104-byte Unix-domain-socket path limit
under the default per-user macOS TMPDIR (~49 chars), so every test that
opened a real pipe threw ArgumentOutOfRangeException at pipe creation
unless TMPDIR=/tmp was exported. Rename to mxgw-{pid}-{sessionUid} (the
session guid hex without the session- prefix; worst-case 43 chars) and
shorten the three test-fixture names the same way. Uniqueness is
unchanged: gateway pid + full session guid. The worker receives the pipe
name via its launch command line, so mixed Server/Worker deploy SHAs are
unaffected. Docs updated in the same change (gateway.md,
GatewayProcessDesign, GatewayConfiguration, Sessions, CLAUDE.md); new
regression test pins the format and the length budget.

Verified: SessionManagerTests 39/39; SessionWorkerClientFactory,
GatewayEndToEndFakeWorkerSmoke, WorkerClient, and ReconnectReplay suites
33/33 under the default macOS TMPDIR — this also retires the
previously-misdiagnosed 'macOS pipe-timeout test failures': they were
this path-length throw, not a timeout-message defect.
This commit is contained in:
Joseph Doherty
2026-08-10 05:54:11 -04:00
parent 0152180929
commit 8769ee9765
14 changed files with 769 additions and 15 deletions
@@ -417,7 +417,8 @@ public sealed class SessionManager : ISessionManager
string? clientIdentity,
string? ownerKeyId)
{
string sessionId = CreateSessionId();
string sessionUid = Guid.NewGuid().ToString("N");
string sessionId = $"session-{sessionUid}";
string backendName = string.IsNullOrWhiteSpace(request.RequestedBackend)
? GatewayContractInfo.DefaultBackendName
: request.RequestedBackend!;
@@ -425,7 +426,11 @@ public sealed class SessionManager : ISessionManager
TimeSpan startupTimeout = TimeSpan.FromSeconds(_options.Worker.StartupTimeoutSeconds);
TimeSpan shutdownTimeout = TimeSpan.FromSeconds(_options.Worker.ShutdownTimeoutSeconds);
TimeSpan leaseDuration = TimeSpan.FromSeconds(_options.Sessions.DefaultLeaseSeconds);
string pipeName = $"mxaccess-gateway-{Environment.ProcessId}-{sessionId}";
// The short prefix and bare guid keep the pipe's Unix-domain-socket path
// (TMPDIR + "CoreFxPipe_" + name) inside the 104-byte sun_path limit on
// macOS, whose default per-user TMPDIR is ~49 chars; the gateway PID keeps
// the name collision-free across gateway restarts (NEXT-01).
string pipeName = $"mxgw-{Environment.ProcessId}-{sessionUid}";
string nonce = CreateNonce();
DateTimeOffset openedAt = _timeProvider.GetUtcNow();
string clientCorrelationId = CreateClientCorrelationId(request.ClientSessionName, sessionId);
@@ -484,11 +489,6 @@ public sealed class SessionManager : ISessionManager
: timeout;
}
private static string CreateSessionId()
{
return $"session-{Guid.NewGuid():N}";
}
private static string CreateNonce()
{
Span<byte> bytes = stackalloc byte[32];