Send client logs to the host — the log-escape hatch for locked-down platforms #247
Merged
enricobuehler
merged 1 commits from 2026-08-15 10:57:19 +00:00
worktree-client-log-upload into main
1
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5ae08ffaa5 |
feat: send client logs to the host — the log-escape hatch for locked-down platforms
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 3m15s
android / android (pull_request) Successful in 5m38s
ci / rust (pull_request) Failing after 5m11s
ci / bun-nix (pull_request) Successful in 43s
ci / docs-site (pull_request) Successful in 2m8s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 6m39s
ci / rust-arm64 (pull_request) Successful in 12m57s
ci / web (pull_request) Successful in 10m37s
On a Steam Deck in Gaming Mode, a tvOS box or a webOS TV the user has no realistic way to get the client's log off the device, so field reports arrive host-log-only and the client half of every stutter story is invisible (today's Skynet analysis was the third such report in two days). This inverts the collection: an explicit action on the client posts its recent log to the PAIRED host, and the host's web console lists the bundle next to the host's own log export — both halves of a report in one place, from the one surface reporters already use. Host: crate::client_logs is a bounded file store under <config-dir>/client-logs (traversal-proof ids per the stats_recorder pattern, newest 5 bundles per device, 1 MiB cap), NOT the log ring — a multi-thousand-line bundle would evict the host's own log there. POST /api/v1/client-logs is the cert lane's first and only WRITE: paired mTLS devices may upload (write-only — no read of anything, not even their own bundle), while list/fetch/delete stay on the loopback bearer lane; the lane matrix rows pin all four. Per-client access (#245) integration: the upload gate uses effective() — an expired guest's upload is refused (403) while any live-authorized device, including view-only guests, may send; no input-grant bit is required since uploading one's own diagnostics is not an input capability. Client: pf_client_core::logring keeps the newest 4096 lines / 768 KiB (dependency-free ring; each shell installs a thin tracing layer — the session binary's ring_layer captures DEBUG+ regardless of RUST_LOG, wall-clock stamped so bundles correlate with the host log). send_to_host reuses the library fetch's mTLS agent + host pin and the same error classification. The gamepad console gains "Send logs to host" in the per-host menu (paired + online rows only), a ConsoleCmd worker thread, and a shared-model notice channel so the result lands as a toast. Web console: a Client logs card on the Logs page (list/download/delete, hidden while empty), en+de messages, api/openapi.json regenerated. Apple (tvOS/iOS/macOS), Android and webOS legs are follow-ups: each already holds a paired identity and the mgmt port from the Welcome, so they only need a ring + one authenticated POST. Gates: mgmt+client_logs 57/57 and full host suite green on Ubuntu 26.04 (the one failure, hooks::prep_runs_do_in_order_and_undo_in_reverse, fails identically on pristine origin/main — pre-existing); clippy clean across punktfunk-host, pf-client-core, pf-console-ui; session binary checks; web build + tsc + i18n clean; pf-client-core logring test run in the amd64 container. |