From 4ae6b8d5e6dabac108a799daf8223ddaca11598e Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 00:09:37 +0000 Subject: [PATCH 1/7] revert(broker): restore doc comments outside docs-only scope A review fix round edited doc comments in apps/broker/src/main.rs to match the docs updated on this branch. The branch is docs-only by explicit constraint, so no file under a src/ directory may change here. The stale comment stands as a separate follow-up. --- apps/broker/src/main.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/broker/src/main.rs b/apps/broker/src/main.rs index 18b4e91..0baa455 100644 --- a/apps/broker/src/main.rs +++ b/apps/broker/src/main.rs @@ -5,7 +5,7 @@ //! shell, Registry path, or hardware primitive crosses this boundary. //! //! Only the Unix domain socket transport is implemented; the Windows named-pipe -//! transport is not yet available, so the binary refuses to run there. +//! transport is deliberately out of scope, so the binary refuses to run there. //! //! The broker always establishes one owner-only private directory of its own, //! under `$XDG_RUNTIME_DIR` (or `/run`). Unless `--socket`/`--journal` or their @@ -98,10 +98,10 @@ or the broker refuses to start."; /// Environment override for `--journal`. /// /// Deliberately distinct from the `FPSMAXXING_JOURNAL_PATH` the unprivileged - /// gateway, CLI, and watchdog read. Sharing that variable would let an - /// operator who exported it for the CLI silently move the privileged - /// broker's audit journal out of its owner-only directory and into a file - /// the gateway is writing concurrently. + /// gateway and CLI read. Sharing that variable would let an operator who + /// exported it for the CLI silently move the privileged broker's audit + /// journal out of its owner-only directory and into a file the gateway is + /// writing concurrently. const JOURNAL_ENV: &str = "FPSMAXXING_BROKER_JOURNAL_PATH"; /// Directory the broker keeps its socket and journal in by default. @@ -259,7 +259,7 @@ or the broker refuses to start."; /// [`resolve_paths`] against an arbitrary runtime base and environment. /// /// Only [`SOCKET_ENV`] and [`JOURNAL_ENV`] are ever consulted; the broker - /// shares no path variable with the unprivileged gateway, CLI, or watchdog. + /// shares no path variable with the unprivileged gateway or CLI. /// /// The private directory under `base` is created and vetted whatever the /// overrides say, because the single-instance lock lives in it and must not @@ -692,8 +692,7 @@ or the broker refuses to start."; resolve_paths_from, restrict_journal, runtime_base, }; - /// The variable the unprivileged gateway, CLI, and watchdog use for - /// their journal. + /// The variable the unprivileged gateway and CLI use for their journal. const GATEWAY_JOURNAL_ENV: &str = "FPSMAXXING_JOURNAL_PATH"; /// An unprivileged uid, so `XDG_RUNTIME_DIR` is eligible at all. From e1288eef8d944c2fb9547e9991e9442979ec44d4 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 00:29:36 +0000 Subject: [PATCH 2/7] no-mistakes(review): defer broker doc status to README, fix systemd wording --- README.md | 2 +- docs/BROKER_OPERATIONS.md | 2 +- docs/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b253e2c..667d4f3 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ It is a demonstration binary rather than an MCP tool, takes no arguments, and jo `fpsmaxxing-broker` is the trusted side of the local IPC boundary: it serves capability discovery and the bounded provider lifecycle to authenticated local peers over a Unix domain socket, and refuses to run on Windows because the Windows named-pipe transport is not yet available. The gateway does not connect to it yet, so the broker path is exercised by the `BrokerClient` in `crates/ipc` and its end-to-end tests in `apps/broker/tests/integration.rs` rather than by the MCP command above. -[Broker operations and deployment](docs/BROKER_OPERATIONS.md) covers running it directly: socket, journal, and lock paths, private-directory ownership rules, and systemd units. +[Broker operations and deployment](docs/BROKER_OPERATIONS.md) covers running it directly: socket, journal, and lock paths, private-directory ownership rules, and systemd RuntimeDirectory settings. ```bash cargo run -p fpsmaxxing-broker diff --git a/docs/BROKER_OPERATIONS.md b/docs/BROKER_OPERATIONS.md index 0a1b531..32fcda3 100644 --- a/docs/BROKER_OPERATIONS.md +++ b/docs/BROKER_OPERATIONS.md @@ -6,7 +6,7 @@ For why the boundary is shaped this way, read [Architecture](ARCHITECTURE.md); f The `fpsmaxxing-broker` binary is the trusted side of the local IPC boundary. It owns the control plane and serves capability discovery and the bounded provider lifecycle to authenticated local peers over a Unix domain socket. Only the Unix domain socket transport is implemented, and the Windows named-pipe transport is not yet available, so the binary refuses to run there. -The gateway does not connect to it yet - it still opens an in-process control plane of its own - so the broker path is exercised by the `BrokerClient` in `crates/ipc` and its end-to-end tests in `apps/broker/tests/integration.rs` rather than by an MCP client. +For what currently drives that boundary, see [Privileged broker](../README.md#privileged-broker) in the project README. ## Running the broker diff --git a/docs/README.md b/docs/README.md index 1c19cad..eb0d5c0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,7 +15,7 @@ Use this page as the documentation entry point. The Markdown documents are canon | Document | Purpose | | --- | --- | -| [Broker operations and deployment](BROKER_OPERATIONS.md) | Running the privileged broker: socket, journal, and lock paths, private-directory ownership rules, and systemd units | +| [Broker operations and deployment](BROKER_OPERATIONS.md) | Running the privileged broker: socket, journal, and lock paths, private-directory ownership rules, and systemd RuntimeDirectory settings | ## Extension guides From 5a433d85f496b60b0083010310ae4f00dfcb1601 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 00:42:14 +0000 Subject: [PATCH 3/7] no-mistakes(review): name walkthrough referent, reorder broker ops sections --- README.md | 4 ++-- docs/BROKER_OPERATIONS.md | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 667d4f3..bacf197 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ BIOS changes, voltage changes, raw MSR/PCI/EC access, firmware flashing, and arb ## Repository status FPSMaxxing is a Rust 2024 Cargo workspace with OSS governance, a security policy, issue templates, CI, and an organized [documentation index](docs/README.md) covering architecture, plans, threat model, broker operations, and provider guides. -Every stage of the closed loop above has a working implementation on the mock path, except what the walkthrough marks as future. +Every stage of the closed loop above has a working implementation on the mock path, except what the closed-loop walkthrough above marks as future. What ships today, by capability: - **Capabilities and providers.** Shared capability and provider contracts, a provider SDK lifecycle, and a mock provider covering snapshot, preview, apply, verify, and rollback under test. @@ -94,7 +94,7 @@ What ships today, by capability: - **Crash and lease recovery.** An independent watchdog that restores prior state from the journal after a crash or a lease expiry, on the Linux-safe mock path. - **Measurement and decision.** A deterministic experiment runner that gates measured trials through an immutable evaluator and replays them from the journal alone. -Everything the walkthrough above states in the future tense is still ahead of us. +Everything the closed-loop walkthrough above states in the future tense is still ahead of us. So are real hardware providers and live frame-time measurement. Try the read-only alpha: diff --git a/docs/BROKER_OPERATIONS.md b/docs/BROKER_OPERATIONS.md index 32fcda3..9120de5 100644 --- a/docs/BROKER_OPERATIONS.md +++ b/docs/BROKER_OPERATIONS.md @@ -26,6 +26,19 @@ cargo run -p fpsmaxxing-broker -- \ --journal "$HOME/.local/state/fpsmaxxing/journal.sqlite" ``` +## The private directory + +The private directory is `$XDG_RUNTIME_DIR/fpsmaxxing`, or `/run/fpsmaxxing` when `XDG_RUNTIME_DIR` is unset, is not absolute, or the broker runs as root. +The broker creates it mode `0700` whether or not an override moved the socket and the journal out of it, because the single-instance lock lives there, and refuses to start unless it and every directory above it are owned by the broker or root and are not writable by anyone else. +It still establishes that directory even when both paths are given, so it also needs to be able to create `$XDG_RUNTIME_DIR/fpsmaxxing` - or `/run/fpsmaxxing`, when that variable is unset - on every start. + +Do not put your own directory at `/run/fpsmaxxing`. +That is the privileged broker's own private directory, and it is the one directory held to exact ownership: root ownership satisfies an explicit `--socket` or `--journal` parent, but a broker accepts its private directory only when it owns that itself. +Creating `/run/fpsmaxxing` as your user therefore leaves a later root broker refusing to start until it is chowned to root or removed. +A root broker creates and vets it on its own. + +A systemd unit needs both `RuntimeDirectory=fpsmaxxing` and `RuntimeDirectoryMode=0700`: `RuntimeDirectoryMode` defaults to `0755`, and the broker validates an existing private directory rather than correcting its mode, so a unit that omits the mode is refused on every start. + ## Socket and journal paths | Setting | Flag | Environment variable | Default | @@ -44,19 +57,6 @@ Nor is group or world traversal excused: the socket's own mode cannot be pinned, The journal file itself is created mode `0600`, and SQLite's rollback journal and write-ahead log inherit that. -## The private directory - -The private directory is `$XDG_RUNTIME_DIR/fpsmaxxing`, or `/run/fpsmaxxing` when `XDG_RUNTIME_DIR` is unset, is not absolute, or the broker runs as root. -The broker creates it mode `0700` whether or not an override moved the socket and the journal out of it, because the single-instance lock lives there, and refuses to start unless it and every directory above it are owned by the broker or root and are not writable by anyone else. -It still establishes that directory even when both paths are given, so it also needs to be able to create `$XDG_RUNTIME_DIR/fpsmaxxing` - or `/run/fpsmaxxing`, when that variable is unset - on every start. - -Do not put your own directory at `/run/fpsmaxxing`. -That is the privileged broker's own private directory, and it is the one directory held to exact ownership: root ownership satisfies an explicit `--socket` or `--journal` parent, but a broker accepts its private directory only when it owns that itself. -Creating `/run/fpsmaxxing` as your user therefore leaves a later root broker refusing to start until it is chowned to root or removed. -A root broker creates and vets it on its own. - -A systemd unit needs both `RuntimeDirectory=fpsmaxxing` and `RuntimeDirectoryMode=0700`: `RuntimeDirectoryMode` defaults to `0755`, and the broker validates an existing private directory rather than correcting its mode, so a unit that omits the mode is refused on every start. - ## Single-instance lock Only one broker may run per user: it takes an exclusive lock on `/broker.lock` before the journal is opened and before the socket is bound, so a second broker exits non-zero without having touched either. From 2747ea88a8553cc0fa464492b26778baef9f34c1 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 00:56:08 +0000 Subject: [PATCH 4/7] no-mistakes(review): fix broker directory ownership claim, cut duplicate sentence --- docs/BROKER_OPERATIONS.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/BROKER_OPERATIONS.md b/docs/BROKER_OPERATIONS.md index 9120de5..d84fe97 100644 --- a/docs/BROKER_OPERATIONS.md +++ b/docs/BROKER_OPERATIONS.md @@ -29,8 +29,7 @@ cargo run -p fpsmaxxing-broker -- \ ## The private directory The private directory is `$XDG_RUNTIME_DIR/fpsmaxxing`, or `/run/fpsmaxxing` when `XDG_RUNTIME_DIR` is unset, is not absolute, or the broker runs as root. -The broker creates it mode `0700` whether or not an override moved the socket and the journal out of it, because the single-instance lock lives there, and refuses to start unless it and every directory above it are owned by the broker or root and are not writable by anyone else. -It still establishes that directory even when both paths are given, so it also needs to be able to create `$XDG_RUNTIME_DIR/fpsmaxxing` - or `/run/fpsmaxxing`, when that variable is unset - on every start. +The broker creates it mode `0700` on every start, whether or not an override moved the socket and the journal out of it, because the single-instance lock lives there, and refuses to start unless it and every directory above it are owned by the broker or root and are not writable by anyone else. Do not put your own directory at `/run/fpsmaxxing`. That is the privileged broker's own private directory, and it is the one directory held to exact ownership: root ownership satisfies an explicit `--socket` or `--journal` parent, but a broker accepts its private directory only when it owns that itself. @@ -48,8 +47,8 @@ A systemd unit needs both `RuntimeDirectory=fpsmaxxing` and `RuntimeDirectoryMod A flag wins over its environment variable, and both are broker-specific so nothing the gateway, the CLI, or the watchdog exports can move the privileged journal. -A path from a flag or an environment variable is held to the same bar as the default: it must be absolute, the directory holding it must exist, and the whole chain above it is vetted, so an override cannot place a privileged socket or audit journal somewhere another user can reach it. -Give the socket and the journal a directory of their own at mode `0700`, owned by the broker or root - the default private directory already is one. +A path from a flag or an environment variable is vetted as well: it must be absolute, the directory holding it must exist, and the whole chain above it is vetted, so an override cannot place a privileged socket or audit journal somewhere another user can reach it. +Give the socket and the journal a directory of their own at mode `0700`, owned by the broker or root, which is the looser of the two ownership rules: the default private directory is accepted only when the broker owns it itself. That directory is held higher than the ancestors above it, in two ways. The sticky bit does not excuse group or world write there: sticky stops another user removing the broker's socket or journal, but not creating either one first and keeping ownership of it, so a shared root like `/tmp` is refused. From 93f43c66035c06f247d9efd77193bc9714284083 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 01:09:45 +0000 Subject: [PATCH 5/7] no-mistakes(review): drop committed core dump, fix private-directory ownership rule --- docs/BROKER_OPERATIONS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/BROKER_OPERATIONS.md b/docs/BROKER_OPERATIONS.md index d84fe97..1abf83c 100644 --- a/docs/BROKER_OPERATIONS.md +++ b/docs/BROKER_OPERATIONS.md @@ -29,10 +29,11 @@ cargo run -p fpsmaxxing-broker -- \ ## The private directory The private directory is `$XDG_RUNTIME_DIR/fpsmaxxing`, or `/run/fpsmaxxing` when `XDG_RUNTIME_DIR` is unset, is not absolute, or the broker runs as root. -The broker creates it mode `0700` on every start, whether or not an override moved the socket and the journal out of it, because the single-instance lock lives there, and refuses to start unless it and every directory above it are owned by the broker or root and are not writable by anyone else. +The broker creates it mode `0700` on every start, whether or not an override moved the socket and the journal out of it, because the single-instance lock lives there. +It refuses to start unless that directory is owned by the broker's own uid and has mode exactly `0700`, and unless every directory above it is owned by the broker or root and is not writable by anyone else except under a sticky bit. Do not put your own directory at `/run/fpsmaxxing`. -That is the privileged broker's own private directory, and it is the one directory held to exact ownership: root ownership satisfies an explicit `--socket` or `--journal` parent, but a broker accepts its private directory only when it owns that itself. +That is the privileged broker's own private directory. Creating `/run/fpsmaxxing` as your user therefore leaves a later root broker refusing to start until it is chowned to root or removed. A root broker creates and vets it on its own. From 116f36300606fe70f38f3a4e80ebc632f6faa247 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 01:49:19 +0000 Subject: [PATCH 6/7] no-mistakes(document): link broker operations guide from architecture doc --- docs/ARCHITECTURE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 42630df..aecf74a 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -56,6 +56,7 @@ The audit journal is different: it holds every `apply-intent` record and outlive The broker reads only broker-specific overrides (`FPSMAXXING_BROKER_SOCKET`, `FPSMAXXING_BROKER_JOURNAL_PATH`) and never the `FPSMAXXING_JOURNAL_PATH` the unprivileged gateway, CLI, and watchdog use, so an operator who exported that variable cannot move the privileged audit journal. Both are read as raw `OsString` values, so a path that is not UTF-8 relocates the socket or journal as configured rather than being silently dropped back to the default. The command line is read as `OsString` too, but it is matched against flag names rather than used verbatim, so an argument that is not UTF-8 is a typed fatal parse error naming it - not the mid-iteration panic `env::args` would raise, and not a silent fallback either. +[Broker operations and deployment](BROKER_OPERATIONS.md) turns these rules into the procedure for running the broker, down to the systemd `RuntimeDirectory` settings a unit needs. The broker fails fast rather than degrading. Losing the control-plane worker thread - including to a panic mid-lifecycle, which may leave provider state applied and un-rolled-back - stops the serve loop and exits the process non-zero instead of answering later requests with an internal fault. From 2aeee26013ba79ec1f91248b3988b3d2342a52c0 Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 29 Jul 2026 01:59:10 +0000 Subject: [PATCH 7/7] no-mistakes(lint): ignore crash dumps --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 67f8d66..0233772 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ Thumbs.db .sentrux/cache.bin .sentrux/churn.bin + +# Crash dumps must never enter source control. +core +core.*