containerUpdateBadgeModel gained update icon and button helpers since its prior
branchcov test, so this covers the three previously-uncovered functions and
their state arms (idle, confirming, updating, success, error and the default).
aiProviderPresentation route-label formatting had fourteen uncovered branches,
now exercised through the four exported entry points. dockerIdentityConflict
conflict collection reaches full branch coverage including the hostnames
fallback and the name fallback chain.
All three are new test-only files under existing __tests__ directories. No source
changed. Each was confirmed with vitest and type-check, and measured to raise
branch or function coverage over the pre-existing suite.
Cloned VMs that keep the same /etc/machine-id collapse into a single
Docker host in Pulse, with each clone's report silently overwriting the
other (#1584). The server now tracks per-identity hostname and machine
ID observations and flags a conflict when a value flaps back to one
already seen inside a 15-minute window, a signature a one-time rename
never produces. The conflict rides the DockerHost model through unified
resources, and the Docker page shows a warning naming the flapping
hostnames with the machine-id remedy. The warning self-clears once one
clone stops reporting for the window.
A vSphere 6.x target fails the connect test at the Automation session
step with a generic "HTTP 500" message, because /api on those releases
routes to the JSON-RPC servlet. When /api/session fails with a non-auth
status, probe the legacy /rest CIS session API with the same
credentials; if that login works the target predates the JSON APIs
Pulse uses, so the test now reports the unsupported-version warning
naming the vCenter 8.0U1 floor instead of pointing at credentials. The
probe deletes the session it creates. Also reword the frontend guidance
for that category in plain terms.
Related to #1585.
Every ID token verification failure rendered the issuer-mismatch
advice, sending users with audience or clock problems down the wrong
path and telling users with a genuine issuer mismatch nothing they had
not already checked (#1533). Map the distinct verification failures
(issuer, audience, expiry) to their own error codes and give each
accurate login-page copy pointing at the server log's got/want detail.
The Security Overview configure-https action linked /docs/SECURITY.md
with external: false, so Solid Router intercepted the same-origin
anchor click and rendered the SPA NotFound page instead of letting the
browser fetch the embedded doc. Mark the link external like every
other shipped-doc consumer.
Refs discussion #1505
Add a purely-additive branch-coverage suite for the residual uncovered arms of
patrolInvestigationContextModel builders (assistant briefing/handoff inputs,
configuration-failure handoff secret redaction, investigation context summary
numeric clamping, proposed-fix keep/drop gating, approval-policy checks). The
existing dev test is left untouched; this exercises previously-unexecuted
exports and branch arms only. No source changed.
The Update button on the Docker containers table and workloads rows now
plans an audited update action and opens the same governed review
dialog the lifecycle controls use (approve, run, per-action audit),
instead of calling the retired direct-update endpoint. The host
drawer's bulk update-all reports honestly that updates run as reviewed
per-container actions until a reviewed bulk flow exists, and the dead
updateDockerContainer/updateAllDockerContainers API clients are
removed. Update state still tracks through the containerUpdates store,
flipping to success when the refreshed report clears updateAvailable.
In row drawers the Access disclosure sat collapsed at the very bottom, but
expanding it re-rendered the section at the top — clicking "Show access"
teleported the content away from the user, and reaching a container's web
interface meant scrolling the whole drawer down and back up (#1556).
Promote the section whenever it exists so it renders in one stable spot at
the top, and surface the saved URL as a clickable link in the disclosure
header so opening the web interface requires no expansion at all.
Refs #1556
A URL saved from the Docker tab's container drawer went to the docker
store under the runtime container key — the lowest-priority key in the
unified customUrl projection, and one that goes stale the moment the
container is recreated (e.g. by an update). Any stable record, including
an intentionally empty cleared one, masked it forever, so the saved URL
never turned the container name into a table link even after a refresh
(#1556). The Workloads drawer was already fixed to use the stable
host-plus-container-name guest key; align the resource drawer on the
same identity.
Refs #1556
The Proxmox nodes table styled its PVE UI link in the plain text color, so
a working link was indistinguishable from a label (#1556). The workloads
node group headers and both alerts-surface name links had the same drift.
Extract the canonical blue link classes into WEB_INTERFACE_LINK_COLOR_CLASS
on WebInterfaceNameLink and compose it at every call site.
Refs #1556
A provider that issues no refresh token (offline_access not requested,
e.g. default Authelia) left session.OIDCIssuer unset, so
/api/security/status reported an empty ssoSessionUsername and
X-Auth-Method fell back to plain session. The frontend then skipped the
SSO fast path, and the pre-auth bootstrap short-circuit pinned the user
to the login page after ?oidc=success before the /api/state probe could
run (issue #1574). Stamp issuer/client on every OIDC session (refresh
stays gated on the token being present) and let a completed SSO
callback bypass the bootstrap short-circuit.
Actions awaiting a decision are time-boxed, but the nav gave no signal
unless the approval happened to be Patrol-origin and the user was
already on Patrol. Poll the canonical decision queue alongside the
existing 30s open-work refresh and surface the count on the Actions
tab, matching the Alerts/Patrol badge pattern. Sessions without the
action-approve capability stop polling after the first terminal
response.
ssh-keygen -Y verify -f expects the principal in the FIRST field; the
docs published the key in authorized_keys order, so the documented
verification failed against a valid signature (customer-reported against
v6.0.5). Verified the new command against the live v6.0.5 release
artifacts.
A follow-up sent during an active run now offers itself to the running
agentic loop via POST /api/ai/sessions/{id}/steer. Accepted steers join
the loop at its next turn boundary (the abort-check site) as plain user
messages, are announced with a steer_applied stream event so the drawer
settles the pending row, and persist through the end-of-run save. A
steer carries prompt text only: no route, control-level, or autonomy
changes, no turn-budget extension, system sessions rejected, and the
per-session inbox is bounded (steer_backlog overflow). Delivery is not
guaranteed by acceptance: a run that ends first discards the inbox and
the row drains as an ordinary queued turn, so pre-steering queue
semantics remain the fallback. Steering rows lose edit/remove once
accepted.
Chat turns, compaction, and title calls now stamp session_id on their
cost.UsageEvent, and the done event carries session_cost_usd summed from
the operator ledger (cost.Store.SessionCostUSD). The drawer's last-turn
summary appends '$0.12 session' with a sub-cent floor. The figure is
omitted whenever any of the session's models has unknown pricing, and
free local models price known-at-zero, so no figure is ever partial.
Pasting a log or config into the composer flooded the textarea. Pastes
over 8 lines or 800 chars now collapse into a removable chip; the full
text rejoins the prompt after the typed question at send time. Clicking
the chip body expands it back into the textarea for inline editing, and
a chip-only send is allowed.
The undo flow already restores the removed prompt into the composer for
editing, but the only entry points were the header undo button and /undo.
Surface it where users look for it: a hover pencil on the latest
non-queued user prompt that undoes the turn and prefills the composer,
riding the same last-turn undo boundary as regenerate.
Retrying a failed turn re-sent the prompt without removing the persisted
turn, so session history double-recorded the prompt. Session undo now
accepts an expected-prompt guard (a stale retry can never remove a
different turn); retry drops the replaced turn server-side before
re-sending. The latest settled assistant answer gains a hover-revealed
Regenerate button that reuses the same path.
The infrastructure resource drawer saved guest metadata (web interface
URLs) under the unified resource hash or the discovery resource id, a
keyspace no workloads table reads: the tables and the workloads drawer
resolve metadata by the canonical id (instance:node:vmid for PVE guests,
resource id otherwise), which is also the key v5 upgrades carry over in
guest_metadata.json. A URL saved from that drawer was stranded where
only the same drawer could read it back.
Route the drawer's guest metadata id through
getCanonicalWorkloadIdForResource, and canonicalize the resource type
inside that helper so lxc/oci-container/qemu spellings build the same
node-scoped id the workloads surfaces use.
Refs #1556
The 'trusted action review workspace' change (e13abf84f) reworked the verified
verification-outcome copy, breaking a branchcov2 assertion that hard-coded the old
label/detail. Assert 'VERIFIED' normalises to the canonical 'verified' result
instead of exact copy, so the test stays focused on the toLowerCase branch.