feat(maintenance): add authenticated close actions and logs#5525
feat(maintenance): add authenticated close actions and logs#5525magrathean-uk wants to merge 7 commits into
Conversation
✅ Deploy Preview for teslamate ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Hi @JakobLichterfeld, when you have time, could you take a look at the scope and safety model here? It covers the close-action part you outlined in #4850, and includes runtime health, build info and bounded logs because they share the same operations and authentication path. I would really value reviewing it as one workflow first, since the support flow is incomplete if only one part lands. If you would prefer separate PRs after that, the commits are already split by concern. I could not assign labels from the fork, but |
There was a problem hiding this comment.
Pull request overview
This PR introduces a new “operations/maintenance” surface that consolidates runtime diagnostics (build provenance + runtime health), optional bounded file-log access, and optional guarded maintenance actions for safely closing long-running open sessions. It also adds a versioned /api/health endpoint for aggregate runtime health reporting.
Changes:
- Add a new Maintenance LiveView (operations center) with build info, runtime health, data-health findings, optional log tail, and optional close actions.
- Introduce
TeslaMate.RuntimeHealthand wire it into vehicles/stream/MQTT to expose aggregate health viaGET /api/health. - Add build metadata injection (Docker + GitHub Actions) and optional rotating redacted file logging with a bounded tail reader.
Reviewed changes
Copilot reviewed 65 out of 65 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| website/sidebars.js | Adds docs entries for runtime health and operations page. |
| website/docs/maintenance/operations.md | Documents the operations/maintenance UI, auth boundary, logs, and close actions. |
| website/docs/configuration/runtime-health.md | Documents the /api/health endpoint contract and caching/HTTP semantics. |
| website/docs/configuration/environment_variables.md | Documents new env vars for file logging and maintenance actions/auth. |
| test/teslamate/runtime_health_test.exs | Adds unit tests for runtime health collection, redaction, and aggregation. |
| test/teslamate/mqtt/pubsub/vehicle_subscriber_test.exs | Extends subscriber tests for reconnect snapshot republish behavior. |
| test/teslamate/mqtt/handler_test.exs | Tests MQTT handler reporting into runtime health without leaking details. |
| test/teslamate/maintenance_test.exs | Tests safe close logic for eligible drives/charging sessions. |
| test/teslamate/log_redactor_test.exs | Tests log redaction of common secret shapes. |
| test/teslamate/file_log_test.exs | Tests rotating file log installation + bounded, redacted tail reads. |
| test/teslamate/data_health_test.exs | Tests data-health report for long-running open sessions and truncation. |
| test/teslamate/build_info_test.exs | Tests build metadata validation/normalization/log-line formatting. |
| test/teslamate_web/plugs/operations_auth_test.exs | Tests Basic Auth boundary for sensitive operations + fail-closed config. |
| test/teslamate_web/live/maintenance_live_test.exs | End-to-end LiveView tests for diagnostics, logs, and close actions. |
| test/teslamate_web/controllers/health_controller_test.exs | Tests /api/health aggregate response + legacy /health_check. |
| test/tesla_api/stream_test.exs | Tests stream liveness events emitted separately from data receiver. |
| test/support/mocks/vehicles.ex | Extends VehiclesMock with summary/2 + mutable summary state. |
| test/support/mocks/api.ex | Adds arity-4 stream mock support (opts) for liveness receiver. |
| priv/gettext/tr/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/nl/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/nb/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/ja/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/fi/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/en/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/da/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/ca/LC_MESSAGES/default.po | Updates gettext references/strings for Maintenance/Operations UI. |
| priv/gettext/default.pot | Adds new msgids for Maintenance/Operations UI. |
| lib/teslamate/vehicles/vehicle.ex | Records summary/API/stream health into RuntimeHealth; adds stream liveness receiver; records termination. |
| lib/teslamate/mqtt/pubsub/vehicle_subscriber.ex | Republishes retained snapshot after broker reconnect; reports publish health to RuntimeHealth. |
| lib/teslamate/mqtt/handler.ex | Records MQTT connection state transitions into RuntimeHealth. |
| lib/teslamate/mqtt.ex | Passes runtime health dependency into the MQTT handler init state. |
| lib/teslamate/maintenance.ex | Implements safe, opt-in close actions for eligible long-running sessions. |
| lib/teslamate/log.ex | Adds delete_invalid option to avoid deleting drives when close is requested. |
| lib/teslamate/log_redactor.ex | Implements defense-in-depth redaction for common secret shapes. |
| lib/teslamate/import/fake_api.ex | Adds arity-4 stream/4 to match updated API streaming signature. |
| lib/teslamate/file_log.ex | Implements rotating file logger install + bounded tail reader with redaction. |
| lib/teslamate/data_health.ex | Implements read-only long-running open session report with truncation. |
| lib/teslamate/build_info.ex | Implements validated build provenance/identity extraction and logging. |
| lib/teslamate/application.ex | Installs file logging; logs build metadata; starts RuntimeHealth. |
| lib/teslamate/api.ex | Adds streaming overloads to pass liveness receiver through to TeslaApi.Stream. |
| lib/teslamate_web/templates/layout/root.html.heex | Adds navbar entry for the maintenance/operations page. |
| lib/teslamate_web/router.ex | Adds OperationsAuth pipeline and routes /maintenance and /api/health. |
| lib/teslamate_web/plugs/operations_auth.ex | Implements optional Basic Auth boundary with fail-closed config. |
| lib/teslamate_web/live/maintenance_live/index.ex | Implements the Maintenance LiveView UI behavior (refresh, logs, close confirmation). |
| lib/teslamate_web/controllers/health_controller.ex | Implements versioned aggregate runtime health endpoint with 503 behavior. |
| lib/tesla_api/stream.ex | Adds liveness receiver callbacks and emits liveness events on connect/disconnect/terminate. |
| Dockerfile | Injects build metadata env vars; creates log directory for file logging. |
| config/runtime.exs | Adds build-info config + env-driven operations auth, file logging, and maintenance action toggles. |
| assets/css/app.scss | Adds styles for operations layout and log tail view. |
| .github/workflows/ghcr_build.yml | Passes build ref/revision/source into the image build action. |
| .github/workflows/buildx.yml | Passes build ref/revision/source into the image build action. |
| .github/actions/build/action.yml | Adds build args for build provenance + sets TESLAMATE_BUILD_DATE at build time. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Quick correction before you spend time reviewing this: I have now read your closing notes on #5517 and #5518, and those concerns apply to parts of this branch too. I do not want to ask you to review a direction you have already rejected. I am removing the duplicate data-health surface, the hot-path runtime collector, and the second health endpoint. I will update the branch and description so the remaining scope is only the requested maintenance actions, bounded log access, build identity, and their shared auth boundary. |
1bf05d0 to
bcd4f27
Compare
|
Hi @JakobLichterfeld, the narrowed version is pushed now. I removed everything that overlapped with the concerns you raised on #5517 and #5518: there is no duplicate data-health inbox, no hot-path collector, no new What remains covers the close-drive/charge part of #4850, the bounded authenticated log-tail part of #4891, and build identity from #3682. I think these are worth reviewing together because they use the same small Maintenance page and Basic Auth boundary, and the build identity is what makes the support logs traceable. Keeping that shared path avoids three separate routes, auth setups and repeated UI/docs work. I have also called out clearly that the logging part is env-controlled and does not replace the UI-toggle direction in #4898. The commits are still separated by concern if you prefer to split anything after reviewing the safety model. The updated PR description has the exact boundaries and verification, including 411 tests, Dialyzer, a production Docker build, browser checks, auth headers, fail-closed action proof, and VIN/token redaction. |
Remove the duplicate data-health and runtime-health concepts from the maintenance workflow. Open-session queries now run only when close actions are explicitly enabled, and the page is linked from Settings instead of taking a navbar slot. Keep the shared Basic Auth boundary for bounded file logs and close actions. Extend log redaction to cover VINs, token collections, backseat tokens, and escaped structured values before persistence and display.
bcd4f27 to
0697ae2
Compare
|
Hi Bolyki, thank you for the work that went into this — and for proactively narrowing the scope after my notes on #5518 and #5520. The craftsmanship is genuinely good: the fail-closed safety model, the lock-and-recheck transaction, and the test coverage are all well done. That said, I won't review this as a single unit, and I want to be transparent about why. 1. This bundles too much. Build identity (#3682) has nothing to do with maintenance actions or log access — a shared auth path is not enough reason to couple three features. Even with clean commits, a 49-file PR spanning CI, Dockerfile, a new auth plug, a new LiveView, a file logger and a redaction engine is very hard to review and even harder to maintain. As a side note on #3682: our images already carry build identity twice — the OCI labels from 2. Direction before implementation. As I said in #5452: “I'd prefer that we first establish the need for a feature and then discuss the best implementation, rather than iterating on the implementation before we've agreed that the feature itself solves a recurring problem.” For #4891 the need is established — I opened that issue and outlined the requirements there. But this implementation makes decisions that were not part of that outline (mandatory Basic Auth, no UI toggle for file logging), and those are not up for negotiation in a PR thread. Please wait for direction in the issue before implementing; arriving with finished implementations puts me in the position of either accepting decisions I wasn't part of, or rejecting finished work — neither is good for you or for me. 3. The mandatory Basic Auth coupling is a blocker. Many users already secure TeslaMate properly at the deployment level — reverse proxy with Authelia or OIDC, mTLS, VPN — which is the documented model for TeslaMate. Refusing to start unless a second, TeslaMate-specific Basic Auth credential pair is configured punishes exactly the users who have set up better authentication: for them this is not a safety feature but friction and a second credential store to manage. And since the rest of the UI (settings, geofences, token entry) remains unprotected, the boundary doesn't provide a real security gain either. Deployment-level protection has to remain a first-class option. I won't debate the security architecture further in this PR — the expected model will be spelled out in the issues. How to proceed:
One more general note: you've been contributing at a very high pace over the last weeks, and some of it has been genuinely valuable (#5512, #5513, #5514, #5475). But TeslaMate is maintained by volunteers, and review capacity is our scarcest resource. Several small, issue-aligned PRs — coordinated with the work that already exists — will always move faster here than large pre-built solutions. Thanks for understanding. 🤖 Review drafted with Claude Code (Fable 5 high) — sponsored by Claude for Open Source |
Summary
Adds one authenticated Maintenance page for two opt-in operator tasks:
The page also shows validated image build identity so a support log can be tied back to the exact source, ref and revision.
This intentionally does not add a second health endpoint, a runtime collector, a duplicate data-health inbox or a top-level navbar item. The page is linked from Settings, and open-session queries run only when maintenance actions are explicitly enabled.
Issue coverage
Why these parts are together
The remaining pieces share one small operator workflow and one security boundary. Close actions and log access both need an explicitly enabled, authenticated Maintenance page; build identity makes the log output actionable during support. Keeping them together avoids separate routes, auth configuration and repeated UI/documentation, while the commits remain split by concern if maintainers want any part separated.
Safety and privacy
Cache-Control: no-store.Verification
MIX_ENV=test mix ci: 411 tests passedmix dialyzer: 0 errorsnonroot:nonrooton PostgreSQL 18/health_check: 200/maintenancewithout credentials: 401 with Basic Auth challenge andno-store/maintenancewith credentials: 200 withno-storeAll database and browser verification used disposable local containers.