Skip to content

feat(textract): migrate to AWS SDK, add AnalyzeExpense and AnalyzeID#5456

Merged
waleedlatif1 merged 6 commits into
stagingfrom
textract-integration-audit
Jul 7, 2026
Merged

feat(textract): migrate to AWS SDK, add AnalyzeExpense and AnalyzeID#5456
waleedlatif1 merged 6 commits into
stagingfrom
textract-integration-audit

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Replace the hand-rolled AWS SigV4 signer in the Textract parse route with the official @aws-sdk/client-textract package, matching how sibling AWS integrations (Secrets Manager, S3, STS) already call AWS
  • Add an Analyze Expense operation (structured invoice/receipt extraction: vendor, totals, line items) via AnalyzeExpense (sync) / StartExpenseAnalysis+GetExpenseAnalysis (async, S3)
  • Add an Analyze Identity Document operation (AnalyzeID) for driver's licenses/passports, with an optional back-of-ID page
  • These fill a real gap: the block's own templates/skills already advertised invoice extraction and ID verification, but no tool backed them
  • Add an operation dropdown to the textract_v2 block; defaults to the existing Analyze Document behavior so already-saved workflows are unaffected
  • Removed 3 dead/unreferenced interfaces from tools/textract/types.ts

Type of Change

  • New feature

Testing

  • Added unit tests for tool body/response construction (all 3 tools) and for the AWS-response-to-output mapping functions in each route (29 tests total)
  • bun run type-check, bun run lint, and bun run check:api-validation all pass

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

- Replace hand-rolled AWS SigV4 signing with @aws-sdk/client-textract, matching sibling AWS integrations (secrets_manager, s3, sts)
- Add Analyze Expense operation (invoice/receipt structured extraction) via AnalyzeExpense/StartExpenseAnalysis+GetExpenseAnalysis
- Add Analyze Identity Document operation (AnalyzeID) with optional back-of-ID page
- Add an operation selector to the textract_v2 block; defaults to the existing Analyze Document behavior for backward compatibility
- Add tests for tool body/response mapping and route-level AWS response normalization
@waleedlatif1 waleedlatif1 requested a review from a team as a code owner July 7, 2026 01:04
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 7, 2026 2:07am

Request Review

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches document ingestion (SSRF controls, file access) and accepts user-supplied AWS keys; Analyze ID adds PII handling, and the parse-route migration is a large behavioral swap though covered by tests.

Overview
Migrates Textract from hand-rolled SigV4 HTTP calls to @aws-sdk/client-textract, with shared helpers for document resolution (uploads, pinned URL fetch, S3 URI validation), async job polling, and SDK error mapping—including the multi-page PDF hint where async mode exists.

Adds two API surfaces and tools: Analyze Expense (sync AnalyzeExpense / async StartExpenseAnalysis + paginated GetExpenseAnalysis) and Analyze ID (sync AnalyzeID, optional back page), each returning camelCase-normalized payloads.

Extends textract_v2 with an Operation dropdown (defaults to existing analyze-document), routes to textract_parser_v2, textract_analyze_expense, or textract_analyze_id, operation-specific outputs, and back-of-ID inputs for ID verification. Zod contracts and the tool registry are updated; API route count baseline moves to 906.

Reviewed by Cursor Bugbot for commit 55cb4eb. Configure here.

Comment thread apps/sim/blocks/blocks/textract.ts
Comment thread apps/sim/app/api/tools/textract/analyze-expense/route.ts
@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces the hand-rolled AWS SigV4 signing implementation in the Textract parse route with @aws-sdk/client-textract, and adds two new operations — AnalyzeExpense (sync + async) and AnalyzeID (sync only) — behind a new operation dropdown in the textract_v2 block. The SDK migration is clean and removes ~240 lines of bespoke signing/polling code by extracting shared logic into a new shared.ts module.

  • Shared utilities (resolveDocumentInput, pollTextractJob, mapTextractSdkError, parseS3Uri) are extracted into shared.ts, reducing duplication across the three route handlers, and all security guards (SSRF validation, path-traversal checks, S3 bucket name validation) are preserved in the new shared module.
  • A function-typed condition (documentFieldCondition) ensures the front-document upload fields remain visible for analyze_id regardless of any stale processingMode value left over from a prior operation, addressing the previously reported UI bug.
  • 29 unit tests are added covering route-level normalization functions, tool body builders, shared utilities (parseS3Uri, mapTextractSdkError, pollTextractJob), and response deserialization for all three operations.

Confidence Score: 5/5

Safe to merge — the SDK migration is a drop-in replacement for the hand-rolled SigV4 signer, all security guards are preserved in the new shared module, and the new operations follow the same patterns as the existing route.

The migration removes substantial bespoke code in favor of the official SDK and factors shared logic into a well-tested module. The documentFieldCondition function correctly handles the stale-processingMode scenario for analyze_id that was flagged in the previous review cycle. All three routes validate inputs at the contract layer and the route layer, SSRF and path-traversal guards are carried over intact, and 29 tests cover the key normalization and utility functions.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/api/tools/textract/shared.ts New shared module extracting resolveDocumentInput, pollTextractJob, mapTextractSdkError, parseS3Uri, and TextractRouteError; all security guards from the original parse route are preserved, error statuses are correctly typed, and the module is well-tested.
apps/sim/blocks/blocks/textract.ts Adds operation dropdown with three choices and the documentFieldCondition helper that dynamically returns an operation-based condition for analyze_id; tool selector and param-builder updated correctly for all three operations.
apps/sim/app/api/tools/textract/parse/route.ts SDK migration drops ~220 lines; delegates document resolution, job polling, and error mapping to shared.ts; behavior is functionally equivalent to the pre-migration implementation.
apps/sim/app/api/tools/textract/analyze-expense/route.ts New route implementing AnalyzeExpense (sync) and StartExpenseAnalysis/GetExpenseAnalysis (async); normalizeExpenseDocuments maps the AWS SDK shape to a clean camelCase output; pagination handled correctly via pollTextractJob.
apps/sim/app/api/tools/textract/analyze-id/route.ts New synchronous-only route implementing AnalyzeID; correctly passes both front and optional back document pages via DocumentPages; mapTextractSdkError called with hasAsyncMode:false for appropriate error messages.
apps/sim/lib/api/contracts/tools/media/document-parse.ts Adds textractAnalyzeExpenseBodySchema and textractAnalyzeIdBodySchema with proper superRefine cross-field validation; new contracts follow the established pattern.
apps/sim/tools/textract/analyze-expense.ts New tool config; params visibility correctly uses user-only for credentials and hidden for file inputs; body builder handles sync and async paths consistently.
apps/sim/tools/textract/analyze-id.ts New tool config for textract_analyze_id; supports optional back-of-ID document; body builder validates that at least a front document is provided before sending.
apps/sim/tools/textract/types.ts Removes three dead interfaces and adds proper input/output types for the two new operations.

Reviews (6): Last reviewed commit: "chore(textract): drop redundant inline c..." | Re-trigger Greptile

Comment thread apps/sim/app/api/tools/textract/shared.ts Outdated
Comment thread apps/sim/app/api/tools/textract/analyze-expense/route.ts
- textract_analyze_expense/textract_analyze_id now fall back to filePath/filePathBack when the document input is a URL string rather than an uploaded file object, so advanced "File reference" URL inputs actually reach the API (Cursor Bugbot)
- mapTextractSdkError defaults to 500 (not 400) when the AWS SDK error has no HTTP status, since that implies a server-side/network failure rather than a bad request (Greptile)
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/blocks/blocks/textract.ts
- Front-document fields (fileUpload/fileReference) are shared across all 3 operations; gate them with a values-aware condition so switching to Analyze Identity Document keeps them visible even if a stale processingMode='async' is left over from a previous operation
- S3 URI field now also requires operation !== 'analyze_id', since that operation never supports S3 input
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/api/tools/textract/parse/route.ts
pollTextractJob's merge callbacks spread only the latest page, dropping
any field (DocumentMetadata, model version) the first page had but a
follow-up NextToken page omits. Merge accumulated first so later pages
only override fields they actually return.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/api/tools/textract/shared.ts Outdated
…ch failures

fetchDocumentBytes hardcoded 400 for any non-OK response from a document
URL, masking transient 5xx failures from the document host as client
errors and blocking tool-execution retries. Use the actual response
status instead.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit dd92247. Configure here.

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 55cb4eb. Configure here.

@waleedlatif1 waleedlatif1 merged commit b686111 into staging Jul 7, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the textract-integration-audit branch July 7, 2026 02:42
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