feat: attach availability checks as facet on known resource row

Agentless availability checks (ICMP/TCP/HTTP) were always minting
standalone network-endpoint resources, leaving them disconnected from
the known Proxmox/Docker guest they actually monitor. This made
availability evidence invisible on the platform resource row where the
user expects it, per the performance-and-scalability bounded-row
contract.

Backend (unified-resources ingest):
- Add LinkedResourceID field to AvailabilityData and AvailabilityTarget
- resolveAvailabilityLink: explicit link first, then exact-IP unambiguous
  correlation; skip hostname-only (lossy); guard against overwriting a
  different target's facet
- Unlinked/unmatched probes still mint network-endpoint (fallback)

Frontend:
- Relax getAvailabilityProbePresentation for any resource with availability
- Add compact protocol badge to UnifiedResourceHostTableCard name cell
- Add optional 'Link to resource' field to availability target form
- Add linkedResourceId to frontend types

Contracts: api-contracts, unified-resources, monitoring,
performance-and-scalability, storage-recovery.

Governance: coverage_gap + candidate_lane in status.json.
This commit is contained in:
rcourtman
2026-06-26 12:16:11 +01:00
parent adf6c6f1e5
commit 62c2b765d0
23 changed files with 548 additions and 24 deletions
@@ -366,16 +366,19 @@ func TestAgentlessAvailabilityTargetKindStaysCanonical(t *testing.T) {
"AvailabilityTargetDevice AvailabilityTargetKind = \"device\"",
"TargetKind AvailabilityTargetKind `json:\"targetKind,omitempty\"`",
"target.TargetKind = AvailabilityTargetKind(strings.ToLower(strings.TrimSpace(string(target.TargetKind))))",
"LinkedResourceID string `json:\"linkedResourceId,omitempty\"`",
},
filepath.Join("..", "monitoring", "availability_poller.go"): {
"TargetKind string `json:\"targetKind,omitempty\"`",
"TargetKind: string(target.TargetKind),",
"TargetKind: string(target.TargetKind),",
"tags = append(tags, string(target.TargetKind))",
"LinkedResourceID: strings.TrimSpace(target.LinkedResourceID),",
},
"types.go": {
"Availability *AvailabilityData `json:\"availability,omitempty\"`",
"TargetKind string `json:\"targetKind,omitempty\"`",
"LinkedResourceID string `json:\"linkedResourceId,omitempty\"`",
},
filepath.Join("..", "..", "frontend-modern", "src", "api", "availabilityTargets.ts"): {
"export type AvailabilityTargetKind = 'machine' | 'service' | 'device';",