feat: add security, rate limit and data source coverage - #3
Merged
Merged
Conversation
luccastera
approved these changes
Sep 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings the provider from one resource to the full endpoint surface: security, rate limits, and lookups for endpoints created elsewhere.
What is new
quicknode_endpoint_ip,_domain_mask,_referrerquicknode_endpoint_jwtquicknode_endpoint_tokenquicknode_endpoint_request_filterquicknode_endpoint_rate_limitsquicknode_endpoint_method_rate_limitdata.quicknode_endpoint,data.quicknode_endpointsquicknode_endpointgainssecurity_options— seven settable toggles plus two the Admin API reports but will not accept on write — andip_custom_headerfor endpoints behind a proxy.Decisions worth reviewing
Separate resources rather than inline sets. An entry added outside Terraform is left alone, and two modules can each contribute one. Inline lists would make the endpoint resource delete anything it did not create, which is the problem
aws_security_groupinline rules are known for.Allowlist entries import by value, not by id.
123456/203.0.113.7is what an operator already knows; the entry id only exists in the API. Import resolves the value against the endpoint's entries and refuses rather than guesses when more than one matches. Request filters and method rate limiters have no natural name so they keep the id, and tokens import by id on purpose, to keep the credential out of shell history.Adding an entry while its toggle is off warns rather than errors. The API accepts it, and building an allowlist before enabling enforcement is the safe order for an endpoint already serving traffic. The check runs at apply rather than plan: a plan-time read would reject a config that enables the toggle and adds the entry in the same run.
Unmanaged values are omitted from write bodies, never sent as zero. Security toggles are read as booleans and written as the strings
enabledanddisabled, so a strayfalsewould read as "turn this off". Rate limit buckets have the same hazard. Both write paths take pointers and leave anything unmanaged out of the request;TestSetSecurityOptionsSendsStringsandTestSetRateLimitsOmitsUnmanagedBucketsassert it.Dropping a rate limit bucket deletes its override. The patch route has no way to say "return this bucket to the plan default", so removing
rpmfrom the configuration issues a delete against the override id rather than leaving it in place.intervalreplaces a method rate limiter. The update route takes methods, rate and status but no interval.Method rate limits keep the casing the configuration wrote. That route lowercases the method names it stores, so reading them back verbatim leaves a diff no apply can settle.
Readcompares the returned methods to prior state case-insensitively and keeps the configured spelling; a method the prior state does not hold is kept exactly as the API returned it, so a real change is still detected. The request filter route does not normalise, and needs none of this.tokensstays onquicknode_endpoint. It is purely computed, so it cannot fightquicknode_endpoint_tokenover ownership, and removing it would break the schema for no gain.Endpoint URLs
http_urlandwss_urlare renamedsafe_http_urlandsafe_wss_url, and they now carry the literalTOKENwhere the credential belongs instead of having it cut out:The old form deleted the token segment, which mangled every chain that appends a suffix after it —
.../abc123/evmbecame.../evm, a URL that does not work and cannot be repaired by appending a token. Substituting into the placeholder reproduces a working address on any chain:http_url_with_tokenandwss_url_with_tokenare unchanged and stay sensitive.This branch also fixes a leak it introduced:
data.quicknode_endpointsmapped the list route'shttp_urlstraight through, and that route returns the credentialed URL. It was exposed as a non-sensitive attribute documented as safe to log. It is redacted on ingest now, so the list data source carries only the placeholder form — the credentialed URLs are available from a full endpoint read.Testing
The acceptance tests have now run against the live Admin API. All eight pass, together with the unit tests:
make lintreports no issues.They found four issues the unit tests could not have caught:
ethereum-sepolia. The plan-time validator rejected the configuration and named the valid slugs, which is the validator working as intended — the test was wrongipCustomHeaderterraform applycreating an endpoint failed to decode the responsedatais an array with one{option, status}per toggle changedeth_getLogscame backeth_getlogsand left a permanent diffThe create failure is worth noting on its own: the endpoint was created and then the response failed to decode, so the provider returned an error and Terraform recorded nothing. That leaves a real endpoint nobody is tracking.
CheckDestroycannot catch it — the resource never reached state — which is exactly why the decode path matters.CheckDestroyis new here. Terraform treats a destroy as successful as soon as the provider'sDeletereturns no error, so a delete the API quietly declined would have passed and left a billable endpoint behind. Every test case now asks the API whether the endpoints it created are really gone.Acceptance tests still run only on
workflow_dispatchand still need aQUICKNODE_API_KEYsecret, which the repository does not have yet; the job skips until it does.Spec patches
api/admin/patches.jsongrows from 14 to 29. Most add item types to arrays (the security lists, the request filter and method rate limit method arrays, and three list-route filter parameters) so the generated client gets typed slices. Both request filter write routes answer204with no body, which has separate handling. The last two patches are the create-response and security-options shapes above.