--- phase: 01-capture-and-classification plan: 02 subsystem: capture tags: [go-pcap, gopacket, packet-capture, privilege-handling, cgo-free-capture] # Dependency graph requires: - phase: 01-capture-and-classification/01-01 provides: classify/types.go with TrafficClass, ClassifiedPacket, WindowSnapshot types provides: - capture package with OpenCapture, ListInterfaces, StartCapture functions - Platform-specific privilege error messages (Linux setcap hint, macOS sudo hint) - Channel-based packet source with 512-buffer and atomic drop counter affects: - cmd/root.go (will call StartCapture and ListInterfaces) - Phase 2 audio synthesis (receives packets from StartCapture channel) # Tech tracking tech-stack: added: - github.com/packetcap/go-pcap v0.0.0-20251215 (pure-Go live capture) - github.com/sirupsen/logrus v1.9.3 (transitive dep of go-pcap) patterns: - TDD RED/GREEN: write failing tests before implementation - net.Interfaces() for listing (not pcap.FindAllDevs which go-pcap lacks) - Non-blocking channel send with atomic.AddInt64 drop counter - Dynamic link type via layers.LinkType(handle.LinkType()) - runtime.GOOS switch for platform-specific error messages key-files: created: - capture/capture.go - capture/capture_test.go modified: - go.mod (added go-pcap) - go.sum (added go-pcap + logrus hashes) key-decisions: - "Use net.Interfaces() for interface listing — go-pcap has no FindAllDevs equivalent" - "StartCapture uses 512-buffered channel with atomic drop counter to avoid backpressure blocking capture goroutine" - "Dynamic link type detection via handle.LinkType() — not hardcoded LinkTypeEthernet" - "Permission errors wrap platform-specific messages: Linux shows setcap, macOS shows sudo" patterns-established: - "Privilege detection: check error string for 'permission denied', 'operation not permitted', 'pcap_create'" - "Platform branching: switch runtime.GOOS with linux case explicit, default for darwin/others" - "Packet pipeline: goroutine reads from packetSource, writes to buffered channel with non-blocking select" requirements-completed: [CAPT-01, CAPT-02, CAPT-04] # Metrics duration: 2min completed: 2026-03-25 --- # Phase 01 Plan 02: Capture Package Summary **Live packet capture via packetcap/go-pcap with ListInterfaces (stdlib-only), OpenCapture with platform-specific CAP_NET_RAW error messages, and non-blocking StartCapture channel pipeline with atomic drop counter** ## Performance - **Duration:** ~2 min - **Started:** 2026-03-25T11:15:54Z - **Completed:** 2026-03-25T11:17:34Z - **Tasks:** 1 (TDD: 2 commits — RED test + GREEN implementation) - **Files modified:** 4 (capture.go, capture_test.go, go.mod, go.sum) ## Accomplishments - capture package implements all 3 required exports: OpenCapture, ListInterfaces, StartCapture - ListInterfaces uses net.Interfaces() — no CGo or pcap dependency for interface enumeration (CAPT-02) - Permission error detection covers all documented error strings; returns platform-specific sudo/setcap hints (CAPT-04, D-05) - StartCapture goroutine uses buffered channel (512) + atomic drop counter — backpressure-safe for high-traffic interfaces ## Task Commits Each task was committed atomically: 1. **Task 1 RED: failing tests for capture package** - `1eb1dd4` (test) 2. **Task 1 GREEN: implement capture package + add go-pcap** - `9446dd5` (feat) _Note: TDD task has two commits (test RED then implementation GREEN)_ ## Files Created/Modified - `capture/capture.go` - ListInterfaces, OpenCapture, StartCapture, isPermissionError, permissionErrorMsg - `capture/capture_test.go` - 5 tests: TestListInterfaces, TestListInterfacesFormat, TestIsPermissionError, TestIsPermissionErrorNegative, TestPermissionErrorMsg (94 lines) - `go.mod` - Added github.com/packetcap/go-pcap v0.0.0-20251215 - `go.sum` - Added go-pcap + logrus hashes ## Decisions Made - net.Interfaces() for interface listing: go-pcap has no FindAllDevs, stdlib net package covers this without privileges - Dynamic link type: capture uses `layers.LinkType(handle.LinkType())` rather than hardcoded `LinkTypeEthernet` — handles lo (null/loopback) and tunnel interfaces - Non-blocking packet send: `select { case packets <- pkt: default: atomic.AddInt64(&droppedPackets, 1) }` prevents slow downstream consumer from blocking capture goroutine ## Deviations from Plan None — plan executed exactly as written. go-pcap version `v0.0.0-20251215121130-f2cf9f991e7c` resolved correctly (RESEARCH.md listed the date prefix `v0.0.0-20251215` which matched). ## Issues Encountered None — all tests passed on first GREEN run. ## User Setup Required None — no external service configuration required. Capture at runtime requires root or CAP_NET_RAW, but build is CGo-free for the capture layer. ## Next Phase Readiness - capture package is ready for consumption by cmd/root.go (Plan 03/04) - StartCapture channel output type is `gopacket.Packet` — classifier (classify package from Plan 01) accepts these via layer assertions - Dropped packets counter (`*int64`) available for capture-end summary statistics --- *Phase: 01-capture-and-classification* *Completed: 2026-03-25* ## Self-Check: PASSED - capture/capture.go: FOUND - capture/capture_test.go: FOUND - 01-02-SUMMARY.md: FOUND - commit 1eb1dd4 (test RED): FOUND - commit 9446dd5 (feat GREEN): FOUND