Commit Graph

9257 Commits

Author SHA1 Message Date
rcourtman bbd67e0ae0 docs: clarify security review scope 2026-08-16 16:28:19 +01:00
rcourtman 71347eac4c Decide gzip eligibility before a pre-write flush commits headers
A handler that flushes before its first write commits the response
headers with an implicit 200. The gzip wrapper deferred its
compress-or-not decision to the first write, so such a handler would
send headers without Content-Encoding and then a compressed body,
which clients cannot decode. Every current flusher is an SSE handler
whose content type never compresses, so this was latent, but any
future streaming JSON endpoint would have corrupted silently. Flush
now runs the decision first, matching net/http header-commit
semantics.
2026-08-16 14:08:55 +01:00
rcourtman 3fe1f7f181 Quiet the broadcast ticker and allow larger poll worker pools
The broadcast ticker logged seven fields at Info level every tick and
built a full state snapshot to do it, before checking whether any
WebSocket subscriber existed. An idle server paid a snapshot copy plus
roughly 8600 log lines a day for nothing. The log is now Debug and both
the log and the snapshot build sit behind the subscriber check.

The poll task worker pool was also fixed at ten workers no matter how
many instances an estate monitors. POLL_TASK_WORKERS now overrides the
count and the cap, bounded at 128, following the existing env knob
pattern. Behavior without the variable is unchanged.

Contract-Neutral: operational log demotion and an opt-in worker pool env knob, no monitoring or agent-lifecycle contract semantics change
2026-08-16 13:24:08 +01:00
rcourtman 85db074eff copy: simplify security guidance punctuation
Contract-Neutral: Punctuation-only copy revision with no lifecycle behavior or contract change
2026-08-16 10:36:54 +01:00
rcourtman 20cd89dcc2 Raise the client WebSocket frame ceiling to 32 MiB
The browser advertises max_message_bytes on the upgrade request and the
server withholds any state frame larger than that, falling back to REST
recovery. The advertised value was still the historical 8 MiB, which
pushed estates past roughly 3100 resources off the cheap socket delta
path and onto a 30 second full-state REST poll loop. 32 MiB keeps
estates about four times that size on socket deltas. The server honors
whatever the client advertises, so no backend change is needed.


Contract-Neutral: transport frame-limit constant, no alert lifecycle semantics change
2026-08-16 10:28:30 +01:00
rcourtman 205df735c7 Compress API responses for clients that accept gzip
Large estates that exceed the WebSocket frame ceiling recover over an
uncompressed /api/state poll loop, which made the biggest deployments
pay the heaviest transfer cost. Wrap the main HTTP handler in a gzip
middleware that compresses JSON and other text responses roughly an
order of magnitude, while leaving WebSocket upgrades, SSE streams,
Range requests, small declared bodies, and binary content untouched.


Contract-Neutral: transport-only gzip response middleware, no RBAC or persistence semantics change
2026-08-16 10:28:08 +01:00
rcourtman 787a191a5e docs: publish security review evidence 2026-08-16 10:23:15 +01:00
rcourtman effcf2d50c Harden Patrol qualification lifecycle 2026-08-16 10:14:16 +01:00
rcourtman 88c380b514 docs: add production security deployment guide 2026-08-16 09:21:36 +01:00
rcourtman d0e7c747d9 Clear stale ZFS alerts when a storage loses its pool attachment
checkZFSPoolHealth only runs while storage.ZFSPool is attached, so its
clear paths never fire once the attachment goes away and previously raised
zfs-pool-state, zfs-pool-errors, and zfs-device alerts linger until the
multi-day stale cleanup. Clear them on the spot when a storage is checked
without a pool. This is the recovery path for the shared storages that were
wrongly matched to a node-local pool before the matcher's type gate.

Refs #1731
2026-08-16 06:27:23 +01:00
rcourtman 1ff0680c75 Stop attaching node-local ZFS pools to shared storages
matchZFSPoolForStorage's sole-pool fallback attached the node's only ZFS
pool to every storage the per-node endpoint returned, including NFS, CIFS,
PBS, and RBD entries that can never be backed by a local pool. One failing
device then raised a duplicate ZFS device alert per shared storage. Gate
the matcher on isInherentlySharedStorageType so remote-backed storages are
never matched, while dir-type storages keep the single-pool fallback.

Refs #1731
2026-08-16 06:22:55 +01:00
rcourtman 991b3cad35 Reject empty and blocked Patrol evidence 2026-08-15 22:56:51 +01:00
rcourtman 3cbd684fd4 docs: refine AI transparency wording 2026-08-15 22:55:36 +01:00
rcourtman acef44e162 Restrict Patrol grounding to infrastructure evidence 2026-08-15 22:16:00 +01:00
rcourtman b088319589 Validate all Patrol investigation manifests 2026-08-15 21:37:05 +01:00
rcourtman b3a9edd313 Require successful Patrol investigation evidence 2026-08-15 21:19:44 +01:00
rcourtman 857af3e3cc Keep scoped Patrol investigations grounded 2026-08-15 20:58:49 +01:00
rcourtman 1933a5be37 Align Patrol preflight with the live context envelope 2026-08-15 13:12:30 +01:00
rcourtman 12aa31b506 Keep live Patrol context aligned with readiness 2026-08-15 13:05:15 +01:00
rcourtman 80027e98d6 Project Patrol tools from resource scope 2026-08-15 12:38:41 +01:00
rcourtman 2a15ccbefa Reject unadvertised Patrol tool calls 2026-08-15 12:15:17 +01:00
rcourtman 0d0456f435 Require grounded Patrol investigations 2026-08-15 11:48:51 +01:00
rcourtman 73ce59a1ab Recover Patrol after provider circuit failures 2026-08-15 11:37:02 +01:00
rcourtman 3a99f72a5c Ground Patrol fallback summaries in evidence 2026-08-15 11:01:10 +01:00
rcourtman 2fd184315d Simplify and harden verified Patrol receipts
Contract-Neutral: Patrol compact receipt payload does not change agent lifecycle or storage recovery contracts
2026-08-15 10:25:04 +01:00
rcourtman d3a345bd66 Show verified Patrol work receipts
Contract-Neutral: Patrol receipt API does not change agent lifecycle or storage recovery contracts
2026-08-15 08:48:49 +01:00
rcourtman 7fb39f65cf Honor OpenRouter reasoning limits 2026-08-15 07:04:42 +01:00
rcourtman 746990db34 Require typed Patrol remediation proposals 2026-08-15 06:39:48 +01:00
rcourtman fe1f8d7582 Restrict Patrol objective recovery scope 2026-08-15 06:05:34 +01:00
rcourtman 9ebf084bae Recover truncated Patrol objective missions 2026-08-15 05:48:00 +01:00
rcourtman 3c97a04222 Make Patrol observer missions proposal-only 2026-08-15 05:15:00 +01:00
rcourtman 4efc428bb8 Keep Patrol objectives mission-scoped 2026-08-15 05:00:09 +01:00
rcourtman d218b012d1 Preserve canonical Patrol objective scopes 2026-08-15 04:30:09 +01:00
rcourtman 88de80022c Require Patrol to submit supported actions 2026-08-15 03:53:03 +01:00
rcourtman 0460797aab Bind runtime version to packaged binary 2026-08-15 03:30:20 +01:00
rcourtman 5cffa54620 Map low reasoning effort to Ollama thinking control 2026-08-15 03:15:41 +01:00
rcourtman 0bacc727da Honor local Patrol preflight deadlines 2026-08-15 02:23:48 +01:00
rcourtman 50cfa11f20 Align scoped Patrol runtime assessments 2026-08-15 01:42:07 +01:00
rcourtman a36e816161 Recover interrupted Patrol investigations 2026-08-15 01:26:36 +01:00
rcourtman 98bf51efa4 Make Patrol readiness reflect model checks 2026-08-15 00:57:51 +01:00
rcourtman 1a17525380 Give truncated Patrol decisions room to finish 2026-08-15 00:16:47 +01:00
rcourtman 8ca6936ab8 Fail closed on truncated Patrol decisions 2026-08-14 23:59:06 +01:00
rcourtman aaacfcc73f Honor topology limits for investigations 2026-08-14 23:35:30 +01:00
rcourtman 34cfc70329 Keep scoped Patrol all-clears coherent 2026-08-14 23:12:16 +01:00
rcourtman f0478c769b Accept tool-free Patrol all-clears 2026-08-14 22:42:08 +01:00
rcourtman 9dac6ed517 Move Patrol finding snapshot into core 2026-08-14 22:06:04 +01:00
rcourtman ff15cd93ac Make Patrol lifecycle decisions idempotent 2026-08-14 21:35:18 +01:00
rcourtman 99ee4433d0 Keep reliability signals in Patrol decision floor 2026-08-14 21:07:35 +01:00
rcourtman 2843ea954b Keep alert-owned states out of Patrol findings 2026-08-14 20:37:28 +01:00
rcourtman a3d7659f2c Make Patrol finding decisions idempotent 2026-08-14 20:09:26 +01:00