Pulse/docs/release-control/v6/internal/LEGACY_HOST_CLASSIFICATION_2026-03-05.md

13 KiB

Legacy Host Classification Audit

Date: 2026-03-05 Scope: pulse repo only, focused on v6-facing paths and release verification artifacts.

Verdict

No additional active v6 runtime leaks were found after fixing the agent-registration journey.

The remaining host references in v6-adjacent code fall into three intentional buckets:

  1. Compatibility boundaries that explicitly reject or normalize legacy input.
  2. Internal state or wire-format shims that still bridge older model names to v6-facing output.
  3. Non-resource semantics where host means hostname, SSH host key, backup type, or endpoint host.

Release Decision

Release can proceed on the host-type migration question.

Reasoning:

  • canonical v6 request/resource surfaces now reject removed host aliases
  • the known release-facing registration leak has been fixed
  • remaining host naming is contained inside compatibility, ingest, topology, or DTO layers
  • added ratchets now pin the most important release-facing regression points

This audit does not claim that all host-era naming is gone. It claims that the remaining naming debt is not evidence of canonical v6 behavior drifting back to the removed host resource type.

Must Remove

None found in active v6 runtime/read surfaces during this pass.

The previously-found leak is now fixed:

  • tests/integration/tests/journeys/04-agent-install-registration.spec.ts
  • tests/integration/evals/tasks/agent-registration.md

Those artifacts now require unified resources[] and agent.type = "unified".

Intentional Compatibility Boundaries

These are correct to keep because they harden v6 against old clients or old persisted inputs:

  • internal/api/resources_test.go Confirms /api/resources?type=host is rejected.
  • internal/api/org_handlers_test.go Confirms organization sharing rejects resourceType: "host".
  • internal/api/ai_handler_test.go Confirms legacy chat mention aliases like host, container, and k8s are dropped.
  • internal/api/ai_handlers_test.go Confirms target_type: "host" is rejected for run-command normalization.
  • internal/monitoring/monitor_helpers.go Keeps explicit legacy-agent detection: only agent.type = "unified" is canonical.

Intentional Internal Shims

These are still legacy-shaped internally, but they are not evidence of v6 model leakage:

  • internal/monitoring/monitor.go monitorLegacyResourceType() is the frontend wire-shape mapper for /api/state broadcast payloads. It emits canonical v6-facing types like agent, node, and docker-host.
  • internal/models/state_snapshot.go StateSnapshot and ResolveResource() still model host-agent state for producer/wire compatibility. This is not the canonical read model; ReadState and unified resources are.

Internal Models Follow-Up

The remaining internal/models host-era surface is still serving live compatibility and routing work. It should not be treated as dead migration residue.

Must Remain For Release

  • internal/models/models.go Host, HostSensorSummary, HostDiskSMART, ClearAllHosts(), LinkHostAgentToNode(), and UnlinkHostAgent() still back the host-agent ingest and linking flow.
  • internal/models/models_frontend.go HostFrontend and the StateFrontend.Hosts field remain part of the internal/frontend wire DTO layer. /api/state strips that array for the canonical v6 contract, but the model still exists for compatibility, websocket shaping, mock data, and legacy-facing internal consumers.
  • internal/models/converters.go Host -> HostFrontend conversion is still the compatibility bridge from host-agent state into the older frontend DTO family.
  • internal/models/state_snapshot.go StateSnapshot.Hosts and ResolveResource() still support host-agent lookup/routing for compatibility flows.

Active Runtime Boundaries Still Using That Surface

  • internal/api/router.go Metrics/history and live metric fallback still read snap.Hosts when the canonical resource type is agent.
  • internal/api/agent_ingest.go Host agent lookup and registration validation still scan the live snap.Hosts snapshot.
  • internal/monitoring/monitor_agents.go ApplyHostReport() still writes into models.Host state before unified-resource ingestion layers consume it.
  • internal/ai/chat/context_prefetch.go Chat mention prefetch already uses ReadState.Hosts() and maps those records to canonical agent mentions. This is canonical at the read boundary even though the underlying source model is still named Host.

API Runtime Follow-Up

The remaining host-era naming inside internal/api is concentrated in compatibility handlers and helper locals. It is still part of the supported release path for agent install, lookup, and live metric fallback.

Must Remain For Release

  • internal/api/agent_ingest.go HostAgentHandlers is still the compatibility boundary for the Pulse Unified Agent runtime. It reads GetLiveStateSnapshot().Hosts to:
    • validate installer lookup requests
    • resolve config fetch scope
    • enforce token-to-agent ownership
  • internal/api/router.go live metric fallback still resolves canonical agent resources through snap.Hosts when building instant metric points for runtime reads.
  • internal/api/host_agents_test.go keeps the lookup/install compatibility behavior pinned while those handlers still exist.

Why This Is Not A V6 Leak

  • The external resource type at the API boundary is still agent, not host.
  • The remaining host-era code is operating on compatibility storage names (models.Host, snap.Hosts) after canonical request normalization has already happened.
  • Existing API tests already pin explicit rejection of removed host aliases in:
    • AI/chat
    • org shares
    • reporting
    • metrics history
    • resources/discovery

Post-Release Refactor Targets

These are the next cleanup candidates once the host-agent compatibility/state layer is intentionally renamed or retired:

  • internal/api/router.go local helpers like findHost and comments that still describe the agent path in host-era terms
  • internal/api/agent_ingest.go HostAgentHandlers naming, local host variables, and snap.Hosts comments
  • internal/api/host_agents_test.go test names and fixtures that still describe the canonical agent flow as host lookup/config management

These are naming/structure refactors, not release blockers.

Post-Release Rename Candidates

These look like rename-only cleanup once the host-agent compatibility/state layer is intentionally retired or renamed:

  • internal/models/models.go Host, HostSensorSummary, HostDiskSMART, HostCephCluster
  • internal/models/models_frontend.go HostFrontend, HostSensorSummaryFrontend, HostDiskSMARTFrontend
  • internal/models/converters.go ToFrontend converts a Host to HostFrontend
  • internal/models/state_snapshot.go comments like Check generic Hosts and the hosts local variable naming

These are naming debt, not current v6 correctness bugs.

Monitoring Runtime Follow-Up

The remaining host-era surface in internal/monitoring is the active ingest and correlation bridge for Pulse Unified Agent reports. It is still required for release.

Must Remain For Release

  • internal/monitoring/monitor_agents.go ApplyHostReport() still ingests unified-agent reports into models.Host compatibility state before unified-resource ingestion and correlation layers consume them.
  • internal/monitoring/monitor.go helper paths like mergeHostAgentSMARTIntoDisks() and the live host snapshot readers still merge host-agent data into node/disk/runtime views.
  • internal/monitoring/monitor_helpers.go isLegacyAgent() and the host sensor/Ceph/SMART conversion helpers still bridge agent payloads into the compatibility state model.
  • internal/monitoring/host_agent_temps.go still uses host-agent sensor data as the authoritative temperature source for linked nodes.
  • internal/monitoring/monitor_host_agents_test.go pins host-agent offline/recovery behavior while this compatibility layer remains live.

Why This Is Not A V6 Leak

  • At the canonical read boundary, those ingested records become unified agent resources.
  • The remaining Host naming is inside the producer/correlation layer, which is exempt from the ReadState consumer-only bans.
  • Monitoring is still the write/ingest side of the architecture, not the canonical v6 read model.

Post-Release Refactor Targets

These are valid rename/structure candidates after the host-agent compatibility state is intentionally retired:

  • internal/monitoring/monitor_agents.go function names like ApplyHostReport, RemoveHostAgent, LinkHostAgent, UnlinkHostAgent
  • internal/monitoring/monitor.go comments and helper locals that still describe canonical agent data as host
  • internal/monitoring/host_agent_temps.go helper names that still encode host agent terminology even though the canonical resource type is agent

These remain naming debt, not release blockers.

AI And Service Discovery Follow-Up

The remaining host-era naming in internal/ai and internal/servicediscovery is mostly internal execution and topology language, not canonical API/resource typing drift.

Must Remain For Release

  • internal/ai/chat/context_prefetch.go ReadState.Hosts() is still used to discover unified-agent backed resources for chat mentions, but the emitted mention type is canonical agent.
  • internal/ai/tools/adapters.go and internal/ai/tools/tools_storage.go AI tools still consume unifiedresources.HostView for RAID/SMART/Ceph data exposed by unified agents. This is already on the canonical read model even though the view name still says Host.
  • internal/servicediscovery/service.go the discovery service still materializes an internal StateSnapshot.Hosts []Host representation for topology analysis, hostname resolution, and redirecting scans to linked agents.
  • internal/servicediscovery/deep_scanner.go command routing still talks about the agent running “on this host”, but the actual target type for canonical execution remains agent.

Why This Is Not A V6 Leak

  • internal/ai already rejects removed host aliases at the API boundary and works with canonical agent execution targets internally.
  • internal/ai/tools reads host-agent data through unified-resource views (HostView) rather than through legacy state.hosts API payload assumptions.
  • internal/servicediscovery uses host as an internal topology concept for machines discovered via the unified agent, not as an exposed removed resource type token.

Post-Release Refactor Targets

These are rename/structure candidates once the compatibility naming debt is worth paying down:

  • internal/servicediscovery/service.go internal Host and StateSnapshot.Hosts naming
  • internal/servicediscovery/deep_scanner.go comments and helper names that still talk about “host” instead of agent-backed machine resources
  • internal/ai/tools user-facing text strings like “host agents” and helper names keyed on HostView / toolHost*

These are naming debt, not release blockers.

Non-Resource Host Terminology

These are unrelated to the removed v5 resource type and should not be treated as migration debt:

  • internal/mock/generator.go Backup payloads use Type: "host" to mean PMG host config backups, not unified resources.
  • internal/monitoring/knownhosts.go SSH known-hosts management.
  • Node configuration and endpoint code using host as a network address or URL host field.

Ratchets Added

  • internal/unifiedresources/code_standards_test.go Added TestV6AgentRegistrationArtifactsStayCanonical to:
    • scan all tests/integration/tests/**/*.{ts,tsx} and tests/integration/evals/**/*.md for legacy host-resource usage patterns
    • prevent regressions in:
    • tests/integration/tests/journeys/04-agent-install-registration.spec.ts
    • tests/integration/evals/tasks/agent-registration.md

The ratchet bans:

  • state.hosts
  • hosts array
  • type: 'host'
  • agent.type = "host"
  • resourceType: "host" / resourceType: 'host'
  • /api/resources?type=host

And requires:

  • unified resources[]

  • unified agent marker type: 'unified' / agent.type = "unified"

  • internal/unifiedresources/code_standards_test.go Added TestV6ReleaseFacingAPITestsCoverLegacyHostRejection to pin release-facing API tests that explicitly reject removed host aliases in chat, AI actions, org shares, reporting, and metrics history.

Post-Release Queue

Priority 1: unblock and finish executable guardrails

  • restore a green compile/test surface around internal/api, internal/ai/tools, and internal/unifiedresources
  • land the blocked API-level normalizer ratchets for reporting and metrics history

Priority 2: rename compatibility-layer terminology

  • internal/api/agent_ingest.go
  • internal/monitoring/monitor_agents.go
  • internal/models/models.go
  • internal/models/models_frontend.go
  • internal/models/converters.go
  • internal/servicediscovery/service.go

Priority 3: collapse remaining compat storage when feasible

  • retire StateSnapshot.Hosts / models.Host* only after agent-ingest, monitoring, routing, and discovery no longer require the compatibility bridge
  • only do this alongside a deliberate compatibility-removal plan, not as opportunistic cleanup