## Problem #2741 made an operator's split of a Proxmox node and its pulse-agent (report-merge / unlink in the resources API) split the registry's rows. The monitor's own link (`Node.LinkedAgentID`, `Host.LinkedNodeID`) stayed in place, so everything that reads it kept treating the two machines as one: - the physical disk poll used the agent's SMART inventory as the node's disk fallback, and applied the agent's `--disk-exclude` patterns to the node's disks - `linkedHostForNode` fed the node's disk sources from the agent - guests inherited the agent for discovery and commands - deployment reported the node as already running an agent - service discovery routed through the agent - the agent's container filesystem readings were applied to the node's containers - the node's temperatures came from the agent, through the link or the exact-hostname fallback - `sharedSystemAlertCorrelationForHost` tied the node and the agent together ## Decision An operator split should stop the monitor treating the pair as linked. Two stores were recording one fact: the resource store's exclusions and the monitor's link. The resource store's exclusion is now the one record, and the monitor follows it: - `MonitorAdapter.ProxmoxNodeAgentSplit` implements a new `models.NodeAgentSplitDecider`. It applies the registry's own rule for a node's link (`splitProxmoxNodeLink`), also under the ID the registry holds the agent under, and confirms a split it finds against the store's latest decisions, so a relink takes effect on the next poll. - `models.State` holds both sides of a split link back on every link write: the node poll (for the polled nodes and for other connections' retained nodes, before their links can steer where views fold), the reconcile after manual intent, `UpsertHost` and `LinkNodeToHostAgent`. Report ingest drops a split link before it applies it, uses the link the state kept, and clears the agent's cached container readings. Those readings are also not shown for a node that no longer names the agent. The temperature read skips a split agent in its exact-hostname fallback. - Reverse case: the agents API's node link (`/api/agents/agent/link`) is the operator's newer "same machine" decision. It now removes that pair's split from the store (`TakeExclusion`, which returns the rows it actually removed) before it records manual intent, and puts them back with `RestoreExclusion` if the intent fails to persist. A restore never replaces a decision the operator recorded in between. - A split recorded after a manual link ends that intent on the agent's next report that finds the split confirmed in the store, so host continuity stops reserving the node for that agent. An unreadable store confirms nothing and keeps the intent. - The agents API's unlink needs no store write: it clears monitoring's link, and the registry only joins a node and an agent through a link one of them declares or one inferred from another declared link. Limits (recorded in the contracts): a rebuild that cannot read the store's decisions loads none, in the registry as in monitoring, which needs a change in `registry.go` and `monitor_adapter.go` and is left for a follow-up; a carried temperature reading from an agent that was tied to its node by address stays until the ordinary carry window ends; mock mode's fixture graph keeps its own links. ## Tests - `TestMonitorStateHoldsBackAnOperatorSplitNodeAgentLink` runs #2741's six split requests over four link shapes, through a `models.State` holding the adapter's decisions. Each step runs three poll-and-rebuild cycles and checks every view (monitor listing, broadcast coalesce, resources API from listing and from snapshot), the state's links, that a report alone keeps a split pair apart, a relink, an agent-first rebuild that persists its pins, and the request again. - `TestMonitorStateHoldsBackSplitLinksItStartsWith`, `TestMonitorStateKeepsASplitWhenTheAgentStopsReportingItsMachineID` and the two `internal/models` tests (a split agent can no longer fold two connections' node views, for the polled and for the retained node). - `TestOperatorSplitStopsMonitoringTreatingNodeAndAgentAsLinked` follows report-merge through the real readers listed above, with a negative control (an unrelated exclusion keeps every one of them linked). `TestSplitAgentSensorsDoNotReachTheNodeThroughItsName`, `TestAgentContainerReadingsAreNotShownForANodeThatNoLongerNamesTheAgent` and `TestReportUsesTheLinkTheStateKeptWhenASplitLandsMidReport` cover the temperature fallback, the cached readings and a split landing mid-report. - `TestManualNodeLinkReplacesAnOperatorSplit`, `TestManualNodeLinkKeepsTheSplitWhenItsIntentCannotPersist`, `TestManualNodeLinkSurvivesAnUnreadableSplitStore` and `TestConfirmedSplitOfAManualLinkClearsTheAgentsContainerReadings` cover the agents API link before and after a split, a failing intent, an unreadable store and the intent ending. - Store tests for `TakeExclusion` / `RestoreExclusion` in SQLite and memory, including a removal that fails part way, an operator replacing the pair between listing and removal, rows stored in the reversed order, and a stale older link beside the exclusion. - Mutation controls: I disabled each of the 26 rules above in turn (state and proposal hold-back, retained-node hold-back, the `UpsertHost` checks, the report-ingest checks, ending and keeping manual intent, the lift, the restore, the store confirm, the held agent ID, the temperature filter, the cached-reading checks, and so on). Each made at least one of these tests fail. - The full `models`, `unifiedresources`, `monitoring`, `config`, `alerts`, `servicediscovery` and `resourceapi` suites pass on pulse-dev; `TestGuestMetadataWriterFailuresAreOwnedWithoutSpinRetry`, `TestDeliveryEpisodeCoalescingSurvivesRestart` and `TestTrueNASPollerUnresponsiveRPCDoesNotFreezeOtherConnections` failed once under load average ~80 in packages this change does not touch, and each passes alone.
Pulse documentation
Start here for installation, platform setup, security, operations, and Pulse Intelligence. Commands, configuration keys, image names, API fields, and product identifiers remain untranslated in localized guides.
Start here
- Install Pulse — signed Proxmox/Linux installation, Docker, Docker Compose, Kubernetes, and first-run setup.
- Production deployment and security — least-privilege Proxmox setup, root-agent boundaries, discovery, supply-chain verification, plan limits, scale evidence, and a rollout checklist.
- Upgrade from Pulse v5 — migration prerequisites, rollback, agent continuity, and post-upgrade checks.
- Releases and update channels: choosing Stable or Preview, beta and RC expectations, and how releases are tested and promoted.
- Configure Pulse — authentication, notifications, discovery, retention, and system settings.
- Deployment models — data locations, lifecycle, and differences between supported deployment paths.
- Troubleshooting and FAQ — common failures, diagnostics, and operator questions.
Localized getting started guides: Deutsch · Español
Platforms and agents
- Proxmox Backup Server
- Proxmox Mail Gateway
- Docker and Podman
- Kubernetes and Helm
- TrueNAS SCALE and CORE
- Unified Agent
- Agent security
- VM disk monitoring
- ZFS monitoring
- Temperature monitoring
VMware vSphere support is early access. Current builds expose dedicated vSphere inventory and recovery context, but operators should validate the integration against their own vCenter before production use.
Monitoring and operations
- Metrics history
- Recovery data
- Webhooks
- Automatic updates
- Centralized agent management (Pro)
- Operational trust model
- Current product screenshots
Pulse Intelligence
- Assistant, Patrol, and external-agent overview
- Patrol modes and safety
- Assistant safety model
- External agent HTTP and MCP substrate
Patrol watch-only analysis is available on Community with a local model or the operator's own provider. Investigation and governed fixes require the relevant Pulse Pro capabilities.
Security, privacy, and access
- Production deployment and security
- Security review scope
- Authentication and credential storage review packet
- Security guide
- Privacy and telemetry disclosure
- OIDC and SSO
- Proxy authentication
- Role-based access control (Pro)
- Audit logging (Pro)
- Reverse proxy configuration
- Code-signing policy
Plans and managed access
- Community, Relay, and Pro capabilities
- Relay and Pulse Mobile handoff
- Multi-tenant organizations (Enterprise/custom)
- Provider-hosted MSP operations (request-assisted)
Pulse Cloud is not generally available. Ordinary self-hosted Pulse remains the primary installation path; MSP and Enterprise access are explicit commercial paths rather than defaults in self-hosted setup.
Development and reference
Detailed design notes and dated migration specifications may remain in this directory for maintainers, but they are not operator setup guides unless they are linked from the sections above.
Previous versions and migrations
- Upgrade from v4 to v5
- Retired unified-navigation migration — historical context only; current Pulse uses platform-shaped navigation.
- Move a Pulse installation
Found a bug? Use the issue forms. For setup questions, use GitHub Discussions.