Repository navigation
feat(conductor): runtime rule loading via CLI, HTTP Basic Auth on the dashboard - #12
Merged
Merged
Conversation
… dashboard Two real operational gaps, closed: - Rules were only ever loadable from a bundled, compile-time-embedded file (RuleEngine::load_from_file and PCHIConductor::with_rules_file already existed, but main.rs never called them) — every venue wanting different thresholds needed a recompile. `--rules <path>` / PCHI_RULES_FILE now wires straight through to the real binary. - The dashboard, its /ws feed, and /governance/export were either fully open or (export only) gated by a bespoke X-Governance-Key header that a plain browser navigation can't satisfy. PCHI_DASHBOARD_PASSWORD now gates all three behind HTTP Basic Auth (username "operator") — the one scheme a direct `GET /` in a browser can answer on its own, via the browser's native credential prompt. Still open by default, unchanged posture: self-hosted on a machine its operator already controls. Verified live, not just in tests: a custom .only-pchi file with a stricter threshold than the bundled default actually denies traffic the default would allow, over real UDP; the auth layer returns real 401s without credentials and real 200s with correct ones, including on /governance/export. 9 new tests (31 -> 40 total). clippy clean. fmt unchanged (pre-existing report-only policy, see .github/workflows/rust.yml). Co-Authored-By: Claude Sonnet 5 <[email protected]>
3 tasks done
vdmo
added a commit
that referenced
this pull request
Oct 1, 2026
Scene state was in-memory only — a restart (planned or crashed) always started from a blank SceneState, even though the governance log already survives restarts fine. A venue running this overnight had no way to come back up mid-show without losing "where things were." - SceneState::save_snapshot/load_snapshot: atomic write (temp file + rename, so a crash mid-write never corrupts the snapshot already on disk), and a missing/corrupt snapshot logs a warning and starts fresh rather than failing startup — this is a resilience convenience, not the safety-critical record (that's still the governance log, which already fsyncs every signed receipt, untouched by this change). - PCHIConductor::with_state_file(path): loads an existing snapshot right now if present, then enables periodic snapshotting via the new run_state_snapshot_loop (every 2s, skipped when nothing changed since the last one). snapshot_state_now() takes one final snapshot on graceful shutdown, so a planned restart loses nothing regardless of where in the interval it happened. - Wired into main.rs as --state-file / PCHI_STATE_FILE, defaulting to pchi_scene_state.json (always on, same posture as the governance log's own default-local-file behavior) — and into the Ctrl+C shutdown path. Verified live against the real binary, not just unit tests: set a control parameter over real UDP, confirmed the periodic snapshot picked it up on disk, sent SIGINT (the real Ctrl+C path), confirmed the final- snapshot log line, restarted the same binary pointed at the same file, and confirmed "Resumed scene state from ... (last updated ...)" with the exact prior timestamp. 5 new tests (40 -> 45 total): 4 for SceneState's save/load, including a corrupt-file case, plus one full restart-resume cycle through PCHIConductor itself (set a value, snapshot, construct a fresh conductor pointed at the same file, confirm it resumes the value). clippy clean. Stacked on #12 (reuses its Cli struct and main.rs flow) — review/merge after that one. Co-authored-by: vdmo <[email protected]> Co-authored-by: Claude Sonnet 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PCHIConductor::with_rules_fileandRuleEngine::load_from_filealready existed, butmain.rsnever called them — a fresh venue wanting different Only-Lang thresholds needed to recompile the binary.--rules <path>(also readable asPCHI_RULES_FILE) now wires straight through./,/ws, and/governance/exportwere either fully open or (export only) gated by a bespokeX-Governance-Keyheader a plain browserGET /can't set.PCHI_DASHBOARD_PASSWORDnow gates all three behind HTTP Basic Auth (usernameoperator) — the one scheme a direct browser navigation can answer itself via the native credential prompt, no login page needed. Still open by default — same self-hosted-trusted-machine posture as before, just consistently applied.README.md(usage examples),docs/LIMITATIONS.md§4 (marked[Improved], with the real remaining caveat about non-browser WS clients needing to send their own Basic Auth header),PRICING.md(env var rename).Test plan
cargo test --workspace— 40/40 passing (31 existing + 9 new: 2 forwith_rules_filebehavior, 7 for the auth middleware covering all three routes, both credential states, and wrong-username/wrong-password)cargo clippy --workspace --all-targets -- -D warnings— clean--rulespointed at a custom file with a threshold stricter than the bundled default, sent a real UDP message that the bundled default would allow (1.5 vs. its 4.0 threshold) and the custom file denies (its own 1.0 threshold) — got a real signed DENY receipt back from/governance/exportwith the custom file's exact message, proving the custom file is genuinely what's running, not a silent fallbackcurlagainst the real running server with no credentials (401), wrong password (401), and correct-u operator:...credentials (200) on both/and/governance/export🤖 Generated with Claude Code