From fe372c8dc870e485838f67f5670002835b15c5f9 Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Thu, 26 Mar 2026 21:27:29 +0100 Subject: [PATCH] docs(07): capture phase context --- .../07-CONTEXT.md | 123 ++++++++++++++++++ .../07-DISCUSSION-LOG.md | 73 +++++++++++ 2 files changed, 196 insertions(+) create mode 100644 .planning/phases/07-custom-rules-and-print-config/07-CONTEXT.md create mode 100644 .planning/phases/07-custom-rules-and-print-config/07-DISCUSSION-LOG.md diff --git a/.planning/phases/07-custom-rules-and-print-config/07-CONTEXT.md b/.planning/phases/07-custom-rules-and-print-config/07-CONTEXT.md new file mode 100644 index 0000000..eb99bdf --- /dev/null +++ b/.planning/phases/07-custom-rules-and-print-config/07-CONTEXT.md @@ -0,0 +1,123 @@ +# 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.]` 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.]` 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 References + +**Downstream agents MUST read these before planning or implementing.** + +### Classification System +- `classify/rules.go` — `Rule` struct (Protocol, DstPort, Class), `DefaultRules` ordered slice, first-match-wins +- `classify/types.go` — `TrafficClass` string type, `AllClasses()`, `ClassifiedPacket`, `WindowSnapshot` +- `classify/classifier.go` — `NewClassifier(rules []Rule)` — accepts injected rule slice + +### Config System (Phase 6 output) +- `config/config.go` — `Load()`, `rawConfig`, `SoundOverride`, `merge()`, `validate()`, `parseWaveform()` +- `config/config_test.go` — Existing test patterns for TOML loading + +### Synthesis Pipeline +- `synth/config.go` — `FreqConfig`, `ClassFreqConfigs`, `WaveformType`, `WaveformPresetHarmonics()` +- `synth/bank.go` — `NewBank(tau, cfgs map[TrafficClass]FreqConfig)` — injection point for merged config +- `encode/mp3.go` — `RunSynthesis(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. + + + + +## 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 + + + + +## 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* diff --git a/.planning/phases/07-custom-rules-and-print-config/07-DISCUSSION-LOG.md b/.planning/phases/07-custom-rules-and-print-config/07-DISCUSSION-LOG.md new file mode 100644 index 0000000..1141842 --- /dev/null +++ b/.planning/phases/07-custom-rules-and-print-config/07-DISCUSSION-LOG.md @@ -0,0 +1,73 @@ +# Phase 7: Custom Rules and Print-Config - Discussion Log + +> **Audit trail only.** Do not use as input to planning, research, or execution agents. +> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered. + +**Date:** 2026-03-26 +**Phase:** 07-custom-rules-and-print-config +**Areas discussed:** Custom rule TOML schema, Class name collision policy, Print-config output format, Sound assignment for custom classes + +--- + +## Custom Rule TOML Schema + +| Option | Description | Selected | +|--------|-------------|----------| +| Minimal: port + protocol + class | Matches existing Rule struct. Sound config in separate [sounds.X]. | ✓ | +| Inline sound: port + protocol + class + frequency/waveform | All-in-one rule block, mixes classification and sound concerns. | | +| Rich matching: port ranges, src/dst, regex | More expressive but significantly more complex. | | + +**User's choice:** Minimal — port + protocol + class +**Notes:** Protocol is required. Port is optional (omit to match any port for the protocol). + +--- + +## Class Name Collision Policy + +| Option | Description | Selected | +|--------|-------------|----------| +| Treat as override | User's rule fires first (prepended), same class name. Simplest model. | ✓ | +| Reject with error | Startup error if user rule uses built-in class name. | | +| Namespace: prefix user classes | User classes get "user-" prefix. Adds naming complexity. | | + +**User's choice:** Treat as override +**Notes:** Resolves the design question flagged in STATE.md since Phase 5 research. + +--- + +## Print-Config Output Format + +| Option | Description | Selected | +|--------|-------------|----------| +| Commented TOML | Valid TOML with comments showing default vs override. Pipeable to file. | ✓ | +| Plain TOML | Clean but doesn't show what's default vs overridden. | | +| Human-readable table | Formatted table, not valid TOML. | | + +**User's choice:** Commented TOML to stdout +**Notes:** Output to stdout so `netsynth --print-config > template.toml` works. Shows source path in header comment. + +--- + +## Sound Assignment for Custom Classes + +| Option | Description | Selected | +|--------|-------------|----------| +| Auto-assign sensible defaults | Pick unused frequency + sine waveform. No silence. | ✓ | +| Require explicit [sounds.X] | Error if no matching sound config. More friction. | | +| Single fallback tone | All custom classes share one tone. Defeats distinct sounds purpose. | | + +**User's choice:** Auto-assign sensible defaults +**Notes:** Satisfies RULE-03 (no silent gaps). Algorithm left to Claude's discretion. + +--- + +## Claude's Discretion + +- Auto-frequency assignment algorithm +- --print-config as flag vs subcommand +- Commented TOML formatting approach +- config.Load() return type extension + +## Deferred Ideas + +None — discussion stayed within phase scope.