refactor(config): externalize rpcAccessProducts to config/rpc_products.yaml #7
Reference in New Issue
Block a user
Delete Branch "devin/1776539646-refactor-config-externalize"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
PR #7 of the 11-PR completion sequence. Moves the Chain 138 RPC access product catalog (core-rpc / alltra-rpc / thirdweb-rpc, each with VMID + HTTP/WS URL + tier + billing model + use cases + management features) out of
api/rest/auth.goand intobackend/config/rpc_products.yamlso operators can retune the catalog without a Go rebuild and internal192.168.11.xCIDR endpoints stop being baked into the binary.New files
backend/config/rpc_products.yaml— source of truth (schema documented in-file).backend/api/rest/rpc_products_config.go— lazy loader + validation + compiled-in fallback defaults.backend/api/rest/rpc_products_config_test.go— unit tests.Loader behaviour
Path resolution (first hit wins):
$RPC_PRODUCTS_PATH(absolute or relative to cwd)$EXPLORER_BACKEND_DIR/config/rpc_products.yaml<cwd>/backend/config/rpc_products.yaml<cwd>/config/rpc_products.yamldefaultRPCAccessProductsfallback (logsWARNING)Validation on load:
slug,http_url,WARNING+ fallback to defaults, never a silent empty catalog.Call-site changes
api/rest/auth.go:var rpcAccessProducts []accessProduct(50-line literal) →func rpcAccessProducts() []accessProductthat forwards to the lazy loader./api/v1/access/productshandlerfindAccessProduct(slug)helperZero behavioural changes — the JSON shape of
/api/v1/access/productsis byte-identical.Verification
go build ./...— clean.go vet ./...— clean.go test ./api/rest/...— PASS (new tests + all existing ones).go mod tidy— promotedgopkg.in/yaml.v3from indirect to direct.Completion criterion advanced
The Chain 138 RPC access product catalog (core-rpc / alltra-rpc / thirdweb-rpc, each with VMID + HTTP/WS URL + tier + billing model + use cases + management features) used to be a hardcoded 50-line Go literal in api/rest/auth.go. The review flagged this as the biggest source of 'magic constants in source' in the backend: changing a partner URL, a VMID, or a billing model required a Go recompile, and the internal 192.168.11.x CIDR endpoints were baked into the binary. This PR moves the catalog to backend/config/rpc_products.yaml and adds a lazy loader so every call site reads from the YAML on first use. New files: backend/config/rpc_products.yaml source of truth backend/api/rest/rpc_products_config.go loader + fallback defaults backend/api/rest/rpc_products_config_test.go unit tests Loader path-resolution order (first hit wins): 1. $RPC_PRODUCTS_PATH (absolute or cwd-relative) 2. $EXPLORER_BACKEND_DIR/config/rpc_products.yaml 3. <cwd>/backend/config/rpc_products.yaml 4. <cwd>/config/rpc_products.yaml 5. compiled-in defaultRPCAccessProducts fallback (logs a WARNING) Validation on load: - every product must have a non-empty slug, - every product must have a non-empty http_url, - slugs must be unique across the catalog. A malformed YAML causes a WARNING + fallback to defaults, never a silent empty product list. Call-site changes in auth.go: - 'var rpcAccessProducts []accessProduct' (literal) -> func rpcAccessProducts() []accessProduct (forwards to the lazy loader). - Both existing consumers (/api/v1/access/products handler at line ~369 and findAccessProduct() at line ~627) now call the function. Zero other behavioural changes; the JSON shape of the response is byte-identical. Tests added: - TestLoadRPCAccessProductsFromRepoDefault: confirms the shipped YAML loads, produces >=3 products, and contains the 3 expected slugs with non-empty http_url. - TestLoadRPCAccessProductsRejectsDuplicateSlug. - TestLoadRPCAccessProductsRejectsMissingHTTPURL. Verification: go build ./... clean go vet ./... clean go test ./api/rest/ PASS (new + existing) go mod tidy pulled yaml.v3 from indirect to direct Advances completion criterion 7 (no magic constants): 'Chain 138 access products / VMIDs / provider URLs live in a YAML that operators can change without a rebuild; internal CIDRs are no longer required to be present in source.'