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.
This commit is contained in:
rcourtman
2026-08-24 09:04:16 +01:00
parent c4af728c0d
commit 29cbf73bba
2 changed files with 90 additions and 1 deletions
@@ -0,0 +1,52 @@
# Resource payload static-metadata bloat (browser performance audit, 2026-08-24)
## Context
A read-only browser performance audit (2026-08-23/24, production build served by
the dev backend against the 50-node / 929-guest / 1,508-resource mock estate)
measured the client-facing resource stream as a primary scalability cost:
- The full state snapshot is **4.73 MB** of JSON in a single websocket frame
(`/api/state` REST recovery returns the same payload). `resources` accounts
for 4.63 MB — ~3 KB average per resource.
- Idle on the Proxmox overview, the browser main thread was blocked for
**12.0 s out of every 45 s** (individual long tasks of 0.81.4 s roughly
every 34 s, aligned with resource delta frames of up to ~500 KB) on an
unthrottled M-series desktop. Under a 4x CPU throttle (mid-range phone
class), tab taps landing inside those windows blocked for multiple seconds.
## Measured payload composition (per-field bytes across 1,508 resources)
| Field | Bytes | Notes |
| --- | --- | --- |
| `canonicalIdentity` | 0.82 MB | 12 aliases incl. 7 superseded hash ids on a typical VM; identity history ships on every snapshot |
| `proxmox` + `platformData` | 1.36 MB | platform payloads |
| `capabilities` | 0.34 MB | only **10 distinct blobs** across all 1,508 resources — duplicated per resource, including human-readable `description` strings |
| `aiSafeSummary` | 0.14 MB | AI-oriented prose on every resource, shipped to every browser client |
| `policy` | 0.12 MB | near-constant routing metadata per resource |
The websocket delta path is already field-level (JSON merge patches in
`internal/websocket/state_delta.go`), so delta size is driven by estate scale,
not by a diffing defect. The static-metadata weight is paid on every full
snapshot, REST recovery, reconnect, and mobile tab resume.
## Why this is a governed gap rather than a quick fix
Slimming the stream means changing the client-facing resource shape (for
example: a capabilities catalog referenced by id instead of inlined blobs,
identity history behind a detail endpoint instead of inline aliases, and
audience-scoped fields so `aiSafeSummary`/`policy` do not ship to browser
sessions that never read them). That is a wire-format change with consumers
beyond frontend-modern — pulse-mobile (OTA-before-server-release constraint),
Pro/enterprise surfaces, and the AI runtime — and payload fields are not
contract-neutral under the governance rules. It needs an owned slice with
contract updates and cross-client verification, not an opportunistic patch.
## Companion fixes already landed separately
- Nav tab identity stabilization (`frontend-modern/src/components/shared/stableNavTabs.ts`)
so websocket ticks no longer recreate every nav button.
- `preloadDynamicChunks: false` in `frontend-modern/vite.config.ts` so cold
start no longer fetches and compiles all ~3.1 MB of lazy chunks up front.
- Per-tab scoped hydration and realtime gating on the Proxmox surface
(`17bb2b3b7`, Performance lane).
+38 -1
View File
@@ -9690,7 +9690,44 @@
"subsystem_ids": []
}
],
"coverage_gaps": [],
"coverage_gaps": [
{
"id": "resource-payload-static-metadata",
"summary": "The client-facing resource stream ships ~3KB of mostly-static metadata per resource (duplicated capabilities blobs with only 10 distinct values across 1,508 resources, canonicalIdentity alias/superseded-id history, aiSafeSummary prose, and policy routing) on every snapshot, REST recovery, and reconnect. At 50-node scale the snapshot is a single 4.73MB websocket frame and browser main-thread cost per delta reaches ~1s even 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 needs an owned slice with contract updates and cross-client verification.",
"owner": "project-owner",
"status": "triaged",
"recorded_at": "2026-08-24",
"lane_ids": [
"L6",
"L10",
"L13"
],
"subsystem_ids": [
"api-contracts",
"performance-and-scalability",
"unified-resources"
],
"proposed_resolution": "lane-expansion",
"coverage_impact": 6,
"evidence": [
{
"repo": "pulse",
"path": "docs/release-control/v6/internal/records/resource-payload-static-metadata-2026-08-24.md",
"kind": "file"
},
{
"repo": "pulse",
"path": "frontend-modern/src/stores/websocket.ts",
"kind": "file"
},
{
"repo": "pulse",
"path": "internal/websocket/state_delta.go",
"kind": "file"
}
]
}
],
"candidate_lanes": [],
"work_claims": [],
"open_decisions": [],