--- phase: 10-classification-layer plan: 01 type: execute wave: 1 depends_on: [] files_modified: - classify/types.go - classify/rules.go autonomous: true requirements: - PROTO-01 - PROTO-02 - PROTO-03 - PROTO-04 - PROTO-05 - PROTO-06 - PROTO-07 - PROTO-08 must_haves: truths: - "21 new TrafficClass constants exist with correct string values per D-05" - "AllClasses() returns 32 classes (18 new + 14 existing, excluding LDAP/Kerberos/Syslog per D-01/D-02)" - "DefaultRules contains 30 new port-matching rules before the catch-alls per D-06" - "Plain/TLS variants share a single class constant per D-03" - "SMTP (port 25) and SMTP-sub (port 587) remain separate classes per D-04" artifacts: - path: "classify/types.go" provides: "21 new TrafficClass constants and updated AllClasses()" contains: "ClassIMAP" - path: "classify/rules.go" provides: "30 new port-matching rules" contains: "ClassMongoDB" key_links: - from: "classify/rules.go" to: "classify/types.go" via: "Rule.Class references TrafficClass constants" pattern: "Class:\\s+Class(IMAP|POP3|FTP|RDP|MySQL)" --- Add all 21 new TrafficClass constants and 30 new port-matching rules to the classify package. Purpose: Phase 10 expands protocol coverage from 14 to 35 traffic classes. This plan adds the production code — constants in types.go and rules in rules.go. Tests are added in Plan 02. Output: Updated classify/types.go with 21 new constants and updated AllClasses(), updated classify/rules.go with 30 new rules organized by family. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @classify/types.go @classify/rules.go From classify/types.go: ```go type TrafficClass string const ( ClassICMP TrafficClass = "ICMP" ClassDNS TrafficClass = "DNS" // ... 12 more existing constants ) func AllClasses() []TrafficClass { return []TrafficClass{ ClassICMP, ClassDNS, ClassHTTPS, ClassHTTP, ClassSSH, ClassSMTP, ClassNTP, ClassDHCP, ClassOtherTCP, ClassOtherUDP, ClassUnknown1, ClassUnknown2, ClassUnknown3, ClassUnknown4, } } ``` From classify/rules.go: ```go type Rule struct { Protocol string DstPort uint16 Class TrafficClass } var DefaultRules = []Rule{ // 10 specific rules + 2 catch-alls (tcp/0 and udp/0 must be last) } ``` Task 1: Add 21 new TrafficClass constants and update AllClasses() classify/types.go - classify/types.go (current constants and AllClasses implementation) - synth/config.go lines 74-110 (frequency table comment showing expected class names) Add 21 new TrafficClass constants to the existing const block in classify/types.go. Group them by family with comments. The exact constants and string values (per D-05 naming convention): ```go // --- Mail (PROTO-01) --- ClassIMAP TrafficClass = "IMAP" ClassPOP3 TrafficClass = "POP3" ClassSMTPSub TrafficClass = "SMTP-sub" // D-04: separate from ClassSMTP (port 25) // --- File Transfer (PROTO-02) --- ClassFTP TrafficClass = "FTP" ClassSMB TrafficClass = "SMB" ClassTFTP TrafficClass = "TFTP" // --- Remote Access (PROTO-03) --- ClassRDP TrafficClass = "RDP" ClassTelnet TrafficClass = "Telnet" ClassVNC TrafficClass = "VNC" // --- Database (PROTO-04) --- ClassMySQL TrafficClass = "MySQL" ClassPostgreSQL TrafficClass = "PostgreSQL" ClassRedis TrafficClass = "Redis" ClassMongoDB TrafficClass = "MongoDB" // --- Discovery (PROTO-05) --- ClassMDNS TrafficClass = "mDNS" ClassSSDP TrafficClass = "SSDP" ClassSNMP TrafficClass = "SNMP" // --- VoIP (PROTO-06) --- ClassSIP TrafficClass = "SIP" // --- Web extension (PROTO-07) --- ClassQUIC TrafficClass = "QUIC" // --- Infrastructure extension (PROTO-08, D-01: no ClassFreqConfigs until Phase 11) --- ClassLDAP TrafficClass = "LDAP" ClassKerberos TrafficClass = "Kerberos" ClassSyslog TrafficClass = "Syslog" ``` Update AllClasses() to return 32 classes. Add 18 new classes (all except LDAP, Kerberos, Syslog — those are excluded per D-01/D-02 to keep synth/config_test.go green). Organize by group with comments: ```go func AllClasses() []TrafficClass { return []TrafficClass{ // Infrastructure ClassICMP, ClassDNS, ClassNTP, ClassDHCP, ClassMDNS, ClassSSDP, ClassSNMP, // Web ClassHTTPS, ClassHTTP, ClassQUIC, // Mail ClassSMTP, ClassIMAP, ClassPOP3, ClassSMTPSub, // Remote Access ClassSSH, ClassRDP, ClassTelnet, ClassVNC, // File Transfer ClassFTP, ClassSMB, ClassTFTP, // Database ClassMySQL, ClassPostgreSQL, ClassRedis, ClassMongoDB, // VoIP ClassSIP, // Unknown / catch-all ClassUnknown1, ClassUnknown2, ClassUnknown3, ClassUnknown4, ClassOtherTCP, ClassOtherUDP, } } ``` IMPORTANT: Do NOT add ClassLDAP, ClassKerberos, or ClassSyslog to AllClasses(). They get constants and rules but are excluded from AllClasses() to avoid breaking TestAllClassesHaveConfig in synth/config_test.go. They will be added in Phase 11 when their ClassFreqConfigs entries are created. cd /home/dev/workspace/yoloyolo && go build ./classify/... - classify/types.go contains `ClassIMAP TrafficClass = "IMAP"` - classify/types.go contains `ClassPOP3 TrafficClass = "POP3"` - classify/types.go contains `ClassSMTPSub TrafficClass = "SMTP-sub"` - classify/types.go contains `ClassFTP TrafficClass = "FTP"` - classify/types.go contains `ClassSMB TrafficClass = "SMB"` - classify/types.go contains `ClassTFTP TrafficClass = "TFTP"` - classify/types.go contains `ClassRDP TrafficClass = "RDP"` - classify/types.go contains `ClassTelnet TrafficClass = "Telnet"` - classify/types.go contains `ClassVNC TrafficClass = "VNC"` - classify/types.go contains `ClassMySQL TrafficClass = "MySQL"` - classify/types.go contains `ClassPostgreSQL TrafficClass = "PostgreSQL"` - classify/types.go contains `ClassRedis TrafficClass = "Redis"` - classify/types.go contains `ClassMongoDB TrafficClass = "MongoDB"` - classify/types.go contains `ClassMDNS TrafficClass = "mDNS"` - classify/types.go contains `ClassSSDP TrafficClass = "SSDP"` - classify/types.go contains `ClassSNMP TrafficClass = "SNMP"` - classify/types.go contains `ClassSIP TrafficClass = "SIP"` - classify/types.go contains `ClassQUIC TrafficClass = "QUIC"` - classify/types.go contains `ClassLDAP TrafficClass = "LDAP"` - classify/types.go contains `ClassKerberos TrafficClass = "Kerberos"` - classify/types.go contains `ClassSyslog TrafficClass = "Syslog"` - AllClasses() body contains ClassSIP but does NOT contain ClassLDAP, ClassKerberos, or ClassSyslog - `go build ./classify/...` succeeds 21 new TrafficClass constants defined, AllClasses() returns 32 classes (excluding LDAP/Kerberos/Syslog), package compiles Task 2: Add 30 new port-matching rules to DefaultRules classify/rules.go - classify/rules.go (current DefaultRules with 12 entries) - classify/types.go (after Task 1 — verify new constants exist) Replace the DefaultRules slice in classify/rules.go with the expanded version containing all 42 rules (12 existing + 30 new). All new specific-port rules MUST appear BEFORE the two catch-all entries (per D-06). Group rules by family with comments for readability. The complete DefaultRules slice: ```go var DefaultRules = []Rule{ // --- Infrastructure --- {Protocol: "icmp", DstPort: 0, Class: ClassICMP}, {Protocol: "udp", DstPort: 53, Class: ClassDNS}, {Protocol: "tcp", DstPort: 53, Class: ClassDNS}, {Protocol: "udp", DstPort: 123, Class: ClassNTP}, {Protocol: "udp", DstPort: 67, Class: ClassDHCP}, {Protocol: "udp", DstPort: 68, Class: ClassDHCP}, // --- Discovery (PROTO-05) --- {Protocol: "udp", DstPort: 5353, Class: ClassMDNS}, {Protocol: "udp", DstPort: 1900, Class: ClassSSDP}, {Protocol: "udp", DstPort: 161, Class: ClassSNMP}, {Protocol: "udp", DstPort: 162, Class: ClassSNMP}, // --- Web (existing + PROTO-07) --- {Protocol: "tcp", DstPort: 443, Class: ClassHTTPS}, {Protocol: "udp", DstPort: 443, Class: ClassQUIC}, // PROTO-07: must use "udp", NOT "tcp" {Protocol: "tcp", DstPort: 80, Class: ClassHTTP}, // --- Mail (existing SMTP + PROTO-01) --- {Protocol: "tcp", DstPort: 25, Class: ClassSMTP}, {Protocol: "tcp", DstPort: 143, Class: ClassIMAP}, // D-03: IMAP plain {Protocol: "tcp", DstPort: 993, Class: ClassIMAP}, // D-03: IMAPS {Protocol: "tcp", DstPort: 110, Class: ClassPOP3}, // D-03: POP3 plain {Protocol: "tcp", DstPort: 995, Class: ClassPOP3}, // D-03: POP3S {Protocol: "tcp", DstPort: 587, Class: ClassSMTPSub}, // D-04: separate from SMTP // --- Remote Access (existing SSH + PROTO-03) --- {Protocol: "tcp", DstPort: 22, Class: ClassSSH}, {Protocol: "tcp", DstPort: 3389, Class: ClassRDP}, {Protocol: "tcp", DstPort: 23, Class: ClassTelnet}, {Protocol: "tcp", DstPort: 5900, Class: ClassVNC}, // --- File Transfer (PROTO-02) --- {Protocol: "tcp", DstPort: 20, Class: ClassFTP}, // D-03: FTP data {Protocol: "tcp", DstPort: 21, Class: ClassFTP}, // D-03: FTP control {Protocol: "tcp", DstPort: 445, Class: ClassSMB}, {Protocol: "udp", DstPort: 69, Class: ClassTFTP}, // --- Database (PROTO-04) --- {Protocol: "tcp", DstPort: 3306, Class: ClassMySQL}, {Protocol: "tcp", DstPort: 5432, Class: ClassPostgreSQL}, {Protocol: "tcp", DstPort: 6379, Class: ClassRedis}, {Protocol: "tcp", DstPort: 27017, Class: ClassMongoDB}, // --- VoIP (PROTO-06) --- {Protocol: "tcp", DstPort: 5060, Class: ClassSIP}, // D-03: SIP plain TCP {Protocol: "tcp", DstPort: 5061, Class: ClassSIP}, // D-03: SIPS TCP {Protocol: "udp", DstPort: 5060, Class: ClassSIP}, // D-03: SIP plain UDP {Protocol: "udp", DstPort: 5061, Class: ClassSIP}, // D-03: SIPS UDP // --- Infrastructure extension (PROTO-08, D-01) --- {Protocol: "tcp", DstPort: 389, Class: ClassLDAP}, // D-03: LDAP plain {Protocol: "tcp", DstPort: 636, Class: ClassLDAP}, // D-03: LDAPS {Protocol: "tcp", DstPort: 88, Class: ClassKerberos}, {Protocol: "udp", DstPort: 88, Class: ClassKerberos}, {Protocol: "udp", DstPort: 514, Class: ClassSyslog}, // Catch-alls (must be last — D-06): {Protocol: "tcp", DstPort: 0, Class: ClassOtherTCP}, {Protocol: "udp", DstPort: 0, Class: ClassOtherUDP}, } ``` CRITICAL: The two catch-all rules `{tcp, 0, ClassOtherTCP}` and `{udp, 0, ClassOtherUDP}` MUST remain as the last two entries. All 30 new specific-port rules go before them. Do NOT add port 465 (SMTPS) — PROTO-01 only specifies port 587. cd /home/dev/workspace/yoloyolo && go build ./classify/... - classify/rules.go contains `DstPort: 143, Class: ClassIMAP` - classify/rules.go contains `DstPort: 993, Class: ClassIMAP` - classify/rules.go contains `DstPort: 110, Class: ClassPOP3` - classify/rules.go contains `DstPort: 995, Class: ClassPOP3` - classify/rules.go contains `DstPort: 587, Class: ClassSMTPSub` - classify/rules.go contains `DstPort: 20, Class: ClassFTP` - classify/rules.go contains `DstPort: 21, Class: ClassFTP` - classify/rules.go contains `DstPort: 445, Class: ClassSMB` - classify/rules.go contains `DstPort: 69, Class: ClassTFTP` - classify/rules.go contains `DstPort: 3389, Class: ClassRDP` - classify/rules.go contains `DstPort: 23, Class: ClassTelnet` - classify/rules.go contains `DstPort: 5900, Class: ClassVNC` - classify/rules.go contains `DstPort: 3306, Class: ClassMySQL` - classify/rules.go contains `DstPort: 5432, Class: ClassPostgreSQL` - classify/rules.go contains `DstPort: 6379, Class: ClassRedis` - classify/rules.go contains `DstPort: 27017, Class: ClassMongoDB` - classify/rules.go contains `DstPort: 5353, Class: ClassMDNS` - classify/rules.go contains `DstPort: 1900, Class: ClassSSDP` - classify/rules.go contains `DstPort: 161, Class: ClassSNMP` - classify/rules.go contains `DstPort: 162, Class: ClassSNMP` - classify/rules.go contains `DstPort: 5060, Class: ClassSIP` (both tcp and udp) - classify/rules.go contains `DstPort: 5061, Class: ClassSIP` (both tcp and udp) - classify/rules.go contains `Protocol: "udp", DstPort: 443, Class: ClassQUIC` - classify/rules.go contains `DstPort: 389, Class: ClassLDAP` - classify/rules.go contains `DstPort: 636, Class: ClassLDAP` - classify/rules.go contains `DstPort: 88, Class: ClassKerberos` (both tcp and udp) - classify/rules.go contains `DstPort: 514, Class: ClassSyslog` - classify/rules.go does NOT contain `DstPort: 465` - The last two entries in DefaultRules are the catch-all rules (DstPort: 0) - `go build ./classify/...` succeeds DefaultRules contains 42 rules (12 existing + 30 new), all specific-port rules before catch-alls, package compiles - `go build ./classify/...` compiles without errors - 21 new constants exist in types.go - AllClasses() has 32 entries (14 existing + 18 new, excluding LDAP/Kerberos/Syslog) - DefaultRules has 42 entries (12 existing + 30 new) with catch-alls last - All 21 new TrafficClass constants compile - AllClasses() returns exactly 32 classes - DefaultRules has exactly 42 rules with catch-alls as last 2 entries - `go build ./classify/...` passes After completion, create `.planning/phases/10-classification-layer/10-01-SUMMARY.md`