Operations
evolvingOperations
TL;DR. How phux behaves at the seams: how errors are typed inside the workspace and translated at the IPC boundary; what logs and runtime introspection are available; where the trust boundary sits. Cross-cuts the architecture; each section below stays focused on a single seam so additions don’t churn the doc.
Error model
Each library crate defines its own error type with thiserror. The
binary crate uses anyhow at the top level only — never inside
library code.
// crates/phux-server/src/error.rs
#[derive(Debug, thiserror::Error)]
pub enum ServerError {
#[error("protocol: {0}")]
Protocol(#[from] phux_protocol::ProtocolError),
#[error("pty: {0}")]
Pty(#[from] PtyError),
#[error("io: {0}")]
Io(#[from] std::io::Error),
// ...
}
Errors that cross the IPC boundary are translated to ERROR messages
(see spec/proto.md) with a code: ErrorCode and
a message: str. The mapping from internal Rust errors to wire
ErrorCode is the responsibility of the server’s IPC layer.
Logging and observability
tracing is the structured logging substrate. Server logs go to
~/.local/state/phux/log/server.log, rotated daily via
tracing-appender’s file rolling writer. Filter precedence:
- Config file (
log_filter = "phux=info,phux_server=debug"). PHUX_LOGenvironment variable (overrides config).- Default:
phux=info.
Spans by convention:
attach(client_id, session_id) — wraps an attachment for its lifetime.pane(terminal_id) — wraps PTY pump andTERMINAL_OUTPUTfanout per terminal.command(request_id, kind) — wraps aCOMMANDdispatch.
Runtime introspection ships as phux server status --json: number of
sessions / windows / terminals / clients, per-terminal refresh rate,
per-client queue depth, total bytes since start. This is the
substrate for any future Prometheus/OpenTelemetry exporter — phux
does not ship one.
Security model
The trust boundary is the operating system user. A phux server trusts every process running as the same UID that can connect to its Unix socket.
- Local. Unix socket under
$XDG_RUNTIME_DIR/phux/(or/tmp/phux-$UID/), with the parent directory created mode0o700. The OS enforces the trust boundary on the directory; the socket inherits that boundary. - Remote (v0.1). SSH-tunneled
phux server --stdiooverssh host. Authentication is SSH’s problem. - Remote (v0.2+). QUIC transport behind the
Transporttrait (ADR-0007); the wire bytes don’t change.
phux itself does no authentication and no encryption. Crypto in
multiplexers is a tarpit; we delegate. See
architecture/transport.md for the
trait shape that makes additional transports purely additive.