diff --git a/core/pkg/config/config.go b/core/pkg/config/config.go index 6a1007c..9996f7e 100644 --- a/core/pkg/config/config.go +++ b/core/pkg/config/config.go @@ -15,6 +15,21 @@ type Config struct { Security SecurityConfig `yaml:"security"` Logging LoggingConfig `yaml:"logging"` HTTPGateway HTTPGatewayConfig `yaml:"http_gateway"` + + // SNIRouter is the stealth TURN-over-443 SNI router toggle (feat-124). + // Phase 4 config generation always emits this block into node.yaml, so + // the field MUST exist here: node.yaml is decoded with KnownFields(true) + // and an unknown top-level key fails the whole parse and crash-loops + // orama-node at boot (same failure mode as the v0.122.42 + // secrets_encryption_key incident). + SNIRouter SNIRouterConfig `yaml:"sni_router"` +} + +// SNIRouterConfig is the top-level stealth SNI router block in node.yaml +// (feat-124). Default-off; when enabled the node runs orama-sni-router on +// :443 and Caddy moves to :8443. +type SNIRouterConfig struct { + Enabled bool `yaml:"enabled"` } // ValidationError represents a single validation error with context. diff --git a/core/pkg/config/decode_test.go b/core/pkg/config/decode_test.go index 37f27cc..018b089 100644 --- a/core/pkg/config/decode_test.go +++ b/core/pkg/config/decode_test.go @@ -234,3 +234,24 @@ http_gateway: t.Errorf("SecretsEncryptionKey = %q, want %q", cfg.HTTPGateway.SecretsEncryptionKey, want) } } + +// TestDecodeStrict_sniRouterBlock guards against a recurrence of the +// v0.122.42-class boot crash for the feat-124 stealth SNI router: Phase 4 +// always emits a top-level `sni_router:` block into node.yaml, so the root +// Config struct must carry a matching field or KnownFields(true) rejects +// the whole file and orama-node crash-loops. +func TestDecodeStrict_sniRouterBlock(t *testing.T) { + yamlInput := ` +node: + id: "test-node" +sni_router: + enabled: true +` + var cfg Config + if err := DecodeStrict(strings.NewReader(yamlInput), &cfg); err != nil { + t.Fatalf("node.yaml with sni_router block must parse (feat-124): %v", err) + } + if !cfg.SNIRouter.Enabled { + t.Errorf("SNIRouter.Enabled = false, want true") + } +}