Skip to content

feat: Connection Graph Model - Phase 1: Port-Based Architecture #362

@ggfevans

Description

@ggfevans

Parent Epic

Part of #71 (Network Interface Visualization and Connectivity)

Supersedes: #261 / PR #355 (cable data model) - refactors to graph-based architecture


Summary

Refactor the cable/connection model from PR #355 to use a proper graph-based architecture with first-class ports. This enables power path traversal, capacity planning, failure impact analysis, and multi-rack support.

Problem

The current Cable model (PR #355) uses an edge-list approach with string-based interface references:

// Current: fragile string references
interface Cable {
  a_device_id: string;
  a_interface: string;  // String name - breaks if renamed
  b_device_id: string;
  b_interface: string;
}

Issues with current approach:

  • No stable port identity (renaming interface breaks connections)
  • Port metadata has nowhere to live (link state, power draw)
  • Traversal requires O(n) string matching at every hop
  • Termination union type violates Open/Closed Principle
  • PDU circuit model is a special-case hack, not generalizable
  • Infrastructure nodes are second-class citizens vs devices

Child Issues

Data Model (v0.7.0)

Issue Title Size Priority
#363 PlacedPort schema and port instantiation M high
#364 Rack.id and Layout.racks array S medium
#365 Connection model refactor (port-ID based) M high
#369 Connection store with validation M high
#370 Port lookup indexes S medium

Extended Model (v0.8.0)

Issue Title Size Priority
#366 InfrastructureNode with ports M medium
#367 InternalConnection generalization M medium
#368 Power interface types and InterfaceRole S low
#371 Migration from Cable to Connection S low

Port Rendering (v0.7.0)

Issue Title Size
#356 Port layout algorithm with multi-row support M
#357 Port render modes (individual and grouped) M
#358 Zoom-aware port rendering thresholds S
#359 Touch-accessible port overlays M
#360 10-inch rack port layout optimizations S

Dependency Graph

Data Model Layer:
  #363 PlacedPort ──────┬──► #365 Connection ──► #369 Store ──► #371 Migration
  #364 Rack.id          │
  #368 Power types ─────┤
                        ├──► #366 InfrastructureNode
                        └──► #367 InternalConnection
  #370 Port indexes ◄───┘

Port Rendering Layer:
  #356 Port layout ──► #357 Render modes ──► #358 Zoom
  #359 Touch overlays                        └──► #360 10"

Cable UI (under #71, depends on this epic):
  #262, #263, #264, #265, #266

Proposed Solution

1. First-Class Ports with Stable Identity

When placing a device, instantiate ports with UUIDs:

interface PlacedPort {
  id: string;              // UUID - stable identity
  template_name: string;   // Reference to InterfaceTemplate.name
  label?: string;          // User override
}

interface PlacedDevice {
  // ...existing fields...
  ports: PlacedPort[];     // Instantiated from DeviceType.interfaces
}

2. Unified Connection Model

Connections reference port IDs, not device+interface strings:

interface Connection {
  id: string;
  connection_class: ConnectionClass;
  a_port_id: string;       // PlacedPort.id - works for devices AND infra
  b_port_id: string;
  cable?: CableProperties;
  status?: ConnectionStatus;
  role?: ConnectionRole;
  redundancy_group?: string;
}

3. Infrastructure Nodes with Same Port Model

interface InfrastructureNode {
  id: string;
  node_type: InfraNodeType;
  name: string;
  scope: InfraScope;
  ports: PlacedPort[];     // Same structure as device ports!
}

4. Generalized Internal Connections

interface InternalConnection {
  from_interface: string;
  to_interfaces: string[];
  connection_type: 'power-distribution' | 'passthrough' | 'fabric' | 'stacking';
  circuit_name?: string;
  breaker_amps?: number;
}

Acceptance Criteria

Schema Changes

  • PlacedPort interface with id, template_name, label
  • PlacedDevice.ports: PlacedPort[] field
  • Connection uses a_port_id/b_port_id (UUIDs)
  • InfrastructureNode with ports: PlacedPort[]
  • InternalConnection on DeviceType
  • InterfaceTemplate.role and electrical fields
  • Power interface types in InterfaceType enum
  • Rack.id field for multi-rack support
  • Layout.racks is array
  • Connection.role and redundancy_group fields

Store/Logic Changes

  • Port instantiation when placing device
  • Connection validation uses port IDs
  • Port lookup indexes (O(1) queries)
  • Validation: port can only have one connection
  • Validation: incompatible port types
  • Zod schemas for all new types

Migration

  • Existing Cable data migrates to Connection format

Architecture Decision Record

This refactor was driven by analysis of graph-based infrastructure modeling:

  1. Everything with ports should be uniform - devices and infrastructure both have ports
  2. Ports need stable identity - UUIDs, not string names
  3. Connections are edges between ports - simple a_port_id → b_port_id
  4. Internal topology is generalizable - not just PDUs, also patch panels, chassis
  5. Multi-rack ready - rack IDs and infrastructure scoping for future expansion

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions