Security
What Database Health Monitor can read and write, what it stores, and what leaves your instance.
It never runs an operating-system command
No subprocess, no os.system, no shell. This is the module's most important security property and the reason free disk space arrives through an endpoint rather than being read directly.
Giving an ERP process the ability to shell out is a larger problem than not knowing the disk is full. It is the capability an attacker who reaches Odoo wants most, and a monitoring module is a poor reason to hand it over.
It reads; it does not remediate
No VACUUM, no reactivating a cron, no clearing a queue, no writes to anything it monitors. The only route that writes anything at all is the agent report, and that accepts a fixed list of six named facts and nothing else.
Probes cannot escape
Every probe runs inside its own savepoint with a five-second statement timeout. A failure is rolled back to the savepoint and recorded as an unknown reading carrying the error text.
Two things this prevents: a slow probe holding a lock or a worker indefinitely, and a raising probe getting the monitoring cron deactivated by Odoo — after which the first symptom of any problem would be silence.
The endpoint
One record per company, every route off or minimal by default.
| Route | Default | Notes |
|---|---|---|
| GET /technovision/health/status | Off | Severity and a count; 503 for critical or unknown |
| — with Expose details | Off | Adds per-check names and values |
| GET /technovision/health/metrics | Off | Prometheus text; names every check |
| POST /technovision/health/report | Off | The only route that writes |
The token goes in Authorization: Bearer, never a query string. A token in a URL ends up in the web server's access log, the browser history and every proxy between you and the server.
The token is stored and shown masked. Rotation keeps the previous token valid for a grace period so the agent and the uptime checker can be rolled separately, and the previous token expires on its own.
Also available on the endpoint: an IP allowlist and a per-minute rate limit. Both are worth setting on anything reachable from outside.
Why status exposes so little
With details off, a caller learns one severity and one count. That is enough for an uptime checker to work on the status code alone and not enough to tell an attacker anything about your instance — which table is largest, which integration is failing, how close a credential is to expiry.
Metrics is off by default for the opposite reason: it cannot avoid naming every check.
Source domains are data
A source's domain is a plain Odoo domain read as data. It is never evaluated as Python. A configuration screen that evaluates Python is a remote-code-execution hole, and monitoring configuration is exactly the kind of screen an administrator hands to somebody junior.
Groups
| Group | Can |
|---|---|
| Health Observer | Read the dashboard, checks and history |
| Health Manager | Change thresholds, alerting, sources and the endpoint |
The endpoint token is readable only by a Health Manager.
Multi-company
Checks, readings, sources, external facts and the endpoint all carry company record rules. Each company has its own endpoint record and its own token, so one company's agent cannot report facts into another's dashboard.
What is stored
Readings — a number, a severity, a timestamp — and a detail string capped at ten rows. Details name tables, models and counts. They do not contain record contents, customer data or credentials.
What it does not protect against
- A user with Settings access, who can change groups or read the token.
- An agent host that is compromised — it holds a token that can write facts. Those facts drive alert severity, so a compromised agent can make the dashboard lie. Treat the token as a credential and rotate it.
- log_db being off, which makes the server-errors check read zero honestly rather than accurately. The reading says so.