Sidecar: auth always-on, protocol version, rich health
Auth is now impossible to turn off by accident. A blank auth_token is never allowed even on loopback: config load generates a token, writes it back into sidecar.toml (preserving the rest of the file), logs it, and continues -- so a forgotten or cleared token self-heals into a working, authenticated setup instead of silently disabling auth. No auth token configured. Generated new token: cb99... Saved to sidecar.toml. Authentication is on. Protocol versioning (PROTOCOL_VERSION = 1) lets the website and sidecar detect a mismatch immediately when a message shape changes. Every response carries an X-UOLink-Version header; /health and ws.hello include "protocol"; a request that declares a different X-UOLink-Version is rejected 409 with both versions so the mismatch is unambiguous. Bump the constant when a contract changes. /health is now a real troubleshooting panel: status (ok/degraded), protocol, plugin_connected (is the shard link up), database (SELECT 1), uptime, and last_event (the timestamp of the last line from the shard). Unauthenticated so monitoring can reach it. Verified: a blank token generates + persists + enforces (401 without, 200 with); X-UOLink-Version header on every response; 409 on a declared mismatch; /health reports degraded/plugin_connected:false with no shard, then flips to ok/true and a populated last_event once the shard connects. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -27,7 +27,42 @@ The website authenticates to the sidecar with a shared token, presented as:
|
||||
- REST — `Authorization: Bearer <token>` or `X-Api-Key: <token>`
|
||||
- WebSocket — `?token=<token>` in the connect URL (browsers can't set headers on a WS handshake)
|
||||
|
||||
`/health` is the only unauthenticated route. The token is compared in constant time. It is generated randomly on first run; rotate it by editing `sidecar.toml` (or setting `UOLINK_WEB_TOKEN`) and restarting. An empty token disables auth and is only tolerated on a loopback bind — binding to `0.0.0.0` with no token logs a warning that the API is exposed. `sidecar.toml` is gitignored because it holds the secret.
|
||||
`/health` is the only unauthenticated route. The token is compared in constant time.
|
||||
|
||||
**Authentication is always on.** If `auth_token` is blank (fresh install, or someone cleared it), the sidecar generates one, writes it back to `sidecar.toml`, logs it, and continues:
|
||||
|
||||
```
|
||||
No auth token configured.
|
||||
Generated new token: cb998929b2201e44914dcf077bbf115583bfbe80dcf93073
|
||||
Saved to sidecar.toml. Authentication is on.
|
||||
```
|
||||
|
||||
So you can never accidentally run without auth. Rotate by editing the token and restarting. `sidecar.toml` is gitignored because it holds the secret.
|
||||
|
||||
## Protocol version
|
||||
|
||||
The wire protocol has a version (`PROTOCOL_VERSION`, currently **1**), so the website and sidecar detect a mismatch immediately instead of failing in strange ways when a message shape changes.
|
||||
|
||||
- Every response carries an `X-UOLink-Version: 1` header.
|
||||
- `/health` and the WebSocket `ws.hello` include `"protocol": 1`.
|
||||
- If a request sends `X-UOLink-Version` and it disagrees with the sidecar, the request is rejected **409 Conflict** with `{sidecar_protocol, client_protocol}` so the mismatch is obvious.
|
||||
|
||||
Bump `PROTOCOL_VERSION` in `main.rs` whenever an event or endpoint's shape changes.
|
||||
|
||||
## Health
|
||||
|
||||
`GET /health` (unauthenticated) returns an at-a-glance status for troubleshooting:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok", // "ok" when plugin connected and DB reachable, else "degraded"
|
||||
"protocol": 1,
|
||||
"plugin_connected": true, // is the shard link up?
|
||||
"database": "ok",
|
||||
"uptime": "3d 12h",
|
||||
"last_event": "2026-07-10T22:08:27Z" // last line received from the shard, null if none
|
||||
}
|
||||
```
|
||||
|
||||
## Status
|
||||
|
||||
|
||||
Reference in New Issue
Block a user