Skip to content

Add auto-provisioning and TcpServer integration to TrackerManager #7

Description

@jonnyspicer

Summary

Wire the TcpServer into TrackerManager, add auto-provisioning of tracker instances for unknown nodes, and handle disconnect/reconnect lifecycle.

Context

Depends on #5 (DetectionSource protocol) and #6 (TcpServer + TcpReceiver).

See design spec: docs/superpowers/specs/2026-03-11-tcp-push-detection-forwarding-design.md in the retina monorepo.

Changes

Updated: TrackerManager (tracker_host/manager.py)

  • Start TcpServer on init if tcp_server.enabled in config
  • For mode: "tcp" trackers in config: create TcpReceiver, register with TcpServer, create TrackerInstance with that receiver
  • For mode: "http" trackers: existing behavior (create DetectionFetcher-backed instance)
  • Auto-provisioning callback: register a callback with TcpServer for unknown node_ids. When a frame arrives from an unknown node with a valid token:
    • Auto-assign a local TCP port from auto_provision_port_start to auto_provision_port_end
    • Create a TcpReceiver and register with TcpServer
    • Create a TrackerInstance with default settings
    • Start the instance (spawns retina-tracker subprocess)
    • Log the auto-provisioning event
  • Reject auto-provisioning when port range is exhausted (log error)

Disconnect/reconnect lifecycle

  • On node disconnect: TcpReceiver.is_healthy becomes False. TrackerInstance keeps subprocess alive for extended_outage_sec (existing behavior via fetch loop).
  • On reconnect: TcpServer routes to existing TcpReceiver. Node's buffered frames drain through. Subprocess continues processing.
  • After extended_outage_sec: subprocess killed, instance stays registered in memory.
  • Late reconnect: subprocess respawned automatically when frames arrive again.

Graceful shutdown

  • Stop accepting new TCP connections
  • Close all node connections (nodes reconnect automatically)
  • Drain in-progress frames
  • Stop all tracker subprocesses (existing TrackerManager.stop() behavior)

Updated: config parsing

  • Parse tcp_server block into TcpServerConfig
  • Updated config.yaml with tcp_server section

Acceptance criteria

  • TcpServer starts when enabled in config
  • TCP-mode trackers in config get TcpReceiver-backed instances
  • HTTP-mode trackers continue working unchanged
  • Unknown nodes with valid tokens get auto-provisioned
  • Auto-provisioned nodes get ports from configured range
  • Port exhaustion logged and handled gracefully
  • Reconnecting nodes reattach to existing instances
  • Subprocess stays alive during grace period
  • Graceful shutdown closes connections and drains frames
  • Unit tests for auto-provisioning and lifecycle

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions