feat(netsuite): add Oracle NetSuite integration - #6476
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryHigh Risk Overview Workflow surface: a NetSuite block with 27 operations (record CRUD/upsert, subresources, forms, select options, attach/detach, actions, transforms, SuiteQL, SuiteAnalytics datasets, async batches, job status/results, metadata, governance). Bounded pickers (record types up to 1,000, async tasks up to 100) go through a new Platform wiring: Reviewed by Cursor Bugbot for commit eb21fe4. Configure here. |
Greptile SummaryThe PR adds an Oracle NetSuite integration with certificate-backed service-account authentication, selectors, documentation, and 27 SuiteTalk operations.
Confidence Score: 5/5The PR appears safe to merge from the reviewed follow-up findings. No blocking failure remains from the previously reported token-cache or import-path issues.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/oauth/credential-service.ts | Extends reusable service-account token resolution and safely isolates cached credentials by credential ID and encrypted-secret rotation fingerprint. |
| apps/sim/lib/credentials/client-credential-accounts/minters/netsuite.ts | Implements certificate-backed NetSuite client-credential assertion signing and token exchange. |
| apps/sim/tools/netsuite/utils.ts | Provides shared SuiteTalk validation, request execution, response contracts, payload limits, timeout handling, and error sanitization. |
| apps/sim/blocks/blocks/netsuite.ts | Defines the NetSuite block’s 27 operations, inputs, selectors, tool mappings, and outputs. |
| apps/sim/app/api/tools/netsuite/objects/route.ts | Adds the typed, credential-authorized selector endpoint for NetSuite record types and async tasks. |
| apps/sim/tools/netsuite/netsuite.test.ts | Verifies block-to-tool coverage and now follows the established absolute import convention. |
Sequence Diagram
sequenceDiagram
participant User
participant Block as NetSuite Block
participant Cred as Credential Service
participant OAuth as NetSuite OAuth
participant Tool as NetSuite Tool
participant SuiteTalk as SuiteTalk REST API
User->>Block: Select stored NetSuite credential
Block->>Cred: Resolve credential ID
Cred->>Cred: Decrypt signing material
Cred->>OAuth: Send signed client assertion
OAuth-->>Cred: Short-lived access token
Cred-->>Tool: Token and normalized SuiteTalk origin
Tool->>SuiteTalk: Validated operation request
SuiteTalk-->>Tool: Record, metadata, dataset, or async response
Tool-->>Block: Normalized bounded result
Reviews (9): Last reviewed commit: "chore(netsuite): regenerate tool metadat..." | Re-trigger Greptile
|
@cursor review |
There was a problem hiding this comment.
✅ 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 cdd5240. Configure here.
|
@cursor review |
There was a problem hiding this comment.
✅ 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 61407f5. Configure here.
32d4bc3 to
c8f3327
Compare
8bb7adb to
841aa5c
Compare
Architecture noteNetSuite intentionally combines three established integration patterns:
No single existing integration covers all of Oracle’s requirements. NetSuite composes these established patterns at their existing architectural boundaries rather than introducing a new integration architecture. |
|
@cursor review |
There was a problem hiding this comment.
✅ 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 607c177. Configure here.
|
@cursor review |
There was a problem hiding this comment.
✅ 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 8cf2388. Configure here.
Oracle documents the Location response header for create and update, and both tools already require it. Upsert and transform also produce a record but Oracle documents no response headers for either, so they dropped the header entirely and the new record's ID was unreachable. Add a `resource-optional` location mode that captures Location when NetSuite sends it and never fails when it is absent, and wire it to upsert and transform along with their tool and block outputs. Async task discovery rejected the whole response if any task link carried a rel other than `self`, collapsing the picker into a 502. Oracle documents a `self` link per task but never guarantees it is the only one, so skip other relationships and fail only when no self link exists. Also use the shared `truncate` helper in the error sanitizer per the repo convention instead of an inline slice.
The shared collection-page validator required links, items, count, hasMore, offset, and totalResults on every 200, and a missing field turns a successful call into a reported failure. Oracle documents all six for record collections and SuiteAnalytics dataset pages, but its SuiteQL reference lists only links, count, offset, totalResults, and items. A documented SuiteQL response that omits hasMore would therefore have been rejected. Split out a suiteql-page validator that requires the five documented SuiteQL fields and type-checks hasMore only when the account returns it. Record collections and dataset pages keep requiring all six.
The rebase conflicted only in the generated tool-id, tool-metadata, and tool-output artifacts, which NetSuite and the newly landed LogRocket integration both extend. Regenerated from the merged registries: the result is staging's catalog plus the 27 NetSuite tools, with LogRocket's entries intact and no other tool changed.
8cf2388 to
eb21fe4
Compare
|
@cursor review |
There was a problem hiding this comment.
✅ 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 eb21fe4. Configure here.
Summary
netsuite-service-accountcredential; tools receive only a short-lived access token and normalized SuiteTalk origin.Architecture record
This branch is rebased on staging commit
cc7f005b3ae1183a502d258320a54b4d0fab2d61.Locationheaders, async idempotency replay, bounded JSON admission, cancellation, deadlines, and error redaction remain in the NetSuite tool layer because the generic executor cannot represent the documented HTTP 400 idempotent-replay success.certificateId, thenetsuite-service-accountprovider registration, selector registry/context entries, API-route baseline bookkeeping, and the handwritten service-account-doc allowlist. No generic executor, selector component, docs parser, credential-deletion behavior, canonical-mode behavior, or NetSuite application layer was added.Final audit fixes
X-NetSuite-PropertyNameValidation: erroris now limited to/services/rest/record/request bodies. SuiteQL sends only its documentedPrefer: transientbehavior plus ordinary JSON/authentication headers.expandquery while retaining its explicitly live-unverified status because current Oracle references conflict.Validation
git diff --checkand the focused four-file Biome check passed.validate-integrationand memory-load pass used the completeintegration_feedback.md, reviewed every branch-changed subsystem, current repository precedents, and current official Oracle evidence. No additional confirmed NetSuite-local defect was found.Merge dependency: shared credential collision
Do not merge this PR until the separate shared credential-creation fix lands and this branch is rebased onto it.
Today, creating a second secret-backed service account with the same provider and display name can return the existing credential instead of rejecting the newly verified secret material. For NetSuite, two valid certificate/entity/role mappings for one account receive the same default display name, so the second mapping can silently select the first credential and execute with the wrong role. This is a generic credential-orchestration defect affecting multiple service-account families and is intentionally not patched inside this integration PR. The shared fix should return a conflict for fresh-secret collisions while preserving explicitly supported exact-ID replay behavior; after it lands, NetSuite must verify the same-name two-mapping journey returns HTTP 409.
Live limitations
No NetSuite credential was available, so real OAuth certificate mappings, account/role permissions, production and sandbox discovery, NetSuite 2026.1 feature availability, mutations, async polling/result variants, and account-specific record/dataset schemas remain live-unverified. Oracle's current create-form guide names
expandas a GET response query parameter, while the 2026.1 Record API Browser omits it from ordinary singular GET; that behavior still needs a sandbox probe. No destructive live calls were attempted.Type of change
Checklist