Commit Graph

4357 Commits

Author SHA1 Message Date
rcourtman 0a58e77bc6 Eliminate remaining frontend template drift 2026-08-24 21:52:47 +01:00
rcourtman a3d7a90b1b Canonicalize platform frontend contracts 2026-08-24 18:56:56 +01:00
rcourtman 164e03ad3c Keep Storage table headers plain 2026-08-24 17:30:21 +01:00
rcourtman baabed91a6 Remove mobile table chevron exception 2026-08-24 17:18:55 +01:00
rcourtman 3d77ac9cec Canonicalize sortable table indicators 2026-08-24 17:06:20 +01:00
rcourtman e140ee2071 Canonicalize object detail history navigation 2026-08-24 16:59:57 +01:00
rcourtman 32b721503c Canonicalize mobile row disclosure affordances 2026-08-24 16:41:06 +01:00
rcourtman b67ac28f25 fix(monitoring): clear host removal blocks from every store on re-enroll
allowHostAgentReenrollLocked trusted only the durable continuity store
when one was attached, so a removal block living only in persisted
monitor state (written by releases predating the store) could never be
cleared: every fresh re-enroll read as already-consumed and the host
was rejected with 400 on every report indefinitely, regardless of new
tokens or reinstalls.

Refs #1772
2026-08-24 16:36:22 +01:00
rcourtman 8d9d567f62 fix(monitoring): honor fixed poll intervals when adaptive scheduling is off
With the adaptive scheduler disabled (the default), every planning pass
on the main poll tick rebuilt each instance task with NextRun=now and
Upsert overwrote the pending slot, so availability targets polled at
the tick cadence regardless of their configured interval. Reproduced
at exactly 10s polling on a 60s ICMP target; c70431caa only covered
the adaptive-scheduler path. Planning now preserves a pending future
slot, tightening it only when a freshly shortened interval justifies
an earlier run.

Refs #1745
2026-08-24 16:36:22 +01:00
rcourtman faf6425d0f Disable hover tooltips for touch interactions 2026-08-24 16:32:38 +01:00
rcourtman 714b26b69f Canonicalize platform table row density 2026-08-24 16:19:21 +01:00
rcourtman 9c7cb9ed9b Require demand_evidence on candidate_lane registration
Every candidate_lanes record now carries demand_evidence: dated pointers
to the demand signals justifying the proposed lane (issues, discussions,
support threads, telemetry findings, or a demand-ledger entry in
pulse-pro/FEATURE_REQUESTS.md), or an explicit named-bet declaration for
maintainer-originated lanes with no external signal yet. The schema
requires the field, status_audit rejects missing or empty lists and
surfaces the evidence in the candidate_lanes and candidate_lane_queue
pretty blocks, and the canonical development protocol documents the
rule. No data migration needed; candidate_lanes is currently empty.
2026-08-24 15:59:32 +01:00
rcourtman 7e363e40e7 Make drawer headers full-width collapse targets 2026-08-24 15:40:29 +01:00
rcourtman 6991208ad6 Register host-identity fork-heal coverage gap
PR #1715 fixed the discovery symptom of forked host identities
(0e8f63cdd): lookups now resolve across the '<base>-<hex>' fork
spellings. The identity defect underneath remains: a re-enrollment
under a new token forks the host and the only heal path
(hostRenameHealSource) requires the same token plus a changed hostname
plus three missed health windows, so a re-enrollment fork fails two of
the three conditions structurally and is held open forever. Every
identity consumer must resolve equivalent spellings indefinitely or
silently miss records.

Healing at the source is clone-safety territory (#1584), so it is
registered as a triaged coverage gap for an owned agent-lifecycle
slice rather than an opportunistic patch. The evidence record carries
the verified heal-path conditions and the field-observed fork shapes,
including the truncated double fork.
2026-08-24 15:25:38 +01:00
rcourtman 08e501bbc8 Unify drawer detail density 2026-08-24 14:59:02 +01:00
rcourtman f1aee5ccd1 Hide disabled Discovery from drawers 2026-08-24 13:15:45 +01:00
rcourtman 66fd37ee6f Simplify object drawer headers 2026-08-24 12:48:31 +01:00
rcourtman 9e622c291d Improve object drawer information hierarchy 2026-08-24 12:37:39 +01:00
rcourtman a73abe909c Show healthy backup shields in compact rows 2026-08-24 12:04:07 +01:00
rcourtman 78be1b1c2a Raise adaptive node preview thresholds 2026-08-24 11:52:56 +01:00
rcourtman 1fbf10e2c2 Move node preview control below table 2026-08-24 11:33:10 +01:00
rcourtman b932dbf975 Align Guests with table header chrome 2026-08-24 11:25:04 +01:00
rcourtman a585eab712 Canonicalize mobile row disclosures 2026-08-24 11:09:53 +01:00
rcourtman e9fdd18570 Make large-estate navigation and updates incremental 2026-08-24 10:39:15 +01:00
rcourtman dec1c94c27 Define recovery list pagination bounds once in the recovery model
Follow-up to 6686cdce2: the 100-default/500-max list page bounds existed
as separate untyped constants in internal/api and internal/recovery/store,
relying on a contract clause to keep them aligned. Export
DefaultListPageLimit / MaxListPageLimit from internal/recovery/model
(re-exported through internal/recovery) and alias both consumers to them,
so drift is impossible by construction. store_test.go and
recovery_handlers_test.go pin both consumers to the shared constants;
the three pagination-meta contract clauses now name the single source.
2026-08-24 10:21:10 +01:00
rcourtman 9e37d629ac Measure node connection test outcomes
Telemetry could see only saved connections, so an install that tried to
reach a node and could not was indistinguishable from one that never
opened the add-node dialog. Both report zero configured connections and
stall at the same activation stage. Fleet data shows that population is
real and concentrated three to one in container deployments, and nothing
recorded whether those installs attempted a connection at all.

Record node connection test attempts and failures in a bounded,
day-bucketed tally in the config directory, pruned to a 31-day retention
window, and report both over the install-ID rotation window as
node_test_attempts_30d and node_test_failures_30d.

Recording starts only once a request carries a target and credentials, so
an incomplete form is never counted as a node that could not be reached.
A host string that turns out to be unusable does count, because the
attempt was made and it failed. Only the add-node dialog endpoint is
instrumented: instrumenting the unused test-config endpoint as well would
double-count a single operator action.

The tally holds counts alone. Hosts, credentials, and error text never
enter it, which is why it is plain JSON rather than encrypted history.
2026-08-24 10:17:17 +01:00
rcourtman 6417319b1e Accept build-output proof for vite.config.ts commits
The deployment-installability verification policy routed
frontend-modern/vite.config.ts through the dev-runtime orchestration
proof set, all of which exercise the unbuilt hot-dev runtime. No
accepted proof could observe production build output, which is why
c4af728c0 (preload posture change) needed
PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT.

Split vite.config.ts into its own frontend-build-output path policy:
the accepted set keeps every dev-runtime proof, so dev-server-facing
edits are unchanged, and adds
frontend-modern/scripts/check-bundle-size.mjs, which now also asserts
the built index.html posture the contract clause pins: modulepreload
links limited to the entry's static imports (no lazy route chunks) and
import map integrity coverage of every built JS asset. The guard test
pins the new policy's accepted set.

Verified against the built output: flipping preloadDynamicChunks to
true fails the check with 47 lazy-chunk preload violations; the
healthy build passes. Full canonical-governance chain run locally, all
exit 0.
2026-08-24 09:23:03 +01:00
rcourtman 6686cdce2c Report recovery pagination meta from the normalized limit
/api/recovery/points and /api/recovery/rollups clamp the requested page
size to [100 default, 500 max] in both the mock paginators and the store
paths, but the meta block was computed from the raw query value. A client
requesting limit=1000 with 1200 rollups was told totalPages=2 while the
server served 3 pages of 500, so iterating totalPages silently dropped
rollups; limit<=0 reported totalPages=1 at an effective limit of 100.

Normalize page and limit once at parse time, compute meta from the
normalized values, and echo the effective limit. Contract clause 34 in
api-contracts.md pins the obligation; storage-recovery and agent-lifecycle
record the boundary alignment and adjacency; recovery_handlers_test.go
pins above-max and non-positive limit meta.
2026-08-24 09:18:36 +01:00
rcourtman 29cbf73bba Register resource-payload static-metadata coverage gap
The browser performance audit measured the client-facing resource
stream as a primary scalability cost at estate scale: a 4.73MB
single-frame snapshot at 1,508 resources, ~3KB of mostly-static
metadata per resource (only 10 distinct capabilities blobs across the
whole estate, identity alias history, aiSafeSummary prose, and policy
routing shipped to every browser), and ~1s of blocked main thread per
delta on desktop hardware. Slimming the stream is a wire-format change
with consumers beyond frontend-modern (pulse-mobile OTA compatibility,
Pro surfaces, AI runtime), so it is registered as a triaged coverage
gap for an owned slice instead of an opportunistic patch. Evidence
record carries the measured payload composition.
2026-08-24 09:04:16 +01:00
rcourtman c4af728c0d Stop modulepreloading every lazy chunk at cold start
The SRI plugin's default preloadDynamicChunks injected modulepreload
links for all ~50 lazy chunks into the built index.html — 3.1MB raw
(4.2MB decoded): every Settings panel, Alerts, Chat, AI Intelligence,
all six platform pages, and both locale bundles fetched and compiled up
front, defeating route-level code splitting exactly where it matters
(slow devices, tab-evicted mobile browsers that cold start often).

Disable dynamic-chunk preloading; the entry keeps its three static
vendor preloads and dynamic-import integrity stays enforced through the
generated import map integrity block (112 entries verified in the built
output). Measured on a 4x-CPU-throttled mobile profile against the
50-node mock estate: cold-load long tasks 32s -> 18s, scripts fetched
99 -> 62, decoded JS 4.2MB -> 2.3MB.

Contract-Neutral: build-output preload posture change: deployment-installability's dev-runtime orchestration proof files all run the unbuilt hot-dev runtime and cannot observe built index.html preloads; verified instead by direct built-output inspection (0 route-chunk preloads, 112 importmap integrity entries) and 4x-throttle before/after measurement; substantive contract clause ships in this same commit
2026-08-24 09:02:21 +01:00
rcourtman 6d3ec88769 Stabilize nav tab identity across websocket ticks
The primaryTabs/utilityTabs memos in AppLayout rebuild their arrays from
live store reads; activeAlerts is replaced wholesale whenever a state
frame carries it, so every reference-keyed <For> consumer (desktop tab
strip and the mobile bottom bar) tore down and recreated all nav buttons
even when nothing visible changed. Probed on the 50-node mock estate:
3 of 4 mobile bottom-bar buttons and 4 of 10 desktop tabs were detached
within 40s of websocket frames; taps landing mid-rebuild die silently.

Reuse previous tab object references (and the previous array identity)
when a rebuilt list is structurally unchanged, so downstream <For>s keep
their DOM. With the fix the same 40s probe keeps every nav element
connected on both form factors. MobileNavBar's proof suite now pins the
DOM-identity behavior and App.architecture pins the stabilizer wiring;
contract notes recorded in frontend-primitives, cloud-paid, and
ai-runtime.
2026-08-24 08:58:49 +01:00
rcourtman 17bb2b3b7d Scale large-estate rendering and navigation 2026-08-24 00:31:39 +01:00
rcourtman 87ee3cd449 Fix command policy after agent reinstall
Project freshly minted installer command intent onto the stable host before returning remote config, and consume that intent once so later admin policy changes remain authoritative.
2026-08-23 23:39:20 +01:00
rcourtman fd7f4156ca Fix large-estate storage rendering performance 2026-08-23 22:20:03 +01:00
rcourtman 1d3ee7a1b3 Align Proxmox node search with visible guests 2026-08-23 21:59:22 +01:00
rcourtman 6794971199 Eliminate large-estate scroll blanks 2026-08-23 20:18:48 +01:00
rcourtman 10116cc17e Scale large-estate realtime monitoring 2026-08-23 19:58:40 +01:00
rcourtman 771d583f4a Sync Proxmox node table with workload search 2026-08-23 19:31:34 +01:00
rcourtman 35b8c0a4c2 Canonicalize Proxmox backup view routes 2026-08-23 18:12:22 +01:00
rcourtman ae9cfb1da8 Restore mobile Proxmox node visibility 2026-08-23 17:48:00 +01:00
rcourtman 4182f79028 Eliminate workload virtualization scroll gaps 2026-08-23 17:05:15 +01:00
rcourtman d8fe2a9358 Stabilize large-estate workload scrolling 2026-08-23 16:32:53 +01:00
rcourtman 4040a79f4f Fix workload virtualization scroll ownership 2026-08-23 15:51:40 +01:00
rcourtman 3bc613c915 Scale large-estate workload and Proxmox demo performance 2026-08-23 15:09:32 +01:00
rcourtman 6869612c66 Isolate PC compilation from SignPath workflow 2026-08-23 15:02:33 +01:00
rcourtman 32d7b22996 Use trusted PC for release compilation 2026-08-23 14:41:11 +01:00
rcourtman 567eca2572 Harden stable release convergence 2026-08-23 14:21:09 +01:00
rcourtman 2f3d224997 Use hosted container qualification for stable releases 2026-08-23 12:43:18 +01:00
rcourtman 0f369a4b0d Use hosted compilation for stable releases 2026-08-23 12:16:14 +01:00
rcourtman c1d0aaa0d5 Approve v6.3.1 unsigned Windows exception 2026-08-23 12:02:53 +01:00