docs(13-01): complete interface info collector plan

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-19 06:07:51 -05:00
parent 397a33abef
commit f0e7c5c00e
4 changed files with 129 additions and 9 deletions

View File

@@ -38,7 +38,7 @@
### Link Discovery ### Link Discovery
- [ ] **LINK-01**: Backend auto-discovers AP-CPE relationships by matching registration table MAC addresses against known device interface MACs - [x] **LINK-01**: Backend auto-discovers AP-CPE relationships by matching registration table MAC addresses against known device interface MACs
- [x] **LINK-02**: Link state uses a temporal state machine (discovered -> active -> degraded -> down -> stale) with consecutive-miss threshold to prevent false flapping - [x] **LINK-02**: Link state uses a temporal state machine (discovered -> active -> degraded -> down -> stale) with consecutive-miss threshold to prevent false flapping
- [x] **LINK-03**: Wireless links are stored in a materialized table for fast dashboard queries - [x] **LINK-03**: Wireless links are stored in a materialized table for fast dashboard queries
- [ ] **LINK-04**: Unmanaged wireless clients (MACs not matching any TOD device) are displayed as "unknown clients" with signal/rate data - [ ] **LINK-04**: Unmanaged wireless clients (MACs not matching any TOD device) are displayed as "unknown clients" with signal/rate data
@@ -113,7 +113,7 @@
| WRCL-04 | Phase 12 | Complete | | WRCL-04 | Phase 12 | Complete |
| WRCL-05 | Phase 12 | Complete | | WRCL-05 | Phase 12 | Complete |
| WRCL-06 | Phase 12 | Complete | | WRCL-06 | Phase 12 | Complete |
| LINK-01 | Phase 13 | Pending | | LINK-01 | Phase 13 | Complete |
| LINK-02 | Phase 13 | Complete | | LINK-02 | Phase 13 | Complete |
| LINK-03 | Phase 13 | Complete | | LINK-03 | Phase 13 | Complete |
| LINK-04 | Phase 13 | Pending | | LINK-04 | Phase 13 | Pending |

View File

@@ -84,7 +84,7 @@ Plans:
2. Link state follows a temporal state machine (discovered, active, degraded, down, stale) with consecutive-miss threshold to prevent false flapping 2. Link state follows a temporal state machine (discovered, active, degraded, down, stale) with consecutive-miss threshold to prevent false flapping
3. Discovered links are stored in a materialized wireless_links table for fast dashboard queries 3. Discovered links are stored in a materialized wireless_links table for fast dashboard queries
4. Wireless clients whose MACs do not match any managed device appear as "unknown clients" with their signal and rate data preserved 4. Wireless clients whose MACs do not match any managed device appear as "unknown clients" with their signal and rate data preserved
**Plans:** 1/3 plans executed **Plans:** 2/3 plans executed
Plans: Plans:
- [ ] 13-01-PLAN.md — Go poller interface collector (/interface/print) and DEVICE_EVENTS publisher - [ ] 13-01-PLAN.md — Go poller interface collector (/interface/print) and DEVICE_EVENTS publisher
@@ -130,7 +130,7 @@ Plans:
| Sites | SITE-01, SITE-02, SITE-03, SITE-04, SITE-05, SITE-06 | 11 | 3/3 | Complete | 2026-03-19 | DASH-01 | 11 | 1 | | Sites | SITE-01, SITE-02, SITE-03, SITE-04, SITE-05, SITE-06 | 11 | 3/3 | Complete | 2026-03-19 | DASH-01 | 11 | 1 |
| Site Dashboard | DASH-02, DASH-03, DASH-04 | 14 | 3 | | Site Dashboard | DASH-02, DASH-03, DASH-04 | 14 | 3 |
| Sectors | SECT-01, SECT-02, SECT-03 | 14 | 3 | | Sectors | SECT-01, SECT-02, SECT-03 | 14 | 3 |
| Wireless Collection | WRCL-01, WRCL-02, WRCL-03, WRCL-04, WRCL-05, WRCL-06 | 12 | 2/2 | Complete | 2026-03-19 | LINK-01, LINK-02, LINK-03, LINK-04 | 13 | 1/3 | In Progress| | WRUI-01, WRUI-02, WRUI-03 | 14 | 3 | | Wireless Collection | WRCL-01, WRCL-02, WRCL-03, WRCL-04, WRCL-05, WRCL-06 | 12 | 2/2 | Complete | 2026-03-19 | LINK-01, LINK-02, LINK-03, LINK-04 | 13 | 2/3 | In Progress| | WRUI-01, WRUI-02, WRUI-03 | 14 | 3 |
| Signal Trending | TRND-01, TRND-02 | 15 | 2 | | Signal Trending | TRND-01, TRND-02 | 15 | 2 |
| Site Alerting | ALRT-01, ALRT-02 | 15 | 2 | | Site Alerting | ALRT-01, ALRT-02 | 15 | 2 |
| **Total** | | | **30** | | **Total** | | | **30** |

View File

@@ -2,9 +2,9 @@
gsd_state_version: 1.0 gsd_state_version: 1.0
milestone: v9.7 milestone: v9.7
milestone_name: Tower & Site Management milestone_name: Tower & Site Management
status: executing status: unknown
stopped_at: Completed 13-02-PLAN.md stopped_at: Completed 13-01-PLAN.md
last_updated: "2026-03-19T11:02:22Z" last_updated: "2026-03-19T11:07:35.900Z"
progress: progress:
total_phases: 5 total_phases: 5
completed_phases: 2 completed_phases: 2
@@ -41,6 +41,7 @@ Plan: 2 of 3
| 11 | 3 | 12min | 4min | | 11 | 3 | 12min | 4min |
| 12 | 2 | 6min | 3min | | 12 | 2 | 6min | 3min |
| 13 | 2 | 5min | 2.5min | | 13 | 2 | 5min | 2.5min |
| Phase 13 P01 | 5min | 2 tasks | 4 files |
## Accumulated Context ## Accumulated Context
@@ -68,6 +69,8 @@ Decisions are logged in PROJECT.md Key Decisions table.
- [Phase 12]: WIRELESS_REGISTRATIONS NATS stream uses 30-day retention (vs 24h for DEVICE_EVENTS) for historical client analytics - [Phase 12]: WIRELESS_REGISTRATIONS NATS stream uses 30-day retention (vs 24h for DEVICE_EVENTS) for historical client analytics
- [Phase 12]: RF monitor collection gated on wireless interface presence to avoid unnecessary API calls - [Phase 12]: RF monitor collection gated on wireless interface presence to avoid unnecessary API calls
- [Phase 13]: No backref on DeviceInterface.device relationship -- link discovery reads interfaces directionally - [Phase 13]: No backref on DeviceInterface.device relationship -- link discovery reads interfaces directionally
- [Phase 13]: MAC addresses lowercased at collection time for consistent downstream matching
- [Phase 13]: InterfaceInfo (identity/link discovery) kept separate from InterfaceStats (traffic counters)
### Pending Todos ### Pending Todos
@@ -81,6 +84,6 @@ None yet.
## Session Continuity ## Session Continuity
Last session: 2026-03-19T11:02:22Z Last session: 2026-03-19T11:07:35.897Z
Stopped at: Completed 13-02-PLAN.md Stopped at: Completed 13-01-PLAN.md
Resume file: None Resume file: None

View File

@@ -0,0 +1,117 @@
---
phase: 13-link-discovery-registration-ingestion
plan: 01
subsystem: poller
tags: [routeros, nats, interfaces, mac-address, link-discovery, go]
requires:
- phase: 12-wireless-registration-collection
provides: "NATS publisher pattern, WIRELESS_REGISTRATIONS stream, withTimeout wrapper"
provides:
- "InterfaceInfo struct with name, MAC, type, running fields"
- "CollectInterfaceInfo function for RouterOS /interface/print"
- "DeviceInterfaceEvent NATS publisher on device.interfaces.{device_id}"
- "DEVICE_EVENTS stream includes device.interfaces.> subject"
affects: [13-link-discovery-registration-ingestion, link-state-machine, topology-map]
tech-stack:
added: []
patterns: [interface-identity-collector, mac-normalization]
key-files:
created:
- poller/internal/device/interfaces.go
- poller/internal/device/interfaces_test.go
modified:
- poller/internal/bus/publisher.go
- poller/internal/poller/worker.go
key-decisions:
- "MAC addresses lowercased at collection time for consistent downstream matching"
- "Entries without mac-address skipped (loopback, bridge without MAC)"
- "Interface info collected separately from traffic counters (InterfaceInfo vs InterfaceStats)"
patterns-established:
- "MAC normalization: all MAC addresses lowercased at the collection layer before publishing"
- "InterfaceInfo vs InterfaceStats: identity data (link discovery) separate from traffic counters (metrics)"
requirements-completed: [LINK-01]
duration: 5min
completed: 2026-03-19
---
# Phase 13 Plan 01: Interface Info Collector Summary
**Go poller InterfaceInfo collector publishing MAC addresses to DEVICE_EVENTS NATS stream for link discovery**
## Performance
- **Duration:** 5 min
- **Started:** 2026-03-19T11:00:38Z
- **Completed:** 2026-03-19T11:06:20Z
- **Tasks:** 2
- **Files modified:** 4
## Accomplishments
- InterfaceInfo struct and CollectInterfaceInfo function collect name, MAC, type, running from /interface/print
- MAC addresses lowercased at collection time for consistent downstream link resolution
- DeviceInterfaceEvent publisher sends to device.interfaces.{device_id} on DEVICE_EVENTS stream
- Wired into PollDevice cycle after traffic counters, before health metrics
## Task Commits
Each task was committed atomically:
1. **Task 1: Create interface info collector with v6/v7 routing** - `4b5bb94` (test) + `6939584` (feat)
2. **Task 2: Add DeviceInterfaceEvent publisher, update DEVICE_EVENTS stream, wire into PollDevice** - `397a33a` (feat)
_Note: Task 1 used TDD with separate test and implementation commits_
## Files Created/Modified
- `poller/internal/device/interfaces.go` - InterfaceInfo struct, CollectInterfaceInfo function, MAC normalization (added alongside existing InterfaceStats)
- `poller/internal/device/interfaces_test.go` - Unit tests for struct fields, MAC lowercasing, running bool parsing
- `poller/internal/bus/publisher.go` - DeviceInterfaceEvent type, PublishDeviceInterfaces method, device.interfaces.> added to DEVICE_EVENTS stream
- `poller/internal/poller/worker.go` - Interface info collection wired into PollDevice after traffic counters
## Decisions Made
- MAC addresses lowercased at collection time (strings.ToLower) so downstream consumers never need to normalize
- Entries without mac-address are silently skipped (loopback, bridge without MAC are not useful for link discovery)
- InterfaceInfo is a separate type from InterfaceStats -- identity data for link discovery vs traffic counters for metrics
- Collection placed after traffic counters, before health metrics in PollDevice to group interface-related work
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] Restored InterfaceStats collector overwritten during file creation**
- **Found during:** Task 1
- **Issue:** Creating interfaces.go overwrote the pre-existing InterfaceStats type and CollectInterfaces function that publisher.go and worker.go depend on
- **Fix:** Restored InterfaceStats and CollectInterfaces, appended new InterfaceInfo types below
- **Files modified:** poller/internal/device/interfaces.go
- **Verification:** go build ./... succeeds
- **Committed in:** 6939584 (Task 1 commit)
---
**Total deviations:** 1 auto-fixed (1 blocking)
**Impact on plan:** File creation overwrote existing code; restored immediately. No scope creep.
## Issues Encountered
None beyond the deviation noted above.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- Interface MAC data now published to NATS on every poll cycle
- Backend subscriber (Plan 03) can consume device.interfaces.> to populate device_interfaces table
- Link discovery (Plan 02) can match registration MACs against interface MACs for topology resolution
## Self-Check: PASSED
All 4 files verified present. All 3 commits verified in git log.
---
*Phase: 13-link-discovery-registration-ingestion*
*Completed: 2026-03-19*