diff --git a/frontend-modern/browser-verification.json b/frontend-modern/browser-verification.json
index 6f93fc4c5..7d0d17560 100644
--- a/frontend-modern/browser-verification.json
+++ b/frontend-modern/browser-verification.json
@@ -1,16 +1,16 @@
{
"version": 1,
- "base_sha": "550b2d80a175cc66ab4e7ac269b7ec350e101611",
- "verified_at": "2026-09-08T11:54:21Z",
+ "base_sha": "d242055f9877a47d31b08133e3e8588cbff65f40",
+ "verified_at": "2026-09-08T20:59:34.058403Z",
"result": "passed",
"changed_paths": [
- "frontend-modern/src/utils/alertDestinationsPresentation.ts"
+ "frontend-modern/src/utils/proxmoxUpdateEvidence.ts"
],
"content_sha256": {
- "frontend-modern/src/utils/alertDestinationsPresentation.ts": "67f6f9a1c98345949e162bf06a38760e61457aa1e8a2130913646647a4f29e88"
+ "frontend-modern/src/utils/proxmoxUpdateEvidence.ts": "b99d8b5411e0e894f294f106d970978c8573915ff7ffe0ed60c451128e22d34a"
},
"routes": [
- "/qualification (real health and delivery-log cards, scripted props)"
+ "/qualification.html (production-built real NodeDrawerOverview with synthetic reactive props)"
],
"viewports": [
{
@@ -27,11 +27,15 @@
}
],
"states": [
- "Retained terminal server_error health diagnosis and failed delivery log entry"
+ "Unavailable permission denial",
+ "Retained stale count with permission-denial title",
+ "Checked zero",
+ "Checked positive count",
+ "Not-checked permission-denial reason"
],
"interactions": [
- "Load both cards at desktop, tablet and phone widths; assert label, guidance, no page errors or horizontal overflow."
+ "At each width select unavailable, stale, zero, positive, not_checked, then unavailable again; assert text, stale title, no obsolete Sys.Audit prescription, no page errors or horizontal page overflow."
],
- "notes": "Phone screenshot visually inspected; screenshots retained at /tmp/pulse-server-error-copy. Initial fixture omitted alertIds and timed out; corrected fixture passed all three widths. No installed delivery or receipt claim.",
- "command": "pulse-heavy-run -- node scripts/check-delivery-server-error-copy.mjs"
+ "notes": "Built isolated real component with Vite esnext target, served compiled assets to Chromium. Desktop stale and phone unavailable screenshots visually inspected. Phone uses existing ellipsis for long values; full reason retained in title. No installed backend or reporter credential reproduction. Initial fixture build attempts failed on default target and virtual HTML path; corrected fixture build and all checks passed. Screenshots /tmp/pulse-update-access-copy; log /tmp/web-205503/browser-built.log.",
+ "command": "pulse-heavy-run -- node scripts/check-update-access-copy.mjs"
}
diff --git a/frontend-modern/src/components/Workloads/__tests__/NodeDrawerOverview.updateEvidence.test.tsx b/frontend-modern/src/components/Workloads/__tests__/NodeDrawerOverview.updateEvidence.test.tsx
index 52f83acd3..14136132a 100644
--- a/frontend-modern/src/components/Workloads/__tests__/NodeDrawerOverview.updateEvidence.test.tsx
+++ b/frontend-modern/src/components/Workloads/__tests__/NodeDrawerOverview.updateEvidence.test.tsx
@@ -52,6 +52,6 @@ describe('NodeDrawerOverview update evidence', () => {
/>
));
- expect(screen.getByText('Unavailable · Sys.Audit permission required')).toBeInTheDocument();
+ expect(screen.getByText('Unavailable · Update check access denied')).toBeInTheDocument();
});
});
diff --git a/frontend-modern/src/utils/__tests__/proxmoxUpdateEvidence.test.ts b/frontend-modern/src/utils/__tests__/proxmoxUpdateEvidence.test.ts
index 07a1fefdd..f2dabdf3b 100644
--- a/frontend-modern/src/utils/__tests__/proxmoxUpdateEvidence.test.ts
+++ b/frontend-modern/src/utils/__tests__/proxmoxUpdateEvidence.test.ts
@@ -51,7 +51,7 @@ describe('Proxmox update evidence presentation', () => {
pendingUpdatesReason: 'permission_denied',
}),
).toMatchObject({
- value: 'Unavailable · Sys.Audit permission required',
+ value: 'Unavailable · Update check access denied',
current: false,
});
});
diff --git a/frontend-modern/src/utils/proxmoxUpdateEvidence.ts b/frontend-modern/src/utils/proxmoxUpdateEvidence.ts
index a8c144ae1..4b90f7a1d 100644
--- a/frontend-modern/src/utils/proxmoxUpdateEvidence.ts
+++ b/frontend-modern/src/utils/proxmoxUpdateEvidence.ts
@@ -16,7 +16,7 @@ type UpdateEvidenceNode = Pick<
const reasonLabel = (reason: Node['pendingUpdatesReason']): string => {
switch (reason) {
case 'permission_denied':
- return 'Sys.Audit permission required';
+ return 'Update check access denied';
case 'source_unavailable':
return 'Proxmox source unavailable';
case 'check_failed':
diff --git a/scripts/check-update-access-copy.mjs b/scripts/check-update-access-copy.mjs
new file mode 100644
index 000000000..47c0b2a00
--- /dev/null
+++ b/scripts/check-update-access-copy.mjs
@@ -0,0 +1,81 @@
+// Isolated real-browser component qualification; no installed backend or delivery claim.
+import { build, preview } from "../frontend-modern/node_modules/vite/dist/node/index.js";
+import solid from "../frontend-modern/node_modules/vite-plugin-solid/dist/esm/index.mjs";
+import { chromium } from "@playwright/test";
+import { resolve } from "node:path";
+import { mkdirSync } from "node:fs";
+import assert from "node:assert/strict";
+const root = resolve("frontend-modern");
+process.chdir(root);
+const fixture = `
+import { render } from 'solid-js/web';
+import { createSignal } from 'solid-js';
+import { NodeDrawerOverview } from '/src/components/Workloads/NodeDrawerOverview';
+import '/src/index.css';
+const base = {id:'lab-pve1',name:'pve1',instance:'lab',status:'online',type:'node',cpu:0,memory:{total:1024,used:256,free:768,usage:25},disk:{total:1024,used:256,free:768,usage:25},uptime:3600,loadAverage:[],kernelVersion:'6.8.12',pveVersion:'9.0.1',cpuInfo:{model:'CPU',cores:4,sockets:1,mhz:'2400'},lastSeen:new Date().toISOString(),connectionHealth:'healthy'};
+const states = {
+ not_checked:{pendingUpdatesStatus:'not_checked',pendingUpdatesReason:'permission_denied'},
+ unavailable:{pendingUpdatesStatus:'unavailable',pendingUpdatesReason:'permission_denied'},
+ stale:{pendingUpdates:1,pendingUpdatesStatus:'stale',pendingUpdatesReason:'permission_denied',pendingUpdatesCheckedAt:new Date().toISOString()},
+ zero:{pendingUpdates:0,pendingUpdatesStatus:'checked',pendingUpdatesCheckedAt:new Date().toISOString()},
+ positive:{pendingUpdates:1,pendingUpdatesStatus:'checked',pendingUpdatesCheckedAt:new Date().toISOString()}
+};
+const [state,setState] = createSignal('unavailable');
+render(() =>