Skip to content

Expand API coverage, add Resource wrapper, error subclasses, tooling#37

Merged
dbirulia merged 2 commits into
mainfrom
missing-features
May 27, 2026
Merged

Expand API coverage, add Resource wrapper, error subclasses, tooling#37
dbirulia merged 2 commits into
mainfrom
missing-features

Conversation

@Kaevan89

@Kaevan89 Kaevan89 commented May 27, 2026

Copy link
Copy Markdown
Collaborator

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 >= 2.14.1, < 3.0 to clear CVE-2026-25765.
    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.
  • json updated to 2.19.5 to clear CVE-2026-33210.
  • bundle-audit is now clean on Ruby 3.0, 3.4 and 4.0.

== 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, and
    pin TargetRubyVersion: 3.0 so cop behaviour is identical across the
    whole 3.0 → 4.0 CI matrix.
  • CI matrix updated to ["3.0", "3.1", "3.2", "3.3", "3.4", "4.0"]
    (drops EOL Ruby 2.7, adds Ruby 4.0 stable).
  • .ruby-version bumped to 3.4.1 for local development parity.
  • 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, including a supported-Ruby
    table covering 3.0 through 4.0.
  • 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/
    spec/fixtures/responses//.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 Environment rspec rubocop bundle-audit
3.0.7 Docker ruby:3.0.7 (CI parity) 205 examples, 0 failures 53 files, no offenses clean
3.4.1 rbenv (arm64-darwin) 205 examples, 0 failures 53 files, no offenses clean
4.0.5 rbenv (arm64-darwin) 205 examples, 0 failures 53 files, no offenses clean

100% line coverage on lib/.

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
Kaevan89 force-pushed the missing-features branch from 4412cd8 to eec6b76 Compare May 27, 2026 00:39
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>
@dbirulia
dbirulia merged commit 392eadf into main May 27, 2026
6 checks passed
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.

2 participants