Skip to content

feat: RFC 9457 error responses with tests - #15

Closed
Taure wants to merge 8 commits into
masterfrom
feat/rfc9457-error-responses
Closed

feat: RFC 9457 error responses with tests#15
Taure wants to merge 8 commits into
masterfrom
feat/rfc9457-error-responses

Conversation

@Taure

@Taure Taure commented Mar 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace thoas with Erlang/OTP json module
  • Update plugin callbacks to 4-arity Nova 0.13 API (pre_request/4, post_request/4)
  • Add init/0 callback to start jesse database and preload schemas
  • Return RFC 9457 application/problem+json error responses with configurable status codes
  • Add group_by_field option to group validation errors by JSON pointer path
  • Fix bug where binary schema keys crashed jesse:validate (jesse's load/1 only accepts lists)
  • Add 56 EUnit tests covering error rendering, JSON pointers, plugin callbacks, and jesse integration
  • Add rebar3_audit, rebar3_sbom, meck (test), xref_ignores for plugin callbacks

Test plan

  • 56 EUnit tests pass locally
  • rebar3 fmt, xref, dialyzer all clean
  • CI workflow validates on push

Taure and others added 7 commits March 16, 2026 22:09
Use json:encode/1 and json:decode/1 directly instead of the
configurable json_lib approach via nova:get_env. The json_lib
config option was removed from Nova.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update pre_request/post_request to 4-arity callbacks matching
the current nova_plugin behaviour. Update plugin_info to return
a map instead of a tuple.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap validation errors in RFC 9457 Problem Details envelope
  (type, title, status, detail, errors)
- Default status code changed from 400 to 422 (configurable via
  status_code option for backwards compatibility)
- Set Content-Type to application/problem+json on error responses
- Add JSON Pointer (RFC 6901) paths for field locations
- Normalize error keys to path, message, type, actual_value, expected
- Handle all Jesse error types (schema_invalid, data_error,
  schema_error) instead of only data_invalid
- Guard file:read_file in validate_json to return clean error on
  missing schema files instead of crashing
- Add group_by_field option to group errors by field path for
  form-friendly consumption
- Bump version to 0.3.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 56 EUnit tests covering RFC 9457 error rendering, JSON pointer
generation, format messages, pre_request/post_request callbacks,
and validate_json with jesse integration.

Fix bug where binary schema keys passed to jesse:validate would crash
with function_clause since jesse_database:load/1 only accepts lists.
Add ensure_list/1 helper to convert binary keys.

Update nova dep to 0.13.7, add meck test dep, xref_ignores for
plugin callbacks, rebar3_audit and rebar3_sbom plugins.
@github-actions

github-actions Bot commented Mar 16, 2026

Copy link
Copy Markdown

🛡️ Security Audit

No vulnerabilities found in 9 dependencies.


ℹ️ 1 OTP CVE auto-ignored (already fixed in running version)

These CVEs are patched in the installed OTP version but NVD data
has not been updated to reflect this. They are excluded from the
scan via an auto-generated .trivyignore.

CVE Details
CVE-2025-4748 Fixed in 28.0.1, running 28.0.1 — Absolute Path in Zip Module

jesse returns wrong_type and missing_required_property without a
{ErrorType, Details} wrapper. For wrong_type, extract the expected
type from the schema map. For missing_required_property, the property
name is in the Value position, not Details.
@Taure

Taure commented Mar 18, 2026

Copy link
Copy Markdown
Contributor Author

Split into two PRs: #16 (plugin format update) and #17 (RFC 9457 error responses)

@Taure Taure closed this Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant