diff --git a/backend/secretapi/README.md b/backend/secretapi/README.md index 5aa1614..75b362c 100644 --- a/backend/secretapi/README.md +++ b/backend/secretapi/README.md @@ -21,6 +21,7 @@ go test ./... ## Environment Template Copy `.env.example` in this folder and set contract/runtime values before deploy. +`secretapi` validates config at startup and fails closed if strict chain verification is enabled without RPC. ## Endpoint Surface diff --git a/backend/secretapi/config.go b/backend/secretapi/config.go index 47524c2..c6c601c 100644 --- a/backend/secretapi/config.go +++ b/backend/secretapi/config.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "os" "strconv" "strings" @@ -65,6 +66,16 @@ func loadConfig() Config { } } +func (c Config) Validate() error { + if c.ChainID <= 0 { + return fmt.Errorf("SECRET_API_CHAIN_ID must be positive") + } + if c.RequireOnchainTxVerify && strings.TrimSpace(c.ChainRPCURL) == "" { + return fmt.Errorf("SECRET_API_REQUIRE_ONCHAIN_TX_VERIFICATION requires SECRET_API_CHAIN_RPC_URL") + } + return nil +} + func env(key, fallback string) string { if v := strings.TrimSpace(os.Getenv(key)); v != "" { return v diff --git a/backend/secretapi/config_test.go b/backend/secretapi/config_test.go new file mode 100644 index 0000000..92677f2 --- /dev/null +++ b/backend/secretapi/config_test.go @@ -0,0 +1,33 @@ +package main + +import "testing" + +func TestConfigValidateAllowsDefaultLocalConfig(t *testing.T) { + t.Parallel() + cfg := loadConfig() + cfg.ChainID = 84532 + cfg.RequireOnchainTxVerify = false + cfg.ChainRPCURL = "" + if err := cfg.Validate(); err != nil { + t.Fatalf("expected default-like config valid, got %v", err) + } +} + +func TestConfigValidateRejectsStrictVerificationWithoutRPC(t *testing.T) { + t.Parallel() + cfg := loadConfig() + cfg.RequireOnchainTxVerify = true + cfg.ChainRPCURL = "" + if err := cfg.Validate(); err == nil { + t.Fatalf("expected strict verification config validation failure") + } +} + +func TestConfigValidateRejectsNonPositiveChainID(t *testing.T) { + t.Parallel() + cfg := loadConfig() + cfg.ChainID = 0 + if err := cfg.Validate(); err == nil { + t.Fatalf("expected chain id validation failure") + } +} diff --git a/backend/secretapi/main.go b/backend/secretapi/main.go index caffce8..7941b48 100644 --- a/backend/secretapi/main.go +++ b/backend/secretapi/main.go @@ -7,6 +7,9 @@ import ( func main() { cfg := loadConfig() + if err := cfg.Validate(); err != nil { + log.Fatalf("invalid config: %v", err) + } logConfig(cfg) st, err := openStore(cfg.DBPath)