Initial commit: NetworkCity — network traffic as a neon city

A native macOS network monitor that renders live traffic as a top-down
neon city: your Mac is downtown, remote orgs are glowing districts, and
traffic is cars of light driving the roads.

Architecture:
- NetworkCityCore: swappable data layer behind a ConnectionSource protocol
  (nettop-backed today), plus pure/tested logic — traffic diffing, org
  classification (reverse-DNS + CIDR), traffic classes, hub-and-spoke
  expansion policy, label anti-overlap, and latency→distance layout.
- NetworkCityApp: SwiftUI + SpriteKit city — auto-expanding districts,
  protocol-coloured cars, click-to-inspect panel, and latency-as-distance
  (districts glide to their measured RTT).
- nettop-probe: CLI proof of the data layer.

44 tests passing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-13 08:43:32 -07:00
commit c08fc277a9
33 changed files with 2499 additions and 0 deletions
@@ -0,0 +1,40 @@
import Foundation
/// A coarse traffic category derived from protocol + port, used to colour the
/// cars of light. Direction (in/out) is conveyed by motion, so colour is free
/// to mean "what kind of traffic is this".
public enum TrafficClass: String, Sendable, CaseIterable {
case dns
case https
case http
case quic
case other
/// Human label for the legend.
public var label: String {
switch self {
case .dns: return "DNS"
case .https: return "HTTPS"
case .http: return "HTTP"
case .quic: return "QUIC"
case .other: return "Other"
}
}
public static func classify(proto: NetProtocol, port: Int?) -> TrafficClass {
// nettop labels QUIC explicitly; trust that first.
if proto == .quic4 || proto == .quic6 { return .quic }
let isUDP = (proto == .udp4 || proto == .udp6)
switch port {
case 53, 5353:
return .dns
case 443:
return isUDP ? .quic : .https // UDP/443 is almost always QUIC
case 80, 8080:
return .http
default:
return .other
}
}
}