Release v1.3.18
v1.3.18 is a correctness release driven by a full audit of v1.3.17 (static review of the backend and both pages, race-enabled tests, browser end-to-end runs and load tests). Existing clients and databases stay compatible.
Highlights
- Pages no longer freeze after a pull-mode system goes offline. Marking a system offline now only sets the flag inside one write transaction instead of rewinding its
updated_at, and the browser freshness guard checks only the first payload after a (re)connection, so a legitimately lower timestamp (offline marking, a server clock step) can no longer make every later snapshot look stale. - Server-driven TCPing results for pull-mode agents are merged inside one transaction; the old read-modify-write could overwrite a poll result or an admin edit committed in between. Pull-mode agents are no longer skipped by the TCPing loop when an unreachable agent earlier in the same tick delayed it.
- TCPing batches: the clock-skew bound scales with the configured interval (a post-outage backlog with a 5 min interval is no longer shifted onto "now"), a batch re-sent after a timed-out push is stored once, a fresh sample always replaces a stored "latest" value whose stamp is in the future, and a target the admin removed can no longer be written back by an in-flight agent write.
- SSE: the per-IP stream cap applies to public addresses only, so viewers arriving through a docker bridge or an untrusted proxy address no longer share a single 200-stream budget (the global cap still applies); connect-time snapshot builds are serialised per view and never replace a newer broadcast; the bundled nginx forwards the upstream
X-Forwarded-Forchain instead of overwriting it. - Admin page: only an explicit verdict (401 or
valid:false) ends the session; a rate-limited or failed verify keeps the token and reconnects with a growing pause. With privacy mode on, an expired token made the stream fail with 401 forever without any notice; after three consecutive failures the page now verifies the session and returns to the login page when it is gone. A failed drag-and-drop save repaints the list from the server instead of leaving the row where it was dropped. - First-run setup: if the automatic login after setting the password fails, the form switches to login mode instead of re-posting the setup request.
- Homepage chart housekeeping: a history fetch that completes after its row was collapsed, hidden or deleted no longer creates a chart on a detached canvas, and emptying the list tears down the per-system chart state like a normal row removal.
- Privacy dialog: saving with the existing link but without the echoed expiry keeps the stored absolute expiry (previously the link stopped validating). The TCPing history cache of a deleted system is invalidated again once its background cleanup finishes.
Compatibility
- Existing clients continue to work; no wire format changed.
- Existing
metrics.dbfiles remain readable. - Behind a reverse proxy or CDN, set
TRUSTED_PROXIESso login rate limits see real client addresses; the SSE per-IP cap no longer needs it.
Verified
- Server vet, race-enabled tests and build; client vet and cross-compilation for all five targets.
- Browser end-to-end runs on both pages under a 120-agent load, offline transitions for push and pull agents, admin session loss with privacy mode on and off.
📦 Docker Images
xhh1128/pulse:1.3.18xhh1128/pulse:latest
📥 Downloads
Client binaries
| Platform | File |
|---|---|
| Linux amd64 | probe-client |
| Linux arm64 | probe-client-arm64 |
| macOS Intel (amd64) | probe-client-darwin-amd64 |
| macOS Apple Silicon (arm64) | probe-client-darwin-arm64 |
| Windows amd64 | probe-client.exe |
| Install Script (Linux + macOS) | install.sh |
Server standalone binaries (uploaded by the standalone workflow)
| Platform | File |
|---|---|
| Linux amd64 | pulse-server-standalone-linux-amd64 |
| Linux arm64 | pulse-server-standalone-linux-arm64 |
Quick Install (Linux & macOS):
curl -sSL https://raw.githubusercontent.com/xhhcn/Pulse/main/client/install.sh | sudo bash -s -- --id YOUR_ID --server http://YOUR_SERVER:8080One-click migration to a new host:
PASSWORD="$OLD_ADMIN_PW" \
sudo -E ./scripts/migrate.sh --from https://old.example.com