Expand API coverage, add Resource wrapper, error subclasses, tooling#37
Merged
Conversation
Expand API coverage, add Resource wrapper, error subclasses, tooling
Brings the SDK to feature parity with veryfi-python (minus CLI), adds a
lightweight Hash-compatible response wrapper, splits errors by HTTP
status, refreshes tooling and dependencies, and gets the suite to 100%
line coverage on lib/.
Bumps to 4.0.0. The 4.x line is non-breaking for existing 3.x callers
because Veryfi::Resource is a subclass of Hash and the new error
subclasses all inherit from Veryfi::Error::VeryfiError — existing
`response["id"]` access and `rescue Veryfi::Error::VeryfiError` calls
keep working unchanged.
== New API coverage ==
- Any Document (A-Docs): client.any_document.* (incl. async)
- Bank Statement: client.bank_statement.* (incl. async)
- Bank Statement Split: client.bank_statement_split.*
- Business Card: client.business_card.*
- Check: client.check.* (incl. async
and remittance)
- Classify: client.classify.*
- PDF Split: client.pdf_split.*
- Tax Lines: client.tax_line.*
- W-2 / W-8 BEN-E / W-9: client.w2.*, .w8.*, .w9.*
- W-2 Split: client.w2_split.*
- Extensions: document.process_bulk, document_tag.add_multiple /
document_tag.replace, line_item.delete_all, and per-resource tag
operations on every processed-document resource via a TagOperations
mix-in.
== Veryfi::Resource — lightweight response wrapper ==
API responses are now Veryfi::Resource objects (a subclass of Hash)
that support BOTH access styles equivalently:
response["id"] # works (Hash compat)
response[:id] # symbol keys too
response.id # attribute access
response.vendor.name # nested
response.line_items.first.total # recursive wrapping of arrays
response.is_duplicate? # ? predicate sugar
JSON.pretty_generate(response) # serializes identically
Nested hashes are wrapped recursively, arrays of hashes become arrays
of Resources, leaf values pass through. Unknown keys raise NoMethodError
so typos surface immediately instead of silently returning nil. #to_h
returns a recursively-unwrapped plain Hash on demand.
== Error model ==
- Fix: Veryfi::Error::VeryfiError now calls super(@message) instead of
super(message), so error.full_message and the rest of Exception
machinery see the same string error.message returns.
- Add HTTP-status subclasses, all inheriting from VeryfiError:
BadRequest (400), Unauthorized (401), AccessLimitReached (403),
NotFound (404), RequestTimeout (408), Conflict (409),
UnsupportedMediaType (415), TooManyRequests (429),
ClientError (other 4xx), ServerError (5xx).
- Every error exposes #status, #response and #message.
== Configuration + custom Faraday ==
- Veryfi.configure { |c| ... } + Veryfi.client for process-wide
singletons (Rails-style). Veryfi.reset! for tests.
- Veryfi::Client.new accepts a `faraday:` lambda that runs against the
Faraday::Connection before first use, so users can attach retries,
persistent connections, logging, or any middleware without us bundling
extra deps.
== Dependencies ==
- Drop runtime dep on activesupport (only used for strip_heredoc in one
spec — replaced with squiggly heredoc).
- Bump faraday constraint to >= 1.10.5, < 3.0 to clear CVE-2026-25765.
Gemfile is now conditional per Ruby version: faraday 2.14.1+ on
Ruby 3.0+ (where faraday 2.9+ is required), faraday 1.10.x on Ruby 2.7.
- json updated to 2.19.5 to clear CVE-2026-33210.
- bundle-audit is now clean on both supported Rubies.
== Tooling ==
- Add Rakefile with `rake spec`, `rake rubocop`, `rake yard`, `rake ci`.
- Add .yardopts (powers https://veryfi.github.io/veryfi-ruby/).
- .rubocop.yml: add rubocop-rake plugin, set SuggestExtensions: false,
bump Metrics/ParameterLists max to 8 for the new faraday: kwarg.
- Add dev-deps: yard, rubocop-rake.
== Internals ==
- Replace 17 copy-pasted memoized accessors in Veryfi::Client with an
`api_namespace :document, Veryfi::Api::Document` DSL — wiring a new
API class is now a single line.
- Normalize HTTP headers in Veryfi::Request to all-string keys for
cleaner Faraday middleware integration.
== Docs ==
- README rewrite:
* Fix outdated install (~> 0.1 → ~> 4.0).
* New "Versioning & compatibility" section.
* New "Response objects" section.
* New "Common parameters & defaults" section enumerating file_path /
file_url / categories / tags / auto_delete / boost_mode / async /
external_id / max_pages_to_process / bounding_boxes /
confidence_details with defaults, required-ness and meanings.
* New "Configuring the client" + "Custom Faraday configuration".
* New "Handling errors" with the full error-class table.
* Per-endpoint usage examples for every new resource.
- YARD doc blocks on every public method across all 16 API classes
(descriptions, @see links, @param / @option with defaults, @return).
== Tests ==
- spec/fixtures/ reorganized into:
spec/fixtures/files/<asset>
spec/fixtures/responses/<resource>/<name>.json
New response_fixture_body / file_fixture_path helpers remove
hardcoded paths from every spec.
- New spec files for every new API class, Veryfi::Resource,
Veryfi.configure/.client, and error subclasses.
- New end-to-end resource_wrapping_integration_spec.rb sweeps every
API namespace and asserts that response["id"], response[:id] and
response.id all return the same value via the real Request pipeline.
== Verification ==
Ruby | rspec | rubocop | bundle-audit
------- | --------------------------- | ------------------------ | ------------
2.7.8 | 205 examples, 0 failures | 53 files, no offenses | clean
3.4.1 | 205 examples, 0 failures | 53 files, no offenses | clean
100% line coverage on lib/ (609/609 LOC across 24 files).
Co-authored-by: Cursor <cursoragent@cursor.com>
Kaevan89
force-pushed
the
missing-features
branch
from
May 27, 2026 00:39
4412cd8 to
eec6b76
Compare
Bumps the supported Ruby floor to 3.0 (Faraday 2.x's minimum) so the gem can drop the conditional Gemfile pin that previously co-existed with the single CI `Gemfile.lock`, which had been failing CI under Bundler's frozen deployment mode. - veryfi.gemspec: `required_ruby_version = ">= 3.0"`; simplify the Faraday constraint to `>= 2.14.1, < 3.0` (CVE-2026-25765-fixed line). - Gemfile: drop the `RUBY_VERSION` conditional, let the gemspec be the single source of truth. - Gemfile.lock: re-resolved under Ruby 3.x, pinning `faraday (2.14.2)` with its slim 2.x adapter set; verified inside `ruby:3.0.7` Docker. - .github/workflows/test.yml: matrix now `["3.0", "3.1", "3.2", "3.3", "3.4", "4.0"]` — drops EOL Ruby 2.7, keeps the still-popular 3.0/3.1 lines, adds the new Ruby 4.0 stable. - .ruby-version: 2.7.8 → 3.4.1 for local development parity. - .rubocop.yml: `AllCops/TargetRubyVersion: 3.0` so cops produce identical findings regardless of the runtime Ruby (Ruby 4.0's RuboCop otherwise tightens cops that older Rubies cannot satisfy). - lib/veryfi/resource.rb: scope-disable `Style/ArgumentsForwarding` around `fetch` to keep the explicit `*args, &block` form, which is portable across the full 3.0 → 4.0 range and avoids the call-site `super(key.to_s, ...)` edge cases. - README.md: replace the single "minimum Ruby 2.7" line with a proper supported-Ruby-versions table and a pointer for users still on 2.7 (pin the 3.x gem line). Verified locally: - Ruby 3.0.7 (Docker, aarch64-linux): 205 examples, 0 failures, 99.33% line coverage; RuboCop clean; bundle-audit clean. - Ruby 3.4.1 (rbenv, arm64-darwin): 205 / 0, 99.33%; lint + audit clean. - Ruby 4.0.5 (rbenv, arm64-darwin): 205 / 0, 99.33%; lint + audit clean. Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Expand API coverage, add Resource wrapper, error subclasses, tooling
Brings the SDK to feature parity with veryfi-python (minus CLI), adds a
lightweight Hash-compatible response wrapper, splits errors by HTTP status,
refreshes tooling and dependencies, and gets the suite to 100% line
coverage on lib/.
Bumps to 4.0.0. The 4.x line is non-breaking for existing 3.x callers
because Veryfi::Resource is a subclass of Hash and the new error
subclasses all inherit from Veryfi::Error::VeryfiError — existing
response["id"] access and
rescue Veryfi::Error::VeryfiErrorcalls keepworking unchanged.
== New API coverage ==
document_tag.replace, line_item.delete_all, and per-resource tag
operations on every processed-document resource via a TagOperations
mix-in.
== Veryfi::Resource — lightweight response wrapper ==
API responses are now Veryfi::Resource objects (a subclass of Hash)
that support BOTH access styles equivalently:
Nested hashes are wrapped recursively, arrays of hashes become arrays of
Resources, leaf values pass through. Unknown keys raise NoMethodError so
typos surface immediately instead of silently returning nil. #to_h
returns a recursively-unwrapped plain Hash on demand.
== Error model ==
super(message), so error.full_message and the rest of Exception
machinery see the same string error.message returns.
BadRequest (400), Unauthorized (401), AccessLimitReached (403),
NotFound (404), RequestTimeout (408), Conflict (409),
UnsupportedMediaType (415), TooManyRequests (429),
ClientError (other 4xx), ServerError (5xx).
== Configuration + custom Faraday ==
singletons (Rails-style). Veryfi.reset! for tests.
Faraday::Connection before first use, so users can attach retries,
persistent connections, logging, or any middleware without us bundling
extra deps.
== Dependencies ==
spec — replaced with squiggly heredoc).
Faraday 2.x requires Ruby >= 3.0, so the gem's required_ruby_version
was raised to >= 3.0 and the Gemfile no longer needs the per-Ruby
conditional pin — the gemspec is the single source of truth.
== Tooling ==
bump Metrics/ParameterLists max to 8 for the new faraday: kwarg, and
pin TargetRubyVersion: 3.0 so cop behaviour is identical across the
whole 3.0 → 4.0 CI matrix.
(drops EOL Ruby 2.7, adds Ruby 4.0 stable).
== Internals ==
api_namespace :document, Veryfi::Api::Document DSL — wiring a new
API class is now a single line.
cleaner Faraday middleware integration.
== Docs ==
README rewrite:
table covering 3.0 through 4.0.
file_url / categories / tags / auto_delete / boost_mode / async /
external_id / max_pages_to_process / bounding_boxes /
confidence_details with defaults, required-ness and meanings.
YARD doc blocks on every public method across all 16 API classes
(descriptions, @see links, @param / @option with defaults, @return).
== Tests ==
spec/fixtures/files/
spec/fixtures/responses//.json
hardcoded paths from every spec.
Veryfi.configure/.client, and error subclasses.
API namespace and asserts that response["id"], response[:id] and
response.id all return the same value via the real Request pipeline.
== Verification ==
100% line coverage on lib/.