feat(EVO-1738): stateless POST /custom-tools/test (test-before-save) - #22
Merged
gomessguii merged 2 commits intoJul 24, 2026
Merged
Conversation
The wizard needs to test a tool's HTTP request BEFORE it is saved, but the only test
endpoint was GET /:id/test (requires a persisted tool). Add a stateless POST
/custom-tools/test accepting {method, endpoint, headers, body_params} and returning the
same TestResult, reusing the SSRF-hardened runToolTest (scheme allowlist, public-IP-only
+ DNS-rebinding revalidation, redirects off, 1 MiB/15s caps, header allowlist).
- service: TestPayload(ctx, method, endpoint, headers, bodyParams) — validates the method
then delegates to runToolTest. Same defenses as Test, no saved tool required.
- handler: TestPayload binds the payload (ValidationErrorResponse on bad body); route
POST /custom-tools/test, gated ai_custom_tools:read (parity with GET /:id/test).
- test: TestPayload runs against an httptest server (success 200) and fails fast on an
unsupported method. go build/vet/test ./pkg/custom_tool/... green.
Backend half of the EVO-1738 wizard "Test" button; the frontend wires it. File is
pre-existing CRLF on develop, kept out of gofmt to avoid a line-ending-only diff.
There was a problem hiding this comment.
Sorry @pastoriniMatheus, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
…ms, 400 on bad method
Code-review follow-ups on the stateless POST /custom-tools/test endpoint.
- Permission gate read -> create. Unlike GET /:id/test (which only replays a
tool someone with create rights already authored), this endpoint takes
method/endpoint/headers straight from the request body, so gating it on
"read" handed every read-only user an arbitrary server-side HTTP fetcher.
- resolveToolURL applies the tool's path placeholders and query params before
the request goes out. Both test paths dropped them, so "/users/{user_id}"
was requested literally and query params never reached the wire -- the
wizard could report "Request OK -- HTTP 200" for a request that carried
none of the user's configuration. Path values are percent-escaped and
validateEndpoint still runs on the RESOLVED url, so the SSRF gate holds.
- normalizeToolMethod shared by Test and TestPayload so the allowlists cannot
drift, returning a 400 ApiError: an unsupported method is caller input, and
a plain fmt.Errorf mapped to 500 INTERNAL_ERROR.
- TestPayload takes model.CustomToolTestPayloadRequest instead of a widening
positional list.
Tests: path/query application, placeholder-cannot-inject-a-host (plus the
literal link-local case still hitting the public-IP gate), 400 mapping, and a
first test file for the handler package (binding, envelope, error mapping).
gomessguii
force-pushed
the
feat/EVO-1738-custom-tools-test-payload-endpoint
branch
from
July 24, 2026 22:16
3cad1ce to
46c8fb6
Compare
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.
EVO-1738 (core) — endpoint stateless de teste de ferramenta NÃO salva
Contexto
O wizard de Custom Tools só permitia testar uma ferramenta depois de salva (
GET /custom-tools/{id}/test). O requisito da issue é test-before-save: testar a requisição com a config ainda em rascunho no wizard, antes de persistir.Mudança
Novo endpoint stateless
POST /custom-tools/test, que executa a requisição de uma ferramenta ainda não persistida:service.TestPayload(ctx, method, endpoint, headers, bodyParams)— valida o método HTTP e reusa orunToolTestjá existente (o mesmo caminho SSRF-hardened usado no teste de ferramenta salva). Nada é gravado.handler.TestPayload— bind de{method, endpoint, headers, body_params}; rotaPOST /custom-tools/testprotegida porai_custom_tools:read(paridade com o gate doGET /{id}/test).Testes
TestTestPayload_UnsavedTool_RunsAndValidatesMethod— roda uma ferramenta não salva, valida o método e retorna o resultado do teste.go build -modfile=go.community.mod ./...limpo (build community, sem SDK enterprise).POST /custom-tools/testcom{method:GET, endpoint:jsonplaceholder/todos/1}→ HTTP 200,test_result.success=true,status_code=200, comheaders,bodyeresponse_timereais.Relacionado
Frontend par: frontend #269.