Commit Graph
336 Commits
Author SHA1 Message Date
mrhid6 eb6f47c8ed fix(monitors): document 403 and 404 on monitor update and delete; regenerate openapi
Chart Release / chart (push) Successful in 18s
Server Deploy / deploy (push) Successful in 4m10s
2026-09-17 09:25:11 +00:00
mrhid6 42766968e3 fix(monitors): keep reboot_required_since on a transient inventory read error 2026-09-17 09:24:42 +00:00
mrhid6 cffa7e84b2 fix(monitors): index heartbeat token hash 2026-09-17 09:24:42 +00:00
mrhid6 2701b32b5f fix(monitors): 400/404 on bad updates, clamp for_sec, reset heartbeat state on re-enable 2026-09-17 09:24:16 +00:00
mrhid6 753ba09e6e fix(mcp): filter list_incidents by the token's visible servers 2026-09-17 09:23:14 +00:00
mrhid6 13e7160405 fix(monitors): rate limit heartbeats per token and kind; test limiter key and fail body cap 2026-09-17 09:22:50 +00:00
mrhid6 2afdc267f8 fix(monitors): keep a down server down while its breach lasts after for_sec is raised 2026-09-17 09:22:50 +00:00
mrhid6 3cb8463dc7 feat(api): metric monitor per-server states and server-scoped incidents 2026-09-17 09:02:35 +00:00
mrhid6 2017c95a7a feat(monitors): sweep metric monitors per server with incidents per breach 2026-09-17 08:59:24 +00:00
mrhid6 4068349afe feat(monitors): validate metric monitors and confine selectors to token scope 2026-09-17 08:56:15 +00:00
mrhid6 f01375470e fix(monitors): ignore partitions reporting more used than total 2026-09-17 08:52:21 +00:00
mrhid6 12136d1c17 feat(monitors): metric rule evaluators and per-server state decisions 2026-09-17 08:40:06 +00:00
mrhid6 1a1f6998a4 feat(inventory): record when a reboot became required 2026-09-17 08:37:41 +00:00
mrhid6 17ed0192c1 feat(monitors): public heartbeat ping endpoints, header token, log masking and sweeper 2026-09-17 08:27:34 +00:00
mrhid6 839d716a47 fix(monitors): guard heartbeat sweep against a concurrent ping 2026-09-17 08:24:13 +00:00
mrhid6 09888825a8 feat(monitors): heartbeat token, ping recording and overdue verdict 2026-09-17 08:20:16 +00:00
mrhid6 590c369d36 fix(notify): include server name in monitor alert email 2026-09-17 08:16:10 +00:00
mrhid6 64dbad1d20 refactor(monitors): extract applyTransition and add passive monitor model fields 2026-09-17 08:14:24 +00:00
mrhid6 189bce55ba feat(runs): mask encoded and multi-line secrets in run logs
Chart Release / chart (push) Successful in 19s
Server Deploy / deploy (push) Successful in 3m25s
Mask base64 and URL-encoded forms of secret values, each line of a
multi-line secret, and secrets loaded by earlier steps of the run.
Replace longer values first so overlapping secrets mask cleanly.
2026-09-17 07:33:20 +00:00
mrhid6 217e2dc5a9 feat(auth): prefer rather than require passkey user verification
Chart Release / chart (push) Successful in 20s
Server Deploy / deploy (push) Successful in 2m59s
Requiring user verification made password managers such as NordPass ask
for their master password on every passkey use. Every ceremony now asks
for it as preferred and no longer rejects a result without it.

This is a deliberate trade-off: a passkey used without verification is
possession-only, so passwordless sign-in and step-up rest on the device or
vault being unlocked. The spec records the decision.
2026-09-16 15:20:31 +00:00
mrhid6 934501f4ec fix(auth): store passkey backup flags so synced passkeys verify
Chart Release / chart (push) Successful in 19s
Server Deploy / deploy (push) Successful in 3m4s
go-webauthn refuses an assertion whose Backup Eligible flag differs from
the stored credential's. The flag was never stored, so it compared against
false and every synced passkey (iCloud Keychain, Google Password Manager,
1Password) failed with "Backup Eligible flag inconsistency" - in
passwordless sign-in, second-factor sign-in and step-up alike.

Registration now stores BackupEligible and BackupState. Rows registered
before this have no baseline, so their first verified assertion adopts the
signed flag and records it; a recorded value always stands, so a genuine
change is still refused.
2026-09-16 15:03:54 +00:00
mrhid6 b1193c59e3 fix(auth): log why a passkey ceremony was refused
Chart Release / chart (push) Successful in 18s
Server Deploy / deploy (push) Successful in 3m3s
Every WebAuthn refusal answered "that passkey could not be verified" and
discarded the library's error, leaving a misconfigured relying party
undiagnosable. Log the stage, the derived RP ID and expected origin, the
request's Origin and X-Forwarded-Proto, and the library error with its
DevInfo. None of it is secret.
2026-09-16 14:51:55 +00:00
mrhid6 069e7e7c61 fix(api): declare MFA routes session-only so the server boots
Chart Release / chart (push) Successful in 36s
Server Deploy / deploy (push) Successful in 3m0s
The MFA routes were missing from routeScopes and serverScopedRoutes, and both
boot assertions refused to start the server. They are deliberately not
reachable by API tokens, so they go in a new sessionOnlyRoutes set rather than
receiving a scope, and are declared exempt from server scoping.

Adds a test that registers the real routes and runs both boot assertions, so
an undeclared route fails CI instead of production startup.
2026-09-16 14:40:29 +00:00
mrhid6 19383abaf8 fix(auth): final-review MFA fixes F1 F2 F3 F5 F7 and drop Ticket.Attempts
Chart Release / chart (push) Successful in 18s
Server Deploy / deploy (push) Successful in 5m51s
- OIDC sessions minted through saveSignIn with AMR oidc and StepUpAt
- passwordless passkey uses ValidateDiscoverableLogin with owner-handle check
- TOTP replay guard burns the matched step, not the current one
- enrol-only tickets refused once the user already has a factor
- bootstrap owner session minted through mintSession
2026-09-16 14:26:42 +00:00
mrhid6 142b99e408 test(mfa): end-to-end coverage, OpenAPI and documentation 2026-09-16 14:18:39 +00:00
mrhid6 14e9db606a fix(mfa): wire up webauthn step-up routes
The missing /me/step-up/webauthn/begin and /finish were a plan defect,
not an acceptable gap: a user whose only factor is a passkey was
offered only recovery codes for step-up, burning one every ten
minutes. Adds the handlers in package auth (session-authenticated,
not themselves behind RequireStepUp, modeled on
HandleMFAWebAuthnBegin/finishAssertion) and registers both routes
behind the same RateLimitAuth() as /me/step-up. StepUpModal now offers
"Use passkey" when the server names webauthn and the browser supports
WebAuthn.
2026-09-16 09:44:41 +00:00
mrhid6 d8597ee3ae feat(mfa): require_mfa policy, sign-in rate limit and MFA column 2026-09-16 09:14:16 +00:00
mrhid6 f87626cf17 feat(mfa): account MFA management, passkey registration and step-up 2026-09-16 09:08:24 +00:00
mrhid6 bd0639acfa fix(mfa): refuse rather than panic when RequireStepUp sees no session 2026-09-16 09:03:22 +00:00
mrhid6 e2ff0dace9 feat(mfa): step-up re-authentication on sensitive actions 2026-09-16 09:01:19 +00:00
mrhid6 d54d8971b2 feat(mfa): passwordless passkey sign-in 2026-09-16 08:58:26 +00:00
mrhid6 14a1cdb2b0 feat(mfa): passkey verification as a second factor 2026-09-16 08:48:39 +00:00
mrhid6 1445af11ab fix(mfa): mint session before deleting ticket, collapse dead invalid_code branch 2026-09-16 08:43:53 +00:00
mrhid6 3fa469c303 feat(mfa): forced TOTP enrolment at sign-in 2026-09-16 08:41:56 +00:00
mrhid6 2d75832ceb feat(mfa): second-factor sign-in with TOTP and recovery codes 2026-09-16 08:39:48 +00:00
mrhid6 dfcfd1d3e2 fix(mfa): make ticket attempt count atomic via Redis INCR 2026-09-16 08:37:07 +00:00
mrhid6 9c60adc836 feat(mfa): pending-login ticket store 2026-09-16 08:34:57 +00:00
mrhid6 330c326fb5 fix(mfa): key TOTP replay guard on time step, not the code 2026-09-16 08:33:02 +00:00
mrhid6 25541345a8 feat(mfa): TOTP secrets, recovery codes and factor lookup 2026-09-16 08:30:55 +00:00
mrhid6 b78a9b3832 feat(mfa): user_mfa and webauthn_credentials collections 2026-09-16 08:27:54 +00:00
mrhid6 9aee0a61aa chore(server): bump vantage-shared to v0.7.0 for require_mfa 2026-09-16 08:22:08 +00:00
mrhid6 fbcf436ef6 feat: show Ubuntu phased updates apart and leave them out of pending counts
Chart Release / chart (push) Successful in 29s
Server Deploy / deploy (push) Successful in 5m9s
apt lists phased updates as upgradable while an upgrade defers them until
Ubuntu selects the host, so a freshly patched server kept reporting pending
updates. The agent now flags them; the server stores the flag and leaves them
out of patch run counts, and the server page shows them in their own section.
2026-09-15 14:55:30 +00:00
mrhid6 fc10575b08 fix: require a 2 minute boot time change before counting a patch reboot
Chart Release / chart (push) Successful in 36s
Server Deploy / deploy (push) Successful in 4m19s
Windows reports boot time as now minus uptime, which drifts by a second or so
between reports. A static report sent in the grace period before the reboot
could read as a changed boot and mark a server still owing a reboot as failed.
2026-09-15 14:09:34 +00:00
mrhid6 3f2d20868e fix(patching): final review fixes
Chart Release / chart (push) Successful in 19s
Server Deploy / deploy (push) Successful in 6m12s
- no dispatch in the last 15 minutes of a window; no-result timeout from dispatch time
- per-server output moves to patch_run_outputs (16MB document limit)
- reboot proven by a changed boot time; RebootTimeout 45m, ResultGrace 20m
- window update and delete are server-scoped against the policies using them
- scheduler puts the claim back on an error after it, so the next tick retries
- cancelled runs with failures alert; MCP apply_updates audits per server
- apply-updates 503 body documented; openapi regenerated
- web: cleared numeric fields no longer save as 0; Run now asks for confirmation
2026-09-15 13:49:28 +00:00
mrhid6 b5bbf28c63 feat: patching REST API, patching scope, run IDs from apply-updates and MCP 2026-09-15 09:31:51 +00:00
mrhid6 17c9f813fc fix: patchsched hasActiveRun must not treat a real DB error as no active run 2026-09-15 09:19:51 +00:00
mrhid6 139658864b feat: patch scheduler loop; record patch results and verify reboots from the agent stream 2026-09-15 09:17:27 +00:00
mrhid6 1bb2ba7f2b fix: patch run dispatch - per-server contexts, cancel race, result command guard
Fix round 1 review findings on the patch run service:
- advanceRun no longer runs every server's dispatch claim and failed-send
  reset on the caller's shared short context; each gets its own fresh
  patchCtx(), and a failed reset write is logged instead of discarded.
- The dispatch claim (queued/waiting_offline -> patching) now also requires
  the run to still be status running with no cancelled_at, closing a race
  where a tick that loaded the run just before CancelPatchRun wrote
  cancelled_at could still dispatch.
- RecordPatchResult's write is now guarded on command_id too, so a late
  result for a superseded command cannot land on a re-dispatched attempt.
2026-09-15 09:09:12 +00:00
mrhid6 fef886c93b feat: patch run service - dispatch, results, reboot verification, cancel, alerts, retention 2026-09-15 09:04:23 +00:00
mrhid6 3a1614066e feat: maintenance window and patch policy services
Named patch_window.go (not patch_windows.go) since the _windows.go
suffix is Go's implicit GOOS build constraint and would silently
exclude the file on non-Windows builds.
2026-09-15 08:50:36 +00:00