Files
yoloyolo/.planning/research/STACK.md
T

216 lines
8.1 KiB
Markdown
Raw Normal View History

2026-03-26 16:54:31 +01:00
# Technology Stack
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
**Project:** NetSynth v1.1 — Custom Sound Mappings
**Researched:** 2026-03-26
**Scope:** Additions/changes only. Existing stack (gopacket, go-pcap, go-lame, cobra) is validated and unchanged.
2026-03-24 22:36:28 +01:00
---
2026-03-26 16:54:31 +01:00
## Existing Stack (Do Not Re-research)
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
| Technology | Version | Status |
|------------|---------|--------|
| `github.com/gopacket/gopacket` | v1.5.0 | Validated in v1.0, unchanged |
| `github.com/packetcap/go-pcap` | v0.0.0-20251215 | Validated in v1.0, unchanged |
| `github.com/sjzar/go-lame` | v0.0.9 | Validated in v1.0, unchanged |
| `github.com/spf13/cobra` | v1.10.2 | Validated in v1.0, unchanged |
| Hand-rolled sine oscillator + EMA | — | Validated in v1.0, extend in place |
| Ordered `[]Rule` classifier | — | Validated in v1.0, extend in place |
2026-03-24 22:36:28 +01:00
---
2026-03-26 16:54:31 +01:00
## New Dependencies for v1.1
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
### TOML Config Parsing
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
| Technology | Version | Purpose | Why |
|------------|---------|---------|-----|
| `github.com/BurntSushi/toml` | v1.6.0 | Parse `netsynth.toml` config files | Single-function `toml.Decode()` into a struct. The `MetaData.Undecoded()` method catches unknown keys in user configs — surfacing typos like `frequncy` rather than silently ignoring them. This is the right behavior for a config file tool. v1.6.0 released December 2025, Go 1.18+ required. Zero indirect dependencies. |
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
**Version confirmed:** v1.6.0, December 18, 2025, via pkg.go.dev and GitHub releases page.
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
**Why not `pelletier/go-toml v2`:** go-toml v2.3.0 (March 2026) is faster but the performance difference is irrelevant — config is read once at startup. go-toml v2's `Strict` mode can detect unknown keys but requires more setup than BurntSushi's `MetaData.Undecoded()`. BurntSushi's API is simpler for this use case and has clearer error message patterns for user-facing config mistakes.
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
### Config Auto-Discovery
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
No new dependency. Use Go stdlib only:
2026-03-24 22:36:28 +01:00
```go
2026-03-26 16:54:31 +01:00
// Probe order: --config flag > ./netsynth.toml > ~/.config/netsynth/config.toml
func findConfigPath(flagValue string) (string, bool) {
if flagValue != "" {
return flagValue, true
2026-03-24 22:36:28 +01:00
}
2026-03-26 16:54:31 +01:00
if _, err := os.Stat("./netsynth.toml"); err == nil {
return "./netsynth.toml", true
}
if dir, err := os.UserConfigDir(); err == nil {
p := filepath.Join(dir, "netsynth", "config.toml")
if _, err := os.Stat(p); err == nil {
return p, true
}
}
return "", false
2026-03-24 22:36:28 +01:00
}
```
2026-03-26 16:54:31 +01:00
`os.UserConfigDir()` returns `$XDG_CONFIG_HOME` if set, else `$HOME/.config` on Linux/macOS — confirmed against Go stdlib docs. No third-party XDG library needed.
### Additional Waveform Types
No new dependency. Extend the existing `synth.Oscillator` in place.
Square, sawtooth, and triangle are pure math — each is ~3 lines. The existing oscillator uses a phase accumulator (0.01.0 range), which is the right representation for all four waveforms:
```go
// Waveform enum addition to synth package
type Waveform int
const (
WaveformSine Waveform = iota
WaveformSquare
WaveformSawtooth
WaveformTriangle
)
// Per-sample generation (replaces math.Sin call in Advance())
func sample(phase float64, w Waveform) float64 {
switch w {
case WaveformSquare:
if phase < 0.5 { return 1.0 }
return -1.0
case WaveformSawtooth:
return 2*phase - 1.0
case WaveformTriangle:
if phase < 0.5 { return 4*phase - 1.0 }
return 3.0 - 4*phase
default: // WaveformSine
return math.Sin(2 * math.Pi * phase)
}
}
```
The `Oscillator` struct gains a `Waveform` field; `Advance()` dispatches to `sample()`. Harmonics still work the same way — each harmonic's phase is `phase * ratio`, which maps correctly for all waveform types.
---
## Installation Delta
```bash
# Add only this new dependency
go get github.com/BurntSushi/toml@v1.6.0
```
No changes to build flags. `CGO_ENABLED=1` still required for go-lame.
---
## Integration Points
### Where Config Feeds Existing Code
The TOML config needs to override two existing data structures:
1. **`synth.ClassFreqConfigs`** (map in `synth/config.go`) — user can override `BaseHz` and add a `Waveform` field per class
2. **`classify.DefaultRules`** (slice in `classify/rules.go`) — user can prepend custom rules before the defaults
The config loader should apply overrides at startup before any other initialization. The cleanest integration is:
```
cmd/netsynth/main.go
-> config.Load(path) // returns *AppConfig
-> classify.MergeRules(cfg) // prepend user rules to DefaultRules
-> synth.ApplyOverrides(cfg) // patch ClassFreqConfigs entries
```
Both `classify.DefaultRules` and `synth.ClassFreqConfigs` are currently package-level vars — they can be replaced or cloned at startup without changing the downstream pipeline.
### TOML Struct Shape
The config schema maps naturally to the existing types:
```toml
# netsynth.toml
[[rules]]
protocol = "tcp"
dst_port = 8443
class = "my-https-alt"
[sounds.my-https-alt]
frequency = 195.0
waveform = "square"
[sounds.ICMP]
frequency = 80.0 # override built-in
waveform = "triangle"
```
```go
type AppConfig struct {
Rules []RuleConfig `toml:"rules"`
Sounds map[string]SoundConfig `toml:"sounds"`
}
type RuleConfig struct {
Protocol string `toml:"protocol"`
DstPort uint16 `toml:"dst_port"`
Class string `toml:"class"`
}
type SoundConfig struct {
Frequency float64 `toml:"frequency"`
Waveform string `toml:"waveform"` // "sine"|"square"|"sawtooth"|"triangle"
}
```
Use `toml.Decode()` and check `meta.Undecoded()` to warn on unknown keys.
---
## What NOT to Add
| Avoid | Why | What to Do Instead |
|-------|-----|-------------------|
| `adrg/xdg` or any XDG library | `os.UserConfigDir()` in stdlib already handles `$XDG_CONFIG_HOME` on Linux — confirmed | Use `os.UserConfigDir()` directly |
| `pelletier/go-toml v2` | No advantage over BurntSushi for a single-file startup read; `MetaData.Undecoded()` in BurntSushi is more ergonomic for typo detection | `github.com/BurntSushi/toml` |
| `spf13/viper` | Massive dependency (brings in 20+ transitive deps) for a use case that is one TOML file — Viper adds remote config, env var binding, hot reload, none of which are needed | `BurntSushi/toml` + manual flag override |
| Any waveform/audio library | Square/sawtooth/triangle are 3 lines of math each; no library adds value | Extend `synth.Oscillator` in place |
| `gopkg.in/yaml.v3` or JSON config | TOML is explicitly specified for this milestone and is the right format for user-editable config files (comments supported, less noisy than JSON) | TOML only |
2026-03-24 22:36:28 +01:00
---
## Version Compatibility
2026-03-26 16:54:31 +01:00
| Package | Version | Compatible With | Notes |
|---------|---------|-----------------|-------|
| `BurntSushi/toml` | v1.6.0 | Go 1.18+ | No issues with Go 1.24 |
| `os.UserConfigDir()` | stdlib | Go 1.13+ | Returns `$XDG_CONFIG_HOME` or `$HOME/.config` on Linux |
2026-03-24 22:36:28 +01:00
---
2026-03-26 16:54:31 +01:00
## Confidence Assessment
2026-03-24 22:36:28 +01:00
2026-03-26 16:54:31 +01:00
| Area | Confidence | Source |
|------|------------|--------|
| BurntSushi/toml v1.6.0 version | HIGH | pkg.go.dev confirmed, GitHub releases confirmed |
| `os.UserConfigDir()` XDG behavior | HIGH | Official Go stdlib docs at pkg.go.dev/os |
| Waveform math (no library needed) | HIGH | Trivial math, Dylan Meeus Go audio blog confirms the same approach |
| go-toml v2.3.0 version | HIGH | pkg.go.dev confirmed |
| Recommendation of BurntSushi over go-toml v2 | MEDIUM | Based on API ergonomics for the specific `Undecoded()` use case; both would work |
2026-03-24 22:36:28 +01:00
---
## Sources
2026-03-26 16:54:31 +01:00
- `pkg.go.dev/github.com/BurntSushi/toml` — v1.6.0 confirmed, December 18, 2025
- `github.com/BurntSushi/toml/releases` — v1.6.0 release notes, TOML 1.1 enabled by default
- `pkg.go.dev/github.com/pelletier/go-toml/v2` — v2.3.0 confirmed, March 24, 2026
- `pkg.go.dev/os#UserConfigDir` — XDG_CONFIG_HOME behavior on Linux confirmed via official Go docs
- `dylanmeeus.github.io/posts/audio-from-scratch-pt8/` — Go waveform synthesis from scratch, confirms no library needed
- `github.com/golang/go/issues/76320` — UserConfigDir XDG_CONFIG_HOME discussion (Nov 2025), confirms existing stdlib support on Linux
2026-03-24 22:36:28 +01:00
---
2026-03-26 16:54:31 +01:00
*Stack research for: NetSynth v1.1 — Custom Sound Mappings milestone*
*Researched: 2026-03-26*