check / check (push) Successful in 45s
A buffer failure on POST /api/v1/reports now returns 500 instead of a false `ok`, so clients can retry. Decode errors split: an over-limit body returns 413 (via errors.As on `*http.MaxBytesError`), malformed JSON stays 400. A new MaxBodyBytes middleware (1 MiB default) caps every route — rejecting an oversized Content-Length up front and capping the read otherwise — so the health check and future routes are bounded too. The raw attacker-controlled geo blob is no longer logged, only its length; client_id and timestamp are length-bounded before logging. A decodeJSON handler helper is added. Panic recovery is now a local middleware routing the stack through slog as structured JSON. Storage failure uses 500: a full buffer or write error is server-side and retryable. Model: opus-4-8
97 lines
5.4 KiB
Markdown
97 lines
5.4 KiB
Markdown
# Workflow
|
|
|
|
- branch (from `main`)
|
|
- do the work in Next Step
|
|
- move Next Step to the top of Completed Steps
|
|
- move the top item of Future Steps into Next Step
|
|
- commit (`TODO.md` changes in the same commit as the work)
|
|
- merge to `main` if the branch is not protected, otherwise open a PR
|
|
- push
|
|
|
|
# Status
|
|
|
|
pre-1.0. No git tags. Backend work in flight on feat/reportbuf-storage (dirty:
|
|
src/main.js). Frontend is functional; backend is new and unmerged.
|
|
|
|
# Next Step
|
|
|
|
Land feat/reportbuf-storage: finish the in-progress src/main.js change, get make
|
|
check green, and merge the branch to main. The branch adds the backend (buffered
|
|
zstd-compressed report storage), the CI workflow, and backend repo standard
|
|
files, so merging it also closes most compliance gaps.
|
|
|
|
# Completed Steps
|
|
|
|
- 2026-09-21: report ingest correctness (issue #23): a storage failure now
|
|
returns 500 instead of a false `ok`; oversize bodies return 413 (distinguished
|
|
from malformed JSON, which stays 400); a `MaxBodyBytes` middleware caps every
|
|
route, not just the report route; the raw attacker-controlled `geo` blob is no
|
|
longer logged (only its length) and `client_id`/`timestamp` are length-bounded
|
|
before logging; a `decodeJSON` handler helper was added; and panic recovery
|
|
now routes the stack through slog instead of chi's plain-text stderr
|
|
- 2026-09-21: shutdown lifecycle correctness. The process now shuts down through
|
|
fx instead of `os.Exit`, so every component's `OnStop` runs and buffered
|
|
reports are flushed to disk on `SIGTERM` — previously a full flush window of
|
|
telemetry was silently lost on every restart. The `http.Server` is now built
|
|
before its serving goroutine starts, so shutdown can no longer race or
|
|
nil-deref it; a listen failure exits non-zero via `fx.Shutdowner`; `reportbuf`
|
|
`OnStop` is idempotent; and `writeTimeout` now exceeds the chi per-request
|
|
budget so that budget is actually reachable. Dead `startupTime`, `exitCode`,
|
|
and `cancelFunc` fields were removed
|
|
- 2026-09-21: backend HTTP hardening (issue #19): added `ReadHeaderTimeout` and
|
|
`IdleTimeout` to the server, a `SecurityHeaders` middleware (HSTS, tight CSP,
|
|
frame/sniff/referrer/permissions headers) registered before CORS, and
|
|
trusted-proxy client IP resolution honouring `X-Forwarded-For` / `X-Real-IP`
|
|
only from a `TRUSTED_PROXIES` allowlist (loopback plus RFC1918 by default)
|
|
- 2026-08-10: every interactive control now meets the 44x44 CSS px minimum tap
|
|
target (`.pin-btn`, `#interval-select`, the debug-log label and, on narrow
|
|
viewports, `#pause-btn`). The pin button's hit area grows via matching
|
|
negative margins, so its layout footprint and row density are unchanged
|
|
- 2026-08-10: per-host status line wraps below the 768px breakpoint instead of
|
|
forcing horizontal page scroll at 320px
|
|
- 2026-08-09: `Dockerfile.backend` reworked to the mandated Go multistage
|
|
lint-stage pattern: separate `lint` stage on the hash-pinned
|
|
`golangci/golangci-lint` image, `COPY --from=lint` stage dependency,
|
|
`CGO_ENABLED=0` static build driven by `ARG VERSION`, and no more `COPY .git`
|
|
- 2026-08-09: dotfile compliance — lifted `backend/.editorconfig` to the repo
|
|
root so `root = true` covers the frontend too, and replaced `.gitignore` with
|
|
the org model (OS, editor, node, and environment/secrets sections) plus this
|
|
repo's `dist/` and `*.log`. `.env`, `.env.*`, `*.pem`, and `*.key` are now
|
|
ignored repo-wide, not just under `backend/`. Excluding `.git` from
|
|
`.dockerignore` stays deferred: both images read git metadata at build time
|
|
(`COPY .git` in `Dockerfile.backend`, `git rev-parse` in `vite.config.js`)
|
|
- 2026-08-09: automated responsive-layout harness
|
|
(`make frontend-viewport-test`): digest-pinned headless Chrome driven over CDP
|
|
against the built `dist/`, viewport widths derived from the breakpoints in
|
|
`src/styles.css` ([#13](https://git.eeqj.de/sneak/netwatch/issues/13)). Every
|
|
check carries a presence guard so none of them can pass against a page it is
|
|
not actually measuring. Found two real layout defects, filed as
|
|
[#42](https://git.eeqj.de/sneak/netwatch/issues/42) and
|
|
[#43](https://git.eeqj.de/sneak/netwatch/issues/43)
|
|
- 2026-07-07 Adopted scripts-to-rule-them-all: `script/` entrypoints, Makefile
|
|
shims, README Entrypoints section
|
|
- 2026-02-27: backend with buffered zstd-compressed report storage; CI workflow
|
|
and backend repo standard files; backend Dockerfile fixed (Go 1.25,
|
|
golangci-lint) and moved to repo root (feat/reportbuf-storage, unmerged)
|
|
- 2026-02-26: host row layout redesigned with CSS grid; overflow and spacing
|
|
fixes; nginx config extracted; port hardcoded to 8080
|
|
- 2026-02-26: debug log panel, median stats, recovery probe, Docker build fix,
|
|
S3 Singapore endpoint added
|
|
- 2026-02-23: summary box redesign, host pinning, local and UTC clocks, checks
|
|
counter
|
|
- 2026-02-23: hosts sorted by latency; GET instead of HEAD for latency; timeout
|
|
derived from interval; Hetzner regional endpoints; 3s interval
|
|
- 2026-01-29: initial NetWatch network latency monitor
|
|
|
|
# Future Steps
|
|
|
|
- Wire `script/frontend-viewport-test` into CI as its own step (deliberately not
|
|
part of `make check` today; the decision has real CI-runtime cost and is
|
|
tracked separately)
|
|
- Compliance top-up as one small commit: add .editorconfig and add the hooks
|
|
target to the Makefile
|
|
- After merge, confirm .gitea/workflows/check.yml is on main and CI is green
|
|
(main always green policy)
|
|
- Decide what to do with untracked resume.sh: commit it, gitignore it, or delete
|
|
it
|