35 traffic classes across 9 protocol families shipped. Archives ROADMAP, REQUIREMENTS, and phase directories to milestones/v1.2-*. Updates README with new protocol families, sound design table, and [groups] TOML config documentation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
347 lines
14 KiB
Markdown
347 lines
14 KiB
Markdown
---
|
|
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)"
|
|
---
|
|
|
|
<objective>
|
|
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.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
|
@$HOME/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@classify/types.go
|
|
@classify/rules.go
|
|
|
|
<interfaces>
|
|
<!-- Key types and contracts the executor needs. -->
|
|
|
|
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)
|
|
}
|
|
```
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Add 21 new TrafficClass constants and update AllClasses()</name>
|
|
<files>classify/types.go</files>
|
|
<read_first>
|
|
- classify/types.go (current constants and AllClasses implementation)
|
|
- synth/config.go lines 74-110 (frequency table comment showing expected class names)
|
|
</read_first>
|
|
<action>
|
|
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.
|
|
</action>
|
|
<verify>
|
|
<automated>cd /home/dev/workspace/yoloyolo && go build ./classify/...</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- 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
|
|
</acceptance_criteria>
|
|
<done>21 new TrafficClass constants defined, AllClasses() returns 32 classes (excluding LDAP/Kerberos/Syslog), package compiles</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Add 30 new port-matching rules to DefaultRules</name>
|
|
<files>classify/rules.go</files>
|
|
<read_first>
|
|
- classify/rules.go (current DefaultRules with 12 entries)
|
|
- classify/types.go (after Task 1 — verify new constants exist)
|
|
</read_first>
|
|
<action>
|
|
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.
|
|
</action>
|
|
<verify>
|
|
<automated>cd /home/dev/workspace/yoloyolo && go build ./classify/...</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- 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
|
|
</acceptance_criteria>
|
|
<done>DefaultRules contains 42 rules (12 existing + 30 new), all specific-port rules before catch-alls, package compiles</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
- `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
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- 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
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/10-classification-layer/10-01-SUMMARY.md`
|
|
</output>
|