Files
yoloyolo/.planning/milestones/v1.1-phases/07-custom-rules-and-print-config/07-CONTEXT.md
T
2026-03-26 22:06:36 +01:00

6.7 KiB

Phase 7: Custom Rules and Print-Config - Context

Gathered: 2026-03-26 Status: Ready for planning

## Phase Boundary

Add user-defined traffic classification rules in TOML ([[rules]] array-of-tables) that prepend before built-in rules, with automatic synthesis layer creation for new class names. Add --print-config flag that outputs the full effective config as commented TOML to stdout without starting a capture.

Requirements covered: RULE-01, RULE-02, RULE-03, CFG-06.

## Implementation Decisions

Custom Rule TOML Schema

  • D-01: Custom rules use TOML array-of-tables [[rules]] with three fields: port (uint16, optional — omit to match any port), protocol (string, required — "tcp", "udp", or "icmp"), and class (string, required — the TrafficClass name). Sound configuration for the class goes in a separate [sounds.<class>] block.
  • D-02: Port is optional. When omitted (or 0), the rule matches all traffic for the given protocol, mirroring the existing Rule.DstPort = 0 semantics in classify.DefaultRules.
  • D-03: Protocol is required. No implicit "match both TCP and UDP" behavior. User must write separate rules for each protocol.

Rule Ordering and Priority

  • D-04: User-defined rules are prepended before built-in DefaultRules (RULE-02). First-match-wins semantics are preserved. A user rule for port 443/tcp fires before the built-in HTTPS rule.
  • D-05: Rules within the TOML [[rules]] array maintain their file order. First rule in the file is first to match.

Class Name Collision Policy

  • D-06: User-defined class names that match built-in names (e.g., class = "HTTPS") are treated as overrides, not errors. The user's rule fires first (prepended), so traffic matching it gets classified under the same built-in class name via the user rule. Sound config in [sounds.HTTPS] still applies. This resolves the design question flagged in STATE.md.

Sound Assignment for Custom Classes

  • D-07: New class names that have no [sounds.<class>] entry automatically get sensible defaults: a frequency from an unused range and sine waveform. This satisfies RULE-03 (no silent gaps for user-defined classes).
  • D-08: (Claude's Discretion) The auto-assignment algorithm — how to pick frequencies for new classes that don't collide with built-in frequencies. Could use a hash of the class name, a sequential pool, or a deterministic spread across an unused frequency band.

Print-Config

  • D-09: --print-config outputs the full effective config (defaults merged with user overrides and custom rules) as commented TOML. Comments indicate which values are defaults vs overrides. This satisfies CFG-06.
  • D-10: Output goes to stdout (pipeable). User can do netsynth --print-config > template.toml to create a config template. The command exits without starting a capture.
  • D-11: If a config file is loaded (via auto-discovery or --config), show its source path in a header comment.

Config Package Extension

  • D-12: The existing config.Load() function must be extended to parse [[rules]] blocks in addition to [sounds.*]. The rawConfig struct gains a Rules []RawRule field.
  • D-13: config.Load() returns both the merged FreqConfig map and the user rules (as []classify.Rule). The caller prepends user rules before classify.DefaultRules.

Claude's Discretion

  • How to extend rawConfig struct and Load() return type (tuple, struct, or new function)
  • Auto-frequency assignment algorithm for custom classes without explicit sound config
  • Whether --print-config is a Cobra subcommand or a flag on the root command
  • How to format the commented TOML output (manual string building vs TOML encoder + post-processing)

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Classification System

  • classify/rules.goRule struct (Protocol, DstPort, Class), DefaultRules ordered slice, first-match-wins
  • classify/types.goTrafficClass string type, AllClasses(), ClassifiedPacket, WindowSnapshot
  • classify/classifier.goNewClassifier(rules []Rule) — accepts injected rule slice

Config System (Phase 6 output)

  • config/config.goLoad(), rawConfig, SoundOverride, merge(), validate(), parseWaveform()
  • config/config_test.go — Existing test patterns for TOML loading

Synthesis Pipeline

  • synth/config.goFreqConfig, ClassFreqConfigs, WaveformType, WaveformPresetHarmonics()
  • synth/bank.goNewBank(tau, cfgs map[TrafficClass]FreqConfig) — injection point for merged config
  • encode/mp3.goRunSynthesis(snapshots, outputPath, freqCfgs) — pipeline entry

CLI

  • cmd/netsynth/main.go — Cobra command, --config flag, run() dispatches to live/pcap modes

Prior Context

  • .planning/phases/06-config-package-and-sound-overrides/06-CONTEXT.md — Phase 6 decisions (TOML schema, merge semantics, validation)

No external specs — requirements fully captured in decisions above.

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • classify.Rule struct — Already has Protocol, DstPort, Class fields matching the TOML schema
  • classify.NewClassifier(rules []Rule) — Accepts any rule slice, so prepending user rules is straightforward
  • config.Load() — Existing TOML loading with BurntSushi/toml, validation, and merge pipeline
  • config.rawConfig — Top-level decode struct, needs Rules field added
  • config.parseWaveform() — Reusable for validating waveform strings in sound overrides
  • synth.NewBank(tau, cfgs) — Already accepts arbitrary config maps (Phase 5 injection seam)

Established Patterns

  • First-match-wins rule ordering in classify.DefaultRules
  • TOML strict decoding with Undecoded() for unknown key detection
  • Pointer fields (*float64, *string) for partial override semantics
  • Config loaded once at startup before capture (fail-fast)

Integration Points

  • config.Load() return value must expand to include user rules
  • cmd/netsynth/main.go:run() — Prepend user rules before passing to classify.NewClassifier()
  • config.merge() — Must handle new class names by creating FreqConfig entries with auto-assigned frequencies
  • --print-config — New flag or subcommand in Cobra root command

</code_context>

## Specific Ideas
  • Print-config should show commented TOML with # default / # override annotations and source path header
  • Output to stdout so users can pipe to a file as a template
## Deferred Ideas

None — discussion stayed within phase scope.


Phase: 07-custom-rules-and-print-config Context gathered: 2026-03-26