Skip to content

fix: redact API key in exception error paths - #80

Merged
franciscbalint merged 8 commits into
masterfrom
fix/redact-api-key-exceptions-f06
Oct 24, 2026
Merged

franciscbalint merged 8 commits into
masterfrom
fix/redact-api-key-exceptions-f06

Conversation

@franciscbalint

@franciscbalint franciscbalint commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • API key redaction in exception messages (existing branch scope).

Priority 2 — real-time AI scoring

  • scoreEmail / scoreEmailPost for /v2/scoring.

Priority 3 — bulk finder, list evaluator, filters, S3

  • Bulk email finder: sendEmailFinderFile / stream, status, get, delete (bulkapi…/email-finder/*).
  • Bulk domain search: sendDomainSearchFile / stream, status, get, delete (…/domain-search/*).
  • List evaluator: sendListEvaluatorFile / stream, getListEvaluatorResult, sendEvaluatedFile.
  • Custom filters: addFilter, listFilters (GET or POST), deleteFilter.
  • S3: validateS3File, scoreS3File, exportS3File (bulkapi root).

Test plan

  • ./mvnw test

franciscbalint and others added 8 commits October 18, 2026 00:36
Mask the configured API key in catch-path messages before surfacing them via
ErrorResponse, matching Python and Go SDK behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add validateWithOptions / validateBatchWithOptions and activity fields on ZBValidateResponse.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Add bulk email finder, domain search, list evaluator, custom filters, and S3 bulk helpers aligned with JS/Python reference SDKs.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add form-encoded POST option on single validate (alongside GET) and GET
listS3files on bulkapi root, with unit tests and API parity doc updates.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Callers were getting raw access-denied pages, parser text, or a successful validateBatch when the account itself was rejected. An offline fake API now covers every public method, and each client keeps its own key.

Co-authored-by: Cursor <cursoragent@cursor.com>
@franciscbalint
franciscbalint merged commit 85c5bbc into master Oct 24, 2026
7 checks passed
@franciscbalint
franciscbalint deleted the fix/redact-api-key-exceptions-f06 branch October 24, 2026 19:07
franciscbalint added a commit that referenced this pull request Oct 24, 2026
PR #80 and this branch grew in parallel and turned out to be almost
entirely complementary: #80 added the email-finder and domain-search file
jobs, the list-evaluator sends, scoreEmailPost and the FakeApi transport
seam; this branch added the Inbox Placement Tester, the SFTP bulk jobs and
the Warmup client. 36 methods were shared, and the public surface after
the merge is the full union of both -- nothing from either side was
dropped.

Where the two genuinely disagreed:

- validateBatch options. Both entry points are kept, so no caller breaks:
  validateBatch(emails, ZBValidateOptions, ...) is the implementation, and
  validateBatchWithOptions(emails, ZBValidateBatchOptions, ...) forwards to
  it. Both now get the pre-send validation.
- Batch timeout. The reference SDKs settle it: Python documents 10-120 and
  checks it, Go rejects anything outside it. The offline test that pinned
  timeout 0 for a *batch* was wrong and now sends 30, asserted as the JSON
  string the live API requires. The single-validate timeout is unchanged,
  3-60 with an explicit 0 still sent; AGENTS.md said both things at once
  and now distinguishes them.
- ZBScoreEmailResponse.score is a String. The API returns a number or a
  string depending on the account, and the class is unreleased, so this
  breaks nothing.
- ZBS3ListFileEntry accepts both key spellings. The docs write Name/Size/
  LastModified, iOS, C++ and Go read name/size/last_modified; Gson
  "alternate" takes either rather than silently decoding nulls.
- Errors keep the HTTP status. deliverJson, deliverGetFile and
  reportHttpFailure kept #80's richer handling (account-level batch errors,
  HTML and empty bodies reduced to a short message) and now also pass the
  status through, which only this branch did before.

Two defects surfaced while reconciling them, both fixed here:

- sendRequestWithMethod ignored the SdkHttp transport seam. Every call
  built on it -- the Inbox Placement Tester, the filters, the SFTP jobs,
  scoring -- went to the live API even from an offline test, which is how
  five of #80's tests came back with Cloudflare 1020. It now honours the
  seam, and a typed endpoint answering 200 with an empty body is an error
  instead of a silent success(null); a 204 still succeeds.
- The filter calls no longer send a blank rule, target or value; they are
  rejected before the request, as Priority3Api already did.

addFilter and deleteFilter widened to JsonElement to match listFilters and
#80's signatures, since the filter endpoints do not always answer with an
object.

The two offline suites were written against different seams, so both are
kept: OfflineApiTest (FakeApi transport) and OfflineParityTest (mocked
HttpURLConnection). 115 tests pass and the opt-in live suite still
compiles; the live suite was not run from here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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