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
One-click updates recreated containers from the raw inspected config, so
Docker rejected the create for any container using network_mode:
container:<id> (compose service:<x>) or host with "conflicting options:
hostname and the network mode", leaving the workload stopped under its
_pulse_backup_ name until the rollback rename restored it. Docker fills
Config.Hostname with the namespace owner's ID on such containers, so the
verbatim copy always tripped the daemon validation (verified against a
real Docker 29.5.2 daemon: verbatim create 409s, sanitized create
succeeds and the replacement starts in the shared namespace).
Strip the namespace-owned settings before ContainerCreate: hostname and
domainname for container:/host modes, plus exposed/published ports,
links, DNS options, and extra hosts for container: mode, all of which
the daemon derives from the owning namespace. Bridge and user-defined
networks are untouched.
Refs #1564
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.
Sibling of #1559: canonicalIDFromIdentity hashed the short hostname in
its cluster arm, so two machine-keyless Docker Swarm members with FQDN
hostnames sharing a first label (cloud.a, cloud.b) derived the same
cluster:<swarm>:cloud canonical ID and fully merged in the registry.
PVE is unaffected (single-label node names hash identically).
Both hostname-derived arms now hash NormalizeFullHostname. Derivation
stays a pure function of identity so store-less registries keep deriving
the same IDs as the durable one. Compatibility for hosts minted under
the short era: journal reads already merge both eras via
ResourceIdentityPin.EraIDs, and new canonical-ID succession re-keys
resource_operator_state and action_audits rows to the successor ID at
pin persist (never across a contradicting machine key, never while the
old ID is still live, never rewriting journal rows) so operator intent
like never-auto-remediate survives the era change. Already-merged
keyless pairs cannot be retroactively split; the merged rows succeed to
whichever member persists first.
The code fix (preserve full dotted hostnames in identity pins and the
presentation host coalescer, with short/FQDN equivalence kept for
matching) rode commit 1d3b8e194 through a shared-index race. This
commit carries the unified-resources subsystem contract update and
moves the end-to-end regression test into registry_test.go.
An alert that resolved while its firing notification was still in the
grouping window or waiting in the persistent queue (alert delay pushes
activation close to resolution; quiet-hours replay defers delivery)
produced a recovery-only notification: CancelAlert dropped the queued
firing, but LastNotified had been set optimistically at dispatch, so
the resolved-notification gate believed the firing had been sent.
CancelAlert now reports whether it cancelled a firing notification that
had not been delivered (grouping window entries and pending queue rows;
mid-send rows are excluded because their delivery may still complete),
and handleAlertResolved suppresses the recovery in that case. This also
covers the quiet-hours replay bypass: a recovery only follows a deferred
firing if the replay was actually delivered.
Addresses #1553
Every email covering a single alert now carries In-Reply-To and
References headers set to a deterministic incident thread ID derived
from the alert ID and firing start time, so mail clients thread the
firing, re-notification, and resolved emails of one incident together.
Message-ID stays unique per send because re-notified incidents send
multiple emails and some providers de-duplicate on Message-ID. Grouped
emails skip threading since firing and resolved batches rarely contain
the same alert set.
Addresses #1543 (discussion)
The installer's unit hardens with NoNewPrivileges=true, which strips the
ping binary's setuid/file capabilities, so ICMP availability probes could
never work on a systemd install. Grant the capability ambiently instead,
document the systemctl edit override for existing units, and pin the
hardening block with an install test and contract clause.
Addresses #1554 (discussion)
The ntfy branch of prepareEnhancedWebhookExecution parsed the payload
template without templateFuncMap(), so the built-in ntfy preset (which
uses {{.Type | title}}) failed to parse and Test sends returned HTTP
400 with "function \"title\" not defined". Register the func map on
that parse, matching the generic webhook path, and add a regression
test that renders the actual built-in ntfy preset template.
Addresses #1549