Owns a bound, published generation and its captured runtime directory.
A timestamp/hash collision fails binding without replacing the prior socket.
Unix lock-contention leftovers are repaired on the next successful scan;
Windows card cleanup under contention requires retry or own-PID reload sweep.
No asynchronous task can bind after this guard is dropped.
Discriminator written into every registration so the registry can tell
its own files from other *.json sharing the run dir (daemon.json,
tooling drops). Files missing it (older binaries) are treated as sessions.
Sanitize a session ID for safe use in filenames and socket paths.
Rejects path separators, .., and non-printable characters.
Returns the sanitized string (replaces unsafe chars with _).
Returns the legacy Unix socket path for a session.
Active endpoint clients must read SessionRegistration::socket_path: new
endpoints use bounded generation names, not this pre-publication helper.
Sockets live in the registry dir — $SYNAPS_RUNTIME_DIR when set (e.g.
/run/user/<uid>/synaps), otherwise $SYNAPS_BASE_DIR/run (default
~/.synaps-cli/run/) — which is user-owned and mode 0700, avoiding /tmp
symlink squatting and TOCTOU races.
Remove registrations that no running session can own and return how
many were removed. Always: an owner pid that no longer exists. With
own_pid (the daemon, at startup): also registrations naming that pid,
which can only be leftovers. A reload re-execs the same pid without
running any session’s shutdown, and the new image has not registered
anything yet when it sweeps.
Operator removal by ID (not owner-scoped). No runtime teardown uses this.
Remove only a valid matching registration. Best-effort — never panics.
Also removes the socket file at socket_path if it exists.
Rewrite {session_id}.json with a new name (rename / saveas). The
rest of the record (socket, pid, started_at) is kept. Errors when there
is no registration to update.