fix(service): wrap schema validation sentinel via Err so errors.Is returns 422#28
Conversation
….Is works When a client POSTs (or PATCHes) a provider configuration whose Config does not satisfy the provider's JSON Schema, the create/update command returned a pkg.ValidationError that carried the FLK-0293 sentinel only as a string in Code. The handler's switch uses errors.Is on the sentinel; since ValidationError.Is matches on Code-and-type and Unwrap returned nil, the chain was empty and the request fell through to the default 500 branch. Set the Err field to constant.ErrProviderConfigInvalidSchema so the Unwrap chain reaches the sentinel and the handler maps the failure to HTTP 422 with code FLK-0293 as documented.
…g to 422 Adds command-layer and handler-layer tests that lock in the FLK-0293 mapping for invalid provider-configuration payloads: - create_provider_config_test.go and update_provider_config_test.go drive the create/update commands with a config that violates the provider JSON Schema and assert that the returned error satisfies both errors.Is(err, constant.ErrProviderConfigInvalidSchema) and errors.As to pkg.ValidationError with the FLK-0293 code. - handler_test.go covers POST and PATCH /v1/provider-configurations to confirm the HTTP response is 422 Unprocessable Entity with code FLK-0293 whenever the command service surfaces the wrapped sentinel. Without the Err-field wrapping introduced in the previous commit these tests fail (the command-layer assertions report "Should be true" on errors.Is and the handler returns 500), guarding against any regression that strips Err in the future.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (5)
WalkthroughThis PR adds error-chain semantics for provider configuration schema validation failures. Create and update commands now wrap validation errors with ChangesProvider Config Schema Validation Error Chain
Comment |
📊 Unit Test Coverage Report:
|
| Metric | Value |
|---|---|
| Overall Coverage | 41.3% |
| Threshold | 85% |
Coverage by Package
| Package | Coverage |
|---|---|
github.com/LerianStudio/flowker/api |
100.0% |
github.com/LerianStudio/flowker/internal/adapters/http/in/audit |
0.0% |
github.com/LerianStudio/flowker/internal/adapters/http/in/catalog |
60.9% |
github.com/LerianStudio/flowker/internal/adapters/http/in/dashboard |
91.5% |
github.com/LerianStudio/flowker/internal/adapters/http/in/execution |
81.0% |
github.com/LerianStudio/flowker/internal/adapters/http/in/executor_configuration |
72.0% |
github.com/LerianStudio/flowker/internal/adapters/http/in/health |
100.0% |
github.com/LerianStudio/flowker/internal/adapters/http/in/middleware/testutil |
0.0% |
github.com/LerianStudio/flowker/internal/adapters/http/in/middleware |
44.4% |
github.com/LerianStudio/flowker/internal/adapters/http/in/provider_configuration |
33.4% |
github.com/LerianStudio/flowker/internal/adapters/http/in/readyz |
81.3% |
github.com/LerianStudio/flowker/internal/adapters/http/in/webhook |
87.5% |
github.com/LerianStudio/flowker/internal/adapters/http/in/workflow |
69.7% |
github.com/LerianStudio/flowker/internal/adapters/http/in |
33.3% |
github.com/LerianStudio/flowker/internal/adapters/mongodb/dashboard |
43.0% |
github.com/LerianStudio/flowker/internal/adapters/mongodb/execution |
64.8% |
github.com/LerianStudio/flowker/internal/adapters/mongodb/executor_configuration |
36.6% |
github.com/LerianStudio/flowker/internal/adapters/mongodb/provider_configuration |
45.8% |
github.com/LerianStudio/flowker/internal/adapters/mongodb/workflow |
69.2% |
github.com/LerianStudio/flowker/internal/adapters/postgresql/audit |
42.2% |
github.com/LerianStudio/flowker/internal/bootstrap |
39.8% |
github.com/LerianStudio/flowker/internal/services/command |
29.9% |
github.com/LerianStudio/flowker/internal/services/query |
11.2% |
github.com/LerianStudio/flowker/internal/services |
3.2% |
github.com/LerianStudio/flowker/internal/testutil |
63.6% |
github.com/LerianStudio/flowker/pkg/circuitbreaker |
97.6% |
github.com/LerianStudio/flowker/pkg/clock |
0.0% |
github.com/LerianStudio/flowker/pkg/condition |
87.9% |
github.com/LerianStudio/flowker/pkg/contextutil |
0.0% |
github.com/LerianStudio/flowker/pkg/executor/base |
20.0% |
github.com/LerianStudio/flowker/pkg/executor |
39.5% |
github.com/LerianStudio/flowker/pkg/executors/http/auth |
59.5% |
github.com/LerianStudio/flowker/pkg/executors/http |
0.0% |
github.com/LerianStudio/flowker/pkg/executors/midaz |
76.4% |
github.com/LerianStudio/flowker/pkg/executors/s3 |
0.0% |
github.com/LerianStudio/flowker/pkg/executors/tracer |
72.2% |
github.com/LerianStudio/flowker/pkg/executors |
57.1% |
github.com/LerianStudio/flowker/pkg/model |
57.7% |
github.com/LerianStudio/flowker/pkg/net/http |
91.3% |
github.com/LerianStudio/flowker/pkg/pagination |
0.0% |
github.com/LerianStudio/flowker/pkg/templates/tracer_midaz |
81.5% |
github.com/LerianStudio/flowker/pkg/templates |
0.0% |
github.com/LerianStudio/flowker/pkg/transformation |
67.2% |
github.com/LerianStudio/flowker/pkg/triggers/webhook |
0.0% |
github.com/LerianStudio/flowker/pkg/triggers |
0.0% |
github.com/LerianStudio/flowker/pkg/webhook |
100.0% |
github.com/LerianStudio/flowker/pkg |
90.3% |
Generated by Go PR Analysis workflow
🔒 Security Scan Results —
|
| Policy | Status |
|---|---|
| Default non-root user | ✅ Passed |
| No fixable critical/high CVEs | ✅ Passed |
| No high-profile vulnerabilities | ✅ Passed |
| No AGPL v3 licenses | ✅ Passed |
Pre-release Version Check
✅ No unstable version pins found.
The Postgres testcontainer in both tests/integration and tests/e2e used
`wait.ForListeningPort("5432/tcp")`, which only checks the TCP port. Postgres
opens the port early during init but is not yet ready to accept connections,
so the first `bootstrap.AuditDatabaseManager.Connect` ping races and gets
`connection reset by peer` from the still-initializing server. This has been
flaking integration and e2e CI on develop for at least a week (visible on
runs since 2026-05-08).
Canonical fix: Postgres logs "database system is ready to accept connections"
twice during startup — once for the transient init server, once for the real
external server. Waiting for occurrence #2 (combined with the port check)
guarantees the DB will not reject incoming connections.
Scope note: this fix lives on the Makefile pre-push branch because the
Integration Tests job is part of the same CI surface and was blocking this
PR's merge despite being a pre-existing develop bug. Other open PRs (#23,
#28) will also benefit once they rebase onto a develop that includes this.
The Postgres testcontainer in both tests/integration and tests/e2e used
`wait.ForListeningPort("5432/tcp")`, which only checks the TCP port. Postgres
opens the port early during init but is not yet ready to accept connections,
so the first `bootstrap.AuditDatabaseManager.Connect` ping races and gets
`connection reset by peer` from the still-initializing server. This has been
flaking integration and e2e CI on develop for at least a week (visible on
runs since 2026-05-08).
Canonical fix: Postgres logs "database system is ready to accept connections"
twice during startup — once for the transient init server, once for the real
external server. Waiting for occurrence #2 (combined with the port check)
guarantees the DB will not reject incoming connections.
Scope note: this fix lives on the Makefile pre-push branch because the
Integration Tests job is part of the same CI surface and was blocking this
PR's merge despite being a pre-existing develop bug. Other open PRs (#23,
#28) will also benefit once they rebase onto a develop that includes this.
Summary
Fixes a latent bug where POSTing (or PUTting) a provider configuration with an invalid
configpayload returned HTTP 500 internal server error instead of HTTP 422 Unprocessable Entity with codeFLK-0293. The user saw a generic crash when in fact they sent malformed input.Root cause
internal/services/command/create_provider_config.go(andupdate_provider_config.go) wrapped schema validation failures like this:The handler at
provider_configuration/handler.go:364checks viaerrors.Is(err, constant.ErrProviderConfigInvalidSchema). But:pkg.ValidationError.Is()only returns true forValidationErrortargets with matchingCode— it cannot match plain*errors.errorStringsentinels.ValidationError.Unwrap()returnse.Err, which was nil.errors.Istherefore walked an empty chain and returned false, falling through to the default500branch.Fix
Set
Err: constant.ErrProviderConfigInvalidSchemaon bothValidationErrorconstructions. This wires the Unwrap chain soerrors.Isfinds the sentinel. Principled, single-point fix — no handler changes needed.Test plan
TestCreateProviderConfig_SchemaValidationFailure_IsConstantErrProviderConfigInvalidSchema(and the Update equivalent) fails ondevelopwitherrors.Isreturning false.FLK-0293body on POST and PUT with invalid config.make lint: zero new findings (the 2 inherited pre-existing warnings onInitServersandtoken_fetcher.goare confirmed present on develop).POST /v1/provider-configurationswith a config missing required fields → expect 422 withFLK-0293.Out of scope — follow-up candidates
The agent that fixed this catalogued 20+ other sites in the codebase using the same
pkg.ValidationError{Code: <sentinel>.Error(), ...}pattern without settingErr. Most are in command/repository layers and may or may not have a downstreamerrors.Is(err, <sentinel>)check that's silently broken in the same way. A separate audit PR should:errors.Is(err, sentinel)check in HTTP handlers and worker dispatch paths.Errcarries the sentinel wherever a domain error wraps one.Locations flagged for future investigation:
activate_workflow.go:146, 253, 261, 268create_workflow.go:158, 165, 183execution_repository.go:69, 77, 85, 93, 103, 113provider_config_repository.go:84, 91get_provider_config.go:57mongodb/executor_configuration/repository.go:194, 206mongodb/execution/repository.go:345, 354mongodb/workflow/repository.go:193, 205mongodb/provider_configuration/repository.go:197, 209bootstrap/tls_enforcement.go:52, 69Plus the lookup table at
pkg/errors.go:318+— those are pre-loaded definitions and warrant separate semantic analysis before bulk-editing.Notes
test_tracer_connectivity_missing_api_keyE2E scenario in feat(service): implement ConnectivityProber for Tracer with X-API-Key auth #25, which had to loosen its assertion to "creation rejected with any 4xx/5xx" because of this bug. Once this fix is in develop and feat(service): implement ConnectivityProber for Tracer with X-API-Key auth #25 rebases, that E2E test can be tightened to expect 422 specifically.