Commit Graph

143 Commits

Author SHA1 Message Date
lerko 5401266e83 refactor(tui): two-tier responsive table layout (compact/wide at 120 cols)
CI / test (pull_request) Successful in 2m54s
CI / lint (pull_request) Failing after 1m12s
CI / vulncheck (pull_request) Successful in 56s
Replace continuous surplus distribution with two fixed layouts per table.
Breakpoint at 120 columns — matches how btop/k9s do it.

Compact (<120): short headers (LAT, UP%, RT, ST, MON, SENT, VER),
  tight fixed widths, no surplus guessing.

Wide (≥120): full headers (LATENCY, UPTIME, RETRIES, STATUS, MONITORS,
  LAST SENT, VERSION), generous widths.

Sites tab keeps content-aware NAME sizing + sparkline flex.
All other tabs (Alerts, Maint, Nodes, Users) use simple fixed tiers.

Removed old computeTableLayout/colDef/tierCol/pickTier — no longer needed.
2026-05-28 15:50:23 -04:00
lerko a84f4894f8 fix(tui): maint tab — MONITORS is flex, dates get room, time adapts to width
CI / test (pull_request) Successful in 2m46s
CI / lint (pull_request) Failing after 1m7s
CI / vulncheck (pull_request) Successful in 51s
TITLE was flex eating all space while dates/monitors squeezed. Flipped:
MONITORS is now flex, TITLE fixed (12-24), dates min 14, STATUS min 11.
fmtMaintTime uses compact format (Jan 02) at narrow widths.
2026-05-28 15:40:18 -04:00
lerko d9dcd58b66 fix(tui): maint tab min widths fit 80-column terminals
CI / test (pull_request) Successful in 2m49s
CI / lint (pull_request) Failing after 1m12s
CI / vulncheck (pull_request) Successful in 56s
Reduce minimums so fixedMin=51 (was 71). At narrow: compact headers (ST, MON).
At wide: full headers (STATUS, MONITORS, STARTED) with expanded widths.
2026-05-28 15:31:01 -04:00
lerko 251c723fbd fix(tui): maint tab — bump MONITORS/STARTED/ENDS min widths, respect column width
CI / test (pull_request) Successful in 2m50s
CI / lint (pull_request) Failing after 1m1s
CI / vulncheck (pull_request) Successful in 56s
MONITORS min 13→15 (monitor names can be long, truncate to column width).
STARTED/ENDS min 10→14 (fits '18:30 May 28' = 12 chars + padding).
fmtMaintMonitorW truncates name to actual column width.
2026-05-28 15:24:25 -04:00
lerko eb61a0dd3c fix(tui): increase maint tab min column widths for TYPE/MONITORS/STATUS
CI / test (pull_request) Successful in 2m51s
CI / lint (pull_request) Successful in 1m6s
CI / vulncheck (pull_request) Successful in 51s
TYPE min 10→13 (fits 'maintenance'), MONITORS min 10→13, STATUS min 8→11
(fits 'SCHEDULED'). Prevents word wrapping.
2026-05-28 15:22:18 -04:00
lerko d05bbd007b feat(tui): responsive table layout for all tabs
CI / test (pull_request) Successful in 2m45s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 1m6s
Extract shared computeTableLayout() into table_helpers.go — takes column
definitions with short/full headers, min/max widths, and a flex column
that absorbs surplus space. All tabs now use it:

- Alerts: CONFIG column is flex, NAME/TYPE/SENT expand with width
- Maint: TITLE column is flex, TYPE/MONITORS/STATUS/dates expand
- Nodes: NAME column is flex, REGION/LAST SEEN/VERSION expand
- Users: PUBLIC KEY column is flex, USERNAME expands
- Sites: uses same colDef type (keeps special dual-flex for NAME+HISTORY)

Headers auto-switch short/full based on available width across all tabs.
2026-05-28 15:20:12 -04:00
lerko 217276ca18 fix(tui): correct table border overhead calculation
CI / test (pull_request) Successful in 2m54s
CI / lint (pull_request) Successful in 1m6s
CI / vulncheck (pull_request) Successful in 56s
Was hardcoded to 30 — actual overhead is 2 (borders) + numCols-1
(separators) = 10 for 9 columns. The 20-char gap was being
redistributed by lipgloss into columns like # making them too wide.
2026-05-28 15:11:29 -04:00
lerko 2e489cdc1a fix(tui): apply Width/MaxWidth to header row cells too
CI / test (pull_request) Successful in 2m36s
CI / lint (pull_request) Successful in 1m1s
CI / vulncheck (pull_request) Successful in 54s
Header row was returning bare tableHeaderStyle with no width constraints,
letting lipgloss table-level Width() inflate the # column.
2026-05-28 15:04:38 -04:00
lerko 2569a252ff fix(tui): enforce column MaxWidth to prevent lipgloss redistribution
CI / test (pull_request) Successful in 2m50s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
lipgloss table with Width(tableWidth) redistributes surplus space across
all columns. Adding MaxWidth() caps each column to its computed width.
Also dump any remaining surplus into the HISTORY sparkline column.
2026-05-28 14:18:32 -04:00
lerko 9121b79582 fix(tui): prevent # and SSL columns from expanding unnecessarily
CI / test (pull_request) Successful in 2m48s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 56s
Set min=max for columns that don't benefit from extra width.
Surplus space goes to sparkline instead.
2026-05-28 13:58:04 -04:00
lerko 2c78c60d08 fix(tui): set explicit NAME column width to match content truncation
CI / test (pull_request) Successful in 2m41s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
Was width=0 (auto) which let lipgloss over-allocate the column,
causing visible empty space between truncated names and TYPE column.
Now set to nameW explicitly so column width = truncation limit.
2026-05-28 13:52:24 -04:00
lerko c5477c7ef6 fix(tui): size NAME column to actual content, surplus goes to sparkline
CI / test (pull_request) Successful in 2m44s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 56s
Compute max monitor name length and cap NAME column to that + 4 (icon/padding).
Extra space goes to HISTORY sparkline instead of dead whitespace.
2026-05-28 13:39:00 -04:00
lerko ecdb1a6632 fix(tui): increase LAT/UPTIME min column widths to prevent wrapping
CI / test (pull_request) Successful in 2m59s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 1m2s
LAT min 5→7 (fits '142ms' + padding), UPTIME min 5→8 (fits '100.0%' + padding).
2026-05-28 13:35:55 -04:00
lerko 82d7b2942b feat(tui): responsive table columns — expand headers with terminal width
CI / test (pull_request) Successful in 2m48s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 51s
Replace hardcoded column widths with dynamic layout system:
- Each column has short/full header and min/max width
- At narrow terminals: LAT, UP%, RT, compact widths
- At wide terminals: LATENCY, UPTIME, RETRIES, expanded widths
- Surplus space distributed left-to-right across expandable columns
- Headers switch between short/full based on actual column width

Column definitions:
  # (4-6)  TYPE (8-10)  STATUS (8-10)  LAT/LATENCY (5-10)
  UP%/UPTIME (5-8)  SSL (5-7)  RT/RETRIES (5-9)
2026-05-28 13:28:08 -04:00
lerko af5246e777 chore(tui): visual polish — detail sections, column headers, alert detail
CI / test (pull_request) Successful in 2m41s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 51s
Detail panel:
- Grouped fields into sections (ENDPOINT, TIMING, HTTP, CONFIG)
- Omit Timeout when 0 (unconfigured)
- Omit Method when default GET
- Show explicit "200-299" when AcceptedCodes empty

Table:
- LATENCY header → LAT (design short, never truncate)

Alerts:
- Press [i] for alert detail panel: full config, health status,
  send counts, last error
- Keybinding display updated with [i]Info

Bundled remaining UX polish items from screenshot review.
2026-05-28 13:18:27 -04:00
lerko 26e297cbae Merge pull request 'feat: alert channel health indicator + test alerts' (#36) from feat/alert-health into main
CI / test (push) Successful in 2m48s
CI / lint (push) Successful in 1m17s
CI / vulncheck (push) Successful in 1m6s
Reviewed-on: lerko/uptop#36
2026-05-28 01:33:00 +00:00
lerko 0aa2f9cd8a feat: alert channel health indicator + test alerts
CI / test (pull_request) Successful in 2m46s
CI / lint (pull_request) Successful in 1m1s
CI / vulncheck (pull_request) Successful in 51s
Track alert delivery health at runtime:
- AlertHealth struct: LastSendAt, LastSendOK, LastError, SendCount, FailCount
- triggerAlert records success/failure after each Send()
- Health data exposed via GetAlertHealth() for TUI

Alerts tab enriched:
- Health dot column: green (OK), red (failed), gray (never sent)
- LAST SENT column: relative time ("2m ago", "never")
- [t] key sends test notification through selected channel

Inspired by Grafana's contact point health columns.
2026-05-27 21:23:06 -04:00
lerko f17f06a1c6 Merge pull request 'feat: logs tab overhaul — severity tags, filtering, recovery durations' (#35) from feat/logs-overhaul into main
CI / test (push) Successful in 2m47s
CI / lint (push) Successful in 1m16s
CI / vulncheck (push) Successful in 56s
Reviewed-on: lerko/uptop#35
2026-05-28 00:35:24 +00:00
lerko b14d5e19db feat: logs tab overhaul — severity tags, filtering, recovery durations
CI / test (pull_request) Successful in 2m36s
CI / lint (pull_request) Successful in 1m1s
CI / vulncheck (pull_request) Successful in 51s
Logs tab visual overhaul:
- Severity-classified entries: DOWN (red), UP (green), WARN (amber),
  SYS (cyan), info (gray) — rendered as inline tags, not whole-line color
- Column-aligned format: [timestamp] [severity tag] [message]
- Filter toggle (f key): All vs Important only (hides retry noise)
- Header shows entry count, filter state, hidden count

Engine log improvements:
- Recovery messages include downtime duration ("was down 14m")
- LATE transition logged ("heartbeat overdue")
- Push monitor recovery includes downtime duration
2026-05-27 20:14:43 -04:00
lerko a2b38ddc60 Merge pull request 'feat: proper push monitor lifecycle — PENDING, LATE, DOWN' (#34) from feat/push-monitor-states into main
CI / test (push) Successful in 2m48s
CI / lint (push) Successful in 1m17s
CI / vulncheck (push) Successful in 56s
Reviewed-on: lerko/uptop#34
2026-05-28 00:01:56 +00:00
lerko 5dc31108f8 feat: proper push monitor lifecycle — PENDING, LATE, DOWN states
CI / test (pull_request) Successful in 2m41s
CI / lint (pull_request) Successful in 1m7s
CI / vulncheck (pull_request) Successful in 46s
Push monitors no longer lie about status:

- PENDING stays until first heartbeat (no auto-promote to UP)
- LATE state (amber) when overdue but within grace period
- DOWN only after grace period expires
- Grace period = interval/2, minimum 60s

RecordHeartbeat now handles all transitions:
- PENDING → UP (first heartbeat, logged)
- LATE → UP (late arrival, logged)
- DOWN → UP (recovery, alert + state change persisted)

TUI updates:
- LATE rendered in amber/warning color
- Status bar shows LATE count separately
- Tab badge shows ⚠ for late monitors
- Sort order: DOWN > LATE > UP > PENDING > PAUSED
- Detail panel shows error for LATE monitors

Inspired by Healthchecks.io state machine (new/up/grace/down).
2026-05-27 19:56:50 -04:00
lerko 63773b13d0 Merge pull request 'feat: show error reason when monitors go DOWN' (#33) from feat/error-reason into main
CI / test (push) Successful in 2m51s
CI / lint (push) Successful in 1m1s
CI / vulncheck (push) Successful in 56s
Reviewed-on: lerko/uptop#33
2026-05-27 23:38:26 +00:00
lerko bc3a44beac feat: show error reason when monitors go DOWN
CI / test (pull_request) Successful in 2m42s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 51s
Propagate check failure reasons through the entire stack:
- Checker captures specific errors (DNS, timeout, HTTP status, SSL, etc.)
- Engine tracks LastError, StatusChangedAt, LastSuccessAt per monitor
- State transitions persisted to new state_changes table
- Detail panel shows error reason, HTTP code, state duration, last
  success time, and last 5 state change events
- Monitor table shows inline error preview for DOWN services
- Alert messages include error reason
- Probe nodes forward error reasons to leader

15 files changed across models, checker, engine, store, TUI, and probes.
2026-05-27 19:32:30 -04:00
lerko d8a2cab90f feat: seed SSH users from env var and authorized_keys file (#31)
CI / test (push) Successful in 2m36s
CI / lint (push) Successful in 1m12s
CI / vulncheck (push) Successful in 56s
Release / release (push) Has been cancelled
Release / docker (push) Has been cancelled
## Summary

Docker onboarding was broken — no way to add first SSH user without `docker attach` to TUI.

Now reads SSH public keys from two sources on startup:
- `UPTOP_ADMIN_KEY` env var — single key for quick single-user setup
- `UPTOP_KEYS` file path — authorized_keys format for team setup

Dockerfile already sets `UPTOP_KEYS=/data/authorized_keys` and compose mounts `./data:/data`, so the flow is:

```
echo "ssh-ed25519 AAAA... me@host" > ./data/authorized_keys
docker compose up -d
ssh -p 23234 localhost
```

### Behavior
- Skips keys already in DB (idempotent across restarts)
- All seeded users get admin role
- Username parsed from key comment (e.g. `tyler@macbook` → `tyler`)
- Comments and blank lines in keys file are ignored

### Tested
- UPTOP_ADMIN_KEY seeds single admin user
- UPTOP_KEYS file seeds multiple users with correct usernames
- Second startup skips existing keys (no duplicates)
- Build and all tests pass

Reviewed-on: lerko/uptop#31
2026.05.4
2026-05-27 21:15:00 +00:00
lerko ea721601ab Merge pull request 'ci: overhaul pipeline — caching, GoReleaser, govulncheck' (#30) from ci/pipeline-overhaul into main
CI / test (push) Successful in 2m50s
CI / lint (push) Successful in 1m11s
CI / vulncheck (push) Successful in 56s
Reviewed-on: lerko/uptop#30
2026-05-27 00:37:32 +00:00
lerko b1935aa682 fix(deps): bump golang.org/x/crypto v0.47.0 → v0.52.0
CI / test (pull_request) Successful in 2m46s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 56s
Fixes 7 vulns (GO-2026-5014 through GO-2026-5023) found by govulncheck.
Also bumps x/net, x/sys, x/text, x/sync, x/mod, x/tools to latest.
2026-05-26 20:20:23 -04:00
lerko 2cd3dcddb4 chore: bump Go 1.24.4 → 1.26.3, Alpine 3.21 → 3.23
CI / test (pull_request) Successful in 2m57s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Failing after 1m1s
Go 1.24 EOL since Feb 2026. Fixes 33 stdlib vulns found by
govulncheck (database/sql, os/exec, net/http). Gets Green Tea GC.
2026-05-26 20:12:43 -04:00
lerko 7d4ef1f594 fix(ci): remove explicit container, use sh shell
CI / test (pull_request) Successful in 2m44s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Failing after 1m7s
Act runner is Alpine-based — container: directive breaks node-based
actions (checkout, setup-go). Runner already has apk natively.
Added shell: sh to all jobs since runner lacks bash.
2026-05-26 18:44:08 -04:00
lerko f0ff87c0d0 fix(ci): rename GITEA_TOKEN to RELEASE_TOKEN
CI / test (pull_request) Failing after 31s
CI / lint (pull_request) Successful in 1m9s
CI / vulncheck (pull_request) Failing after 15s
Gitea reserves the GITEA_ prefix for repo action secrets.
2026-05-26 18:36:11 -04:00
lerko 5aab391b74 ci: overhaul pipeline — caching, GoReleaser, govulncheck
- Add module + build cache to CI (was only caching go-build, not go/pkg/mod)
- Declare explicit Alpine container instead of relying on runner image
- Drop redundant go vet (already in golangci-lint)
- Add govulncheck job for dependency CVE scanning
- Add GoReleaser config for Gitea-native binary releases + checksums
- Replace .github/workflows/docker.yml with .gitea/workflows/release.yml
- Docker multiarch (amd64+arm64) via buildx in release workflow
- Dockerfile: add --mount=type=cache for mod/build, add -trimpath
2026-05-26 18:24:19 -04:00
lerko 8ad213c96c Merge pull request 'fix(security): phase 4 code quality and low-severity fixes' (#29) from security/phase-4-quality into main
CI / test (push) Successful in 4m35s
CI / lint (push) Successful in 1m7s
Reviewed-on: lerko/uptop#29
2026-05-26 21:31:40 +00:00
lerko 986f9f1d55 fix(security): phase 4 code quality and low-severity fixes
CI / test (pull_request) Successful in 4m24s
CI / lint (pull_request) Successful in 1m1s
- Fix limitStr to handle multi-byte UTF-8 characters correctly
- Sanitize log messages: strip ANSI escape sequences and newlines
- URL-encode probe node_id instead of string concatenation
- Fix follower resp.Body leak on non-200 responses
- Make SSH host key path configurable via UPTOP_SSH_HOST_KEY env var
- Add HTTP method checks on GET-only endpoints (405 for wrong methods)
- Extract magic numbers into named constants across monitor/store/server
- Standardize error output to stderr for all startup errors
2026-05-26 17:25:47 -04:00
lerko c50ec82dcb Merge pull request 'fix(security): phase 3 medium reliability and hardening' (#28) from security/phase-3-reliability into main
CI / test (push) Successful in 4m25s
CI / lint (push) Successful in 1m6s
Reviewed-on: lerko/uptop#28
2026-05-26 21:07:30 +00:00
lerko bd561d9a5e fix(security): phase 3 medium reliability and hardening
CI / test (pull_request) Successful in 4m23s
CI / lint (pull_request) Successful in 1m11s
- Fail hard on critical migration errors (ignore only "already exists")
- Cache SSH user keys with 30s TTL (avoid DB query per auth attempt)
- Configure DB connection pooling (25 open, 5 idle, 5m lifetime)
- Enable SQLite WAL mode for concurrent read/write
- Optimize check history pruning (only prune above 1100 rows)
- Add security headers: X-Content-Type-Options, X-Frame-Options, CSP, Referrer-Policy
- Add CORS policy on /status/json via UPTOP_CORS_ORIGIN env var
- Add HTTP request logging middleware (method, path, status, duration, IP)
- Fix config file permissions from 0644 to 0600
- Pin Docker images: golang:1.24-alpine3.21, alpine:3.21
- Fix Docker CI tag pattern for CalVer (was semver)
- Pass build args (VERSION, COMMIT, BUILD_DATE) to Docker build
2026-05-26 16:57:03 -04:00
lerko 7a8f2ad15b Merge pull request 'fix(security): phase 2 high-severity hardening' (#27) from security/phase-2-hardening into main
CI / test (push) Successful in 4m33s
CI / lint (push) Successful in 1m6s
Reviewed-on: lerko/uptop#27
2026-05-26 15:31:18 +00:00
lerko d30d1460bd fix(security): phase 2 high-severity hardening
CI / test (pull_request) Successful in 4m31s
CI / lint (pull_request) Successful in 56s
- Push heartbeat accepts Authorization: Bearer header (query string deprecated)
- Gotify alerts use X-Gotify-Key header instead of token in URL
- Per-IP rate limiting on all API endpoints (token-bucket)
- /metrics gated behind cluster secret (UPTOP_METRICS_PUBLIC=true to opt out)
- Config export redacts passwords/tokens by default (redact_secrets=false to override)
- Fix rewritePlaceholders for 100+ SQL parameters
- Fix AddSiteReturningID/AddAlertReturningID race with LastInsertId/RETURNING
- HTTP server timeouts: read 30s, write 60s, idle 120s
2026-05-25 21:15:33 -04:00
lerko b43dfae98f Merge pull request 'fix(security): phase 1 critical fixes for public release' (#26) from security/phase-1-critical into main
CI / test (push) Successful in 4m19s
CI / lint (push) Successful in 1m6s
Reviewed-on: lerko/uptop#26
2026-05-26 00:43:52 +00:00
lerko 60b30935b3 fix(security): phase 1 critical fixes for public release
CI / test (pull_request) Successful in 4m40s
CI / lint (pull_request) Successful in 1m2s
- Redact PostgreSQL DSN password from stdout/logs
- Harden .dockerignore to exclude .ssh/, .claude/, *.db, *.local files
- SSRF protection: block private/loopback/link-local IPs by default
  (UPTOP_ALLOW_PRIVATE_TARGETS=true to override for homelab use)
- Fix email header injection via CRLF in monitor names
- AES-256-GCM encryption for alert credentials at rest
  (UPTOP_ENCRYPTION_KEY env var, migrate-secrets subcommand)
- TLS support for HTTP server (UPTOP_TLS_CERT/UPTOP_TLS_KEY)
  with HSTS header when TLS enabled
2026-05-25 11:26:47 -04:00
lerko b70edaace5 Merge pull request 'chore: rename project from go-upkeep to uptop' (#25) from chore/rename-uptop into main
CI / test (push) Successful in 4m26s
CI / lint (push) Successful in 1m1s
Reviewed-on: lerko/uptime#25
2026.05.3
2026-05-25 01:02:30 +00:00
lerko 9d12e3ecf1 chore: complete rename from go-upkeep to uptop
CI / test (pull_request) Successful in 4m26s
CI / lint (pull_request) Successful in 1m11s
- Module path: gitea.lerkolabs.com/lerko/uptop
- Binary: cmd/uptop/
- All imports updated to full module path
- Env vars: UPKEEP_* → UPTOP_*
- Prometheus metrics: upkeep_* → uptop_*
- Default DB: uptop.db
- Docker image: lerko/uptop
- All docs, compose files, CI updated

Only remaining "go-upkeep" reference is the fork attribution in README.
2026-05-24 20:20:35 -04:00
lerko 36a4b69837 Merge pull request 'feat(tui): theme system with 5 curated dark palettes' (#24) from feat/themes into main
CI / test (push) Successful in 4m51s
CI / lint (push) Successful in 1m12s
Reviewed-on: lerko/uptime#24
2026-05-24 23:30:25 +00:00
lerko fee84c9363 fix(tui): tighten zebra row contrast for Tokyo Night and Gruvbox
CI / test (pull_request) Successful in 4m48s
CI / lint (pull_request) Successful in 1m11s
Previous ZebraBg was too far from Bg, washing out text on those
themes. Reduced to a 2-step shift for subtle row alternation.
2026-05-24 19:19:51 -04:00
lerko 87edd4aa40 feat(tui): swap light theme for Tokyo Night and Gruvbox
Light theme doesn't work well on dark terminals. Replace with
two proven dark palettes. Now 5 themes: Flexoki Dark, Tokyo Night,
Catppuccin Mocha, Nord, Gruvbox.
2026-05-24 19:10:29 -04:00
lerko 602f1b2c52 feat(tui): add theme system with 4 curated palettes
Flexoki Dark (default), Flexoki Light, Catppuccin Mocha, Nord.
Press T to cycle themes; selection persists in preferences.

All hardcoded colors replaced with theme-driven values.
Dedicated ZebraBg per theme for subtle row striping.
2026-05-24 19:05:40 -04:00
lerko 6e659cf6ee Merge pull request 'fix(tui): scope form validators to relevant monitor types' (#23) from fix/ssl-threshold-validation into main
CI / test (push) Successful in 4m48s
CI / lint (push) Successful in 56s
Reviewed-on: lerko/uptime#23
2026-05-24 22:03:33 +00:00
lerko 0a56f01929 fix(tui): guard max retries validator for group type
CI / test (pull_request) Successful in 4m40s
CI / lint (pull_request) Successful in 1m1s
Consistent with interval/timeout validators that already skip for
group monitors. Prevents potential validation block if field is
cleared while editing.
2026-05-24 17:45:19 -04:00
lerko b5b9cc81a5 fix(tui): skip irrelevant field validation by monitor type
URL, SSL threshold, and port validators blocked form progression
when editing monitors that don't use those fields (e.g. ping monitors
failing URL validation, non-SSL sites failing threshold check).

Scope each validator to fire only for its relevant monitor type.
2026-05-24 17:38:40 -04:00
lerko f64b46f055 Merge pull request 'ci: cache Go build artifacts between runs' (#22) from chore/ci-cache into main
CI / test (push) Successful in 4m40s
CI / lint (push) Successful in 1m12s
Reviewed-on: lerko/uptime#22
2026-05-24 20:01:05 +00:00
lerko d038361320 ci: cache Go build artifacts between runs
CI / test (pull_request) Successful in 6m18s
CI / lint (pull_request) Successful in 56s
2026-05-24 15:52:21 -04:00
lerko d03dc0c1ea Merge pull request 'docs: community polish for public readiness' (#21) from chore/community-polish into main
CI / test (push) Successful in 4m44s
CI / lint (push) Successful in 1m7s
Reviewed-on: lerko/uptime#21
2026-05-24 19:40:00 +00:00