Use the existing guest safety signals in the canonical resource drawer, including typed and legacy PVE facets. Keep saved Discovery evidence readable and the backup precaution visible without admitting a manual rescan while paused.
Contract-Neutral: performance-and-scalability; the workload helper input is narrowed without changing its decisions, metrics, render path or performance contract.
Change-source: pulse-maintainer
The Docker container Updates column and the Kubernetes Nodes Status
column hold badges that cannot truncate, and both were cut at the
cell edge at tablet widths.
Docker containers size columns by layout mode with weights that
renormalize over whichever optional columns show (State, Restarts,
Host, Engine). Updates got 54-76px between a 34rem container and the
md breakpoint, where the phone wrap rule no longer applies, so Update
(74px) and Current (69px) were cut from 573 to 800px. The column now
takes its room only from the CPU bar, which never shows a sublabel,
and the collapsed actions menu, so every other column keeps its width
in every layout and column set and the memory bar keeps its used/total
sublabel. The 74px states fit in every layout and column set at the
layout's narrowest table. The 100px states (Check failed, Updating...,
Completed) fit in most layouts but can still clip at a layout's
narrow end when several optional columns show. Wide rows also gain the room their expanded
lifecycle controls need. A model test checks every layout and column
set.
Kubernetes Nodes Status shared the tablet band equally (51px of room
at 573px) and had 8 percent at md (53px at 768px), so Degraded (64px)
was cut. The band now sizes each column for its header and Degraded
at a 34rem table, and md moves 2.5 points from CPU to Status, keeping
the visible total, so Node, Cluster, Roles, Memory and Capacity keep
their widths everywhere. Degraded, NotReady and Unknown fit from
544px; Unschedulable (89px) fits from about 900px.
Incorporate the scoped-read upstream identity through the completed bounded refresh; preserve all reviewed commit identities and existing source evidence.
Change-source: pulse-maintainer
The Images table's Update check badge needs about 122px with its cell
padding for its longest labels ("Update available", "Managed by
Pulse"). Between the phone projection and the md breakpoint every
non-name column took an equal 17.5 percent share, which left the
column 100px at a 600px viewport, and the 16 percent md width left it
111px at 768px. The badge was cut at the cell edge with a stray
ellipsis dot, and the "UPDATE CHECK" header clipped at 600px.
The table now declares tablet-band widths through the sortable
header's bandWidth (Update check 23, Size 12; Host and Used by keep
their 17.5) and moves 3 points of md width to Update check, one each
from Host, Used by and Size. The longest size values ("1023 MB",
"9.99 GB") still fit both narrower Size columns.
A clip sweep on a mock stack from 390 to 1440px (15 widths) found the
update badge clipped at 600, 640, 700 and 768px before and nowhere
after. A probe of all six labels against the narrowest Update check
cell found none clipping at any width, and no other column clipped
more often than before. The base already carries the Used by
block-truncate span from #2514, so Used by was measured as it now
renders.
Follow-up to rcourtman/Pulse#2477.
**Docker containers get the bulk editor**
The strongest demand for saved links (#1556, #624) came from Docker
users, but the editor only reached Proxmox and vSphere guests. The
Docker containers table header now has the same **Edit links** panel,
worded for containers.
- Rows are keyed through `toDiscoveryConfig`, the container drawer's own
metadata target, so bulk and drawer saves read and write the same
`app-container:<host>:name:<name>` record. This includes Docker running
inside Proxmox LXCs.
- The editor now takes a source. Workload tables pass live guests, so
the row model still loads only with the panel. Other tables pass
ready-made rows.
- The Docker table lazy-loads the trigger. Without that, Rollup merged
it into the chunk the Docker and workloads pages share, renamed that
chunk, and broke the `DrawerDiskListCard` bundle budget.
**Read-only tokens no longer see edits that would fail**
Metadata writes require `monitoring:write` for API-token sessions (the
backend's `EnsureScope`). Browser sessions always pass, because metadata
routes have no role check. A kiosk-style `monitoring:read` token saw
edit controls that every save refused with 403. The session store now
mirrors the gate from the security status `tokenScopes`
(`sessionCanWriteMonitoringMetadata()`):
- the bulk editor's **Edit links** button is hidden for such sessions;
- the shared web-interface field shows the saved URL with open and copy,
plus a one-line explanation, but no input, Save, Remove, or "Use this"
suggestion.
**Fewer refetches**
Saves now dispatch their metadata-changed events together after the
writes. `useUnifiedResources` coalesces onto one in-flight refetch, so a
bulk save costs two resource refetches whether it changes 2 links or 4.
Before this, it cost one per link.
**Verification**
- Private mock stack, Docker page and Proxmox page, at 1280 and 375px.
- Real token sessions with the admin bypass off: a `monitoring:read`
token sees no edit affordances, and a `monitoring:read+write` token
saves a container link.
- Receipt: `frontend-modern/browser-verification/e8946b639f30703c.json`.
- Production build: `WorkloadsSurface` 69.08 kB, `Docker` 28.56 kB,
`DrawerDiskListCard` unchanged; no violations.
- Full frontend lint, plus 841 test files (15,618 tests) across
features, hooks, components and stores.
The bulk web-link editor only reached Proxmox and vSphere guests, but the
strongest demand for saved links (#1556, #624) came from Docker users. The
Docker containers table now offers the same Edit links panel, keyed through
the container drawer's own metadata target so bulk and drawer saves share
one record. The trigger is lazy-loaded so it does not merge into the chunk
the Docker and workloads pages already share.
Metadata writes require monitoring:write for API-token sessions, so a
kiosk-style read-only token saw edit controls that every save refused. The
session store now mirrors that gate from the security status token scopes:
the bulk editor is hidden and the shared web-interface field shows the saved
URL without input, Save, Remove, or suggestion adoption. Browser sessions
are unaffected because the backend does not check roles on metadata writes.
Saves now dispatch their metadata-changed events together after the writes,
so a bulk save costs two resource refetches instead of one per link.
Follow-up to #2509, which fixed the Kubernetes tables. Docker, Proxmox
and vSphere summary cells still wrapped long values in a capped
inline-block span (max-w-48 truncate, max-w-[18rem] truncate, or
truncate inline-block). The cap ignored the column width of these
fixed-layout tables, so a long value ran past a narrower cell with no
ellipsis (a swarm service image by 225px at 700 wide, volume mountpoints
by 51px at 1440), and the inline-block sat about 2px above the row's
text line.
A block truncate span fills the cell, ends in an ellipsis inside it and
sits on the row line. The Docker service Update cell keeps its phone
wrap and truncates inside its column from md instead of at a 10rem cap.
The guardrail from #2509 now covers every platform table source that
carried the pattern, and the coverage table test pins the Node cell.
Every subsystem must declare require_explicit_path_policy_coverage, so
build_verification_requirements never falls back to a rule's default
verification policy; an unmatched runtime file becomes a path-policy gap
instead. The default test_prefixes and exact_files were therefore never
consulted, yet 13 of 16 rules carried them (93 files and one prefix),
and authors kept adding proofs there as if they counted.
92 of the 93 files were already proof on some path policy, and
api-contracts' default prefix is on three of its own policies. The one
orphan, internal/api/router_bench_test.go, benchmarks the api-contracts
router rather than any performance-and-scalability runtime, so no policy
should take it; it stays an owned file only.
The registry drops the lists, registry_audit requires them empty and
points authors at the path policy instead, and the canonical protocol
says so. The protocol also stops promising same-subsystem tests "when
the registry explicitly allows them", which the audit no longer permits.
No verdict changes: build_verification_requirements returns identical
requirements for all 2746 owned runtime paths, and for an uncovered
path, under the old and new registry.
Capture all endpoint limiters under their Router owner and seal late worker
admission. Concurrent shutdown joins each cleanup worker without resetting
request budgets or stopping another Router. Integration fixtures use the real
shutdown lifecycle before monitor teardown.
Contract-Neutral: Router worker ownership and concurrent shutdown only; HTTP payloads, limits and windows, auth, tenant selection, revocation and persistence contracts are unchanged.
Change-source: pulse-maintainer
Accept exact PI commit 0c283d2dd5 with retained focused source and Docs browser proof. Preserve conditional runtime-host examples and passive comparison safeguards; this is documentation maintenance, not native collection or alert-delivery acceptance.
Change-source: pulse-maintainer
The five predeclared diagnostic cases retain a real 1m versus 2m health-age counterexample between separate wall-clock evaluations. Give the independent content oracle and production projection the same private health clock without removing any JSON field; pin minute-boundary age advancement and original LastSeen. Production samples real UTC at the unchanged post-read evaluation point.
Contract-Neutral: Internal health-clock test seam preserves the real UTC evaluation point, public resource/history fields, source precedence, agent identity/lifecycle, tenant/revocation and safety contracts; no wire or permission delta.
Change-source: pulse-maintainer
Document host-capacity normalisation, version-qualified rounding and the difference between collected readings and delivered alerts. Keep comparisons on ordinary workload observations rather than forced load, threshold changes or diagnostic reruns.
Contract-Neutral: Existing container CPU semantics and safety guidance only; no runtime, API, threshold, permission or lifecycle contract changes.
Change-source: pulse-maintainer
Preserve the exact Web candidate and its own-parent browser receipt. Retained connected source checks and desktop/touch evidence cover the existing read-only disclosures without changing collection or backup operations.
Change-source: pulse-maintainer
Between the phone projection and the md column widths (a 34rem container
below a 768px viewport) the Configuration and Deployments tables split
their width evenly, so names were cut to a few letters beside short
counts. Headers can now declare a percent width for that band through
bandWidth / platformTableBandWidthStyle, and both tables size names
first.
With one cluster in view every scope cell repeated the cluster name and
crowded out the namespace that tells rows apart, so scope cells show the
namespace alone and keep the full cluster/namespace scope on the title
and for assistive technology. Several clusters keep the combined label.
Deployments Desired returns only with wide tables, since Ready already
reads ready over desired, and Ready keeps its denominator until Desired
is visible. On a phone Age takes Ready's spare width so "18h ago" fits.
Summary cells used a capped inline-block span that ignored the column
width: long values spilled past narrow cells with no ellipsis and sat
above the row's text line. A block span fills the cell, ellipsizes there
and aligns with its neighbours.
Use native read-only disclosure buttons for both backup entry points, with the shared Dialog preserving named completion evidence, focus and guest row action ownership. Keep existing freshness and uncertainty semantics, collection and backup operations unchanged. Include connected regression tests, the subsystem contract and inspected desktop/phone browser verification.
Change-source: pulse-maintainer
Resolve canonical source mappings once per complete projection while preserving detached resource content and target selection after host coalescing. Bind resources and targets to the same locked generation, including absence and continuity overlays, and avoid another owned outer-slice copy. No timestamp cache or native CPU/RSS claim. Retain cold, clean and dirty full-content controls and paired complete-projection measurements.
Contract-Neutral: Internal bulk-read and copy-ownership repair preserves existing public resource/history fields, source precedence, agent identity/lifecycle, tenant/revocation and safety contracts; no wire or permission delta.
Change-source: pulse-maintainer
Kubernetes names clipped badly between about 600 and 900px wide. At
700px node names read "Pr…" and deployment names two letters.
**Why:** between a 544px table container and a 768px viewport, platform
tables show their phone-hidden columns again, but `md:w-[…]` widths are
viewport media queries and don't apply yet. So every visible column took
an equal share. A seven-column Kubernetes table left its name 83px, with
the chevron and status dot inside it. From 768px the Kubernetes name
widths (14–19%) still cut common node, service and event names.
**Fix:**
- The shared table shell keeps the phone 30% name anchor in that band.
Tables sized by a weighted colgroup are unaffected.
- Kubernetes name columns get room for typical names at 768px. The Nodes
columns are rebalanced so Capacity fits at 1100px and wider.
- Generated names (pods, a pod's node, controllers) truncate their head
and keep the trailing segment that tells siblings apart:
`checkout-a…-c7z2p`, `prod…-02`. The tail never outgrows its cell.
Deployment names keep plain end truncation.
**Measured** with a clip sweep over every Kubernetes tab at 600–1440px:
- Identity-column clips fall from 284 to 186. Most of the remainder are
pod heads truncated by design.
- The Nodes table has no name clipping at any width.
- In the band, TrueNAS Storage and a vSphere resource table go from 14
name clips to 0, with no new clips on other platforms.
Between a 544px table container and a 768px viewport, platform tables
show their phone-hidden columns again, but md:w widths are viewport media
queries and do not apply yet, so every visible column took an equal share.
A seven-column Kubernetes table left its name 83px, with the chevron and
status dot inside it, so node names read "Pr..." and deployment names two
letters. From 768px the Kubernetes name widths (14 to 19 percent) still
cut common node, service and event names.
The shared table shell now keeps the phone 30 percent name anchor in that
band. Tables sized by a weighted colgroup are unaffected. Kubernetes name
columns get room for typical names at 768px, with the Nodes columns
rebalanced so Capacity fits at 1100px and wider. Generated names (pods,
the node a pod runs on, controllers) truncate their head and keep the
trailing segment that tells siblings apart, and that tail never outgrows
its cell.
staged_verification_files_for_requirement() matches
allow_same_subsystem_tests against a subsystem's
owned_prefixes/owned_files, but both commit guards passed it the
impacted entry, which carried neither. Since the v6 import (778a2577b6)
a same-subsystem test never satisfied a requirement, while
subsystem_lookup.py (which passes the registry rule) and the guard's own
BLOCKED message ("same-subsystem test/spec files are also accepted")
said it would.
Honouring the 12 flags would have loosened the guard well past their
apparent intent. Every rule requires explicit path-policy coverage, so
the five rule-level flags are never consulted, and on the seven path
policies the flag reaches every test the subsystem owns: a
mutation-registry change would accept any internal/ai or AI Chat test
(~455) instead of its 4 listed proofs, and a frontend Actions change any
Go test under internal/unifiedresources. Six of the seven already list
their own directory in test_prefixes.
So the strictness stays and the tools now agree on it: the registry sets
the 12 flags to false (what has always been enforced), registry_audit
rejects true and points at test_prefixes/exact_files, and the impacted
entry carries the rule's ownership so the completion and commit-shape
guards read the flag the same way subsystem_lookup does.
No requirement accepts a proof it rejected before. subsystem_lookup
stops reporting matches the guard refused: a new internal/hostagent test
no longer claims three agent-lifecycle policies.
Keep admission sealed and reuse a still-running close observer. A later explicit shutdown attempt may persist retained state after a completed write failure; successful close remains idempotent. This avoids a permanent offboarding dead end after an ordinary filesystem repair without an automatic spin retry or overlapping writes.
Contract-Neutral: Internal JSON writer recovery behaviour only; public routes, fields, permissions, identity format, private file mode and atomic persistence are unchanged.
Change-source: pulse-maintainer
Admit detached metadata in order, merge identity fields without restoring stale
operator edits, and persist complete snapshots with one owned writer. Seal late
writes and return shutdown failures before organisation data or offboarding is
removed. Preserve existing drain budgets, file format, tenant boundaries and
atomic persistence. Add controlled burst, ordering, write-error, blocked-close
and real deletion controls.
Contract-Neutral: Behavioural repair of existing JSON persistence and organisation deletion; no route, field, permission, identity format, schema or provider authority change. Shutdown failure uses the existing HTTP error envelope. Internal ownership methods and explanatory contract text change, not the public contract shape.
Change-source: pulse-maintainer
Preserve the exact published frontier alongside reviewed canonical work. No publication or deployment is performed by this merge.
Change-source: pulse-maintainer
Audit Webhooks is the only webhook page in Settings, so people who want
alerts in Discord or Slack land there. In #1344 a user tried to add a
Discord webhook from it and filed a bug when that didn't work. Alert
delivery lives in Alerts, Notifications, which Settings never mentions.
The panel now opens, gated or enabled, with one line saying these
webhooks carry security events only, linking to alert notifications.
Verified at 1440 and 390. The link lands on /alerts/notifications
without a page reload.
The Security Overview tagged the HTTPS tile red and Critical on every
install, directly above a hardening card that calls HTTPS Recommended on
a private network and says local HTTP is acceptable. The same flag
counted plain HTTP as a missing critical control in the posture score,
so a typical LAN install read 55 percent.
The tile now uses the hardening card's rule: critical once the instance
is publicly reachable, recommended otherwise. A private install with a
password and protected exports reads 79 percent (still Moderate). A
public one still shows HTTPS as Critical.
Verified at 1440 and 390 on a private-network instance.
Preserve existing reviewed integrations and published attention-reason presentation without re-parenting source commits.
Change-source: pulse-maintainer
The shared-template rule required every TrueNAS table to use the shared
title-case helper. The storage table used it only for the risk-level
pill, which the Health reason replaced, so it no longer formats any raw
provider value and the required-consumer check failed. The scope-wide
guard against a local titleCase helper still covers the file.
Match QNAP guidance to existing data-volume relocation, create private per-attempt staging and preserve diagnostic logs and identity. Exercise copied commands for preparation and installer failures without an appliance operation.
Contract-Neutral: Clarifies existing installer storage and private staging guidance; no runtime, permission or data-contract change.
Change-source: pulse-maintainer
Audit Webhooks is the only webhook page in Settings, so people looking to
send alerts to Discord or Slack land there. Issue 1344 tried to add a
Discord webhook from it and filed a bug when that did not work. Alert
delivery lives in Alerts, Notifications, which Settings never mentions.
The panel now opens, gated or enabled, with one line saying these webhooks
carry security events only and linking to alert notifications.
On a phone the TrueNAS Storage Health column is hidden, so the row
drawer is where a user learns why a row is amber. It fell short in three
ways:
- A read-only dataset said only "Observed state Degraded", because a
read-only dataset raises no incident.
- A pool showed one of its two incidents, because the health presenter
read only the rollup, plus a generic "Resource Health Issue" line.
- When an open alert matched the first reason, the drawer dropped every
other reason.
The fix:
- The shared health presenter keeps every incident summary.
- It adds a TrueNAS dataset's state, through a small shared util the
storage table will also use.
- It uses the rollup's category label only when nothing more specific
exists.
- The Overview's Needs attention list skips only the reasons an open
alert already states, ignoring a trailing full stop.
Verified on the phone and desktop drawers for the read-only dataset and
the degraded pool, and on the Machines table, which is unchanged.
Preserve the exact reviewed documentation candidate and its retained privacy/query proof; no runtime or storage changes.
Change-source: pulse-maintainer
Additively incorporate the exact observed main frontier without advancing PR2486 or rewriting accepted work. The newer canonical range remains deferred pending its existing source-check and composition-proof routes.
Change-source: pulse-maintainer
The Security Overview tagged the HTTPS tile red and Critical on every
install, directly above a hardening card that calls HTTPS Recommended on
a private network and says local HTTP is acceptable. The same flag also
counted plain HTTP as a missing critical control in the posture score, so
a typical LAN install read 55 percent.
The tile now uses the hardening card's rule: critical once the instance
is publicly reachable, recommended otherwise. A private install with a
password and protected exports reads 79 percent, still Moderate, and a
public one still shows HTTPS as Critical.
On a phone the TrueNAS Storage Health column is hidden, so the row drawer
is where a user learns why a row is amber, and it fell short. A read-only
dataset said only Observed state Degraded, because it raises no incident.
A pool showed one of its two incidents, because the health presenter read
only the rollup, plus a generic Resource Health Issue line. And when an
open alert matched the first reason, the drawer dropped every other one.
The presenter now keeps every incident summary, adds a TrueNAS dataset's
state (the provider's only reason for a read-only dataset, read through a
shared util), and uses the rollup's category label only when nothing more
specific exists. The Overview's Needs attention list skips only the
reasons an open alert already states, ignoring a trailing full stop.