feat(sap): add SAP Concur integration block and SAP S/4HANA validation fixes#4483
feat(sap): add SAP Concur integration block and SAP S/4HANA validation fixes#4483waleedlatif1 merged 13 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryLow Risk Overview Introduces a Reviewed by Cursor Bugbot for commit e10ab76. Configure here. |
|
@greptile |
|
@cursor review |
Greptile SummaryThis PR introduces a new SAP Concur integration block with 70 tools spanning Expense Reports, Travel Requests, Receipts, Cash Advances, Users, Budgets, and more, plus targeted spec-alignment fixes for the existing SAP S/4HANA block. The Concur integration adds a dedicated OAuth 2.0 proxy with per-datacenter routing, DNS-pinned SSRF-safe outbound fetches, and a separate multipart upload endpoint for receipt images.
Confidence Score: 5/5Safe to merge. The Concur proxy and upload routes enforce SSRF protections at multiple layers, credentials are never leaked, and the S/4HANA cookie fix correctly resolves a previously flagged issue. Both new API routes use internal auth gating, Zod schema validation, allowed-datacenter enforcement, and DNS-pinned outbound fetches. The upload route validates MIME types per operation. All 70 tools mark credentials as user-only. The S/4HANA Set-Cookie fix is minimal and targeted. No files require special attention. The 130-file changeset is large but mostly repetitive tool definitions following a consistent pattern verified in the proxy and shared modules. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as Sim Workflow
participant Proxy as /api/tools/sap_concur/proxy
participant Upload as /api/tools/sap_concur/upload
participant Shared as shared.ts (token cache)
participant Concur as SAP Concur API
Client->>Proxy: "POST {auth, path, method, query, body}"
Proxy->>Proxy: checkInternalAuth()
Proxy->>Proxy: SapConcurProxyRequestSchema.parse()
Proxy->>Shared: fetchSapConcurAccessToken(auth)
alt cache miss
Shared->>Concur: POST /oauth2/v0/token
Concur-->>Shared: "{access_token, geolocation}"
Shared->>Shared: validate geolocation in SAP_CONCUR_ALLOWED_DATACENTERS
Shared->>Shared: rememberToken() LRU cache
end
Shared-->>Proxy: "{accessToken, geolocation}"
Proxy->>Concur: secureFetchWithValidation DNS-pinned
Concur-->>Proxy: response
Proxy-->>Client: "{success, output}"
Client->>Upload: "POST {auth, operation, userId, receipt}"
Upload->>Upload: inferMimeType + allowedForOperation check
Upload->>Shared: fetchSapConcurAccessToken(auth)
Shared-->>Upload: "{accessToken, geolocation}"
Upload->>Concur: secureFetchWithValidation multipart POST
Concur-->>Upload: 202 + Location/Link headers
Upload-->>Client: "{success, output}"
Reviews (2): Last reviewed commit: "fix(sap-concur): rename misleading excha..." | Re-trigger Greptile |
SecureFetchHeaders previously collapsed multi-value Set-Cookie headers with ", ", forcing consumers to re-split via a fragile regex. Cookie values containing "=" or "," (e.g., Base64 session tokens) could be misparsed and produce malformed Cookie strings on CSRF-protected mutations. Add SecureFetchHeaders.getSetCookie() that returns the raw array, and update the S/4HANA OData proxy's joinSetCookies to consume it directly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…refresh_token grant, validate geolocation host - Rename sap_concur_get_exchange_rate to sap_concur_upload_exchange_rates (POST bulk upload, not GET) - Remove refresh_token from SapConcurGrantType / Zod enum / block dropdown / docs (no implementation) - Validate Concur geolocation hostname against SAP_CONCUR_ALLOWED_DATACENTERS Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
@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 e10ab76. Configure here.
d68be45 to
79c6fde
Compare
Tool and trigger descriptions can contain URL path placeholders like
{reportId} or JSON-shape hints like { Items, NextPage }. When rendered
as MDX prose (not table cells), these were emitted unescaped and MDX
parsed them as JSX expressions, failing prerender with
"ReferenceError: reportId is not defined".
Escape { and } in the operation-level description and trigger
description renderers, matching the existing escaping in table-cell
descriptions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…and context types - list_travel_profiles_summary: rename Status query to Active with 1/0 values, tighten LastModifiedDate format hint - list_itineraries / get_itinerary: use documented userid_type / userid_value / ItemsPerPage / Page query keys - create_report_comment: contextType allows MANAGER (move to EXPENSE_READ_CONTEXT_TYPE_OPS) - get_list_item: drop unused listId from block (tool only needs itemId) - Tighten description copy on list_expenses/get_itemizations/associate_attendees/remove_all_attendees Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Update Cash Advance create/get/issue tools from /cashadvance/v4/ to /cashadvance/v4.1/ to match the live API - Add filter query param to list_users (SCIM v4.1 supports filtering by userName, employeeNumber, externalId) - Regenerate docs MDX Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…v4.1 GET) SCIM Identity v4.1 GET /Users does not accept a filter query parameter — filtering is only supported via POST /Users/.search (already exposed by sap_concur_search_users). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Verified against live SAP Concur docs (concur/developer.concur.com preview branch): - Revert Cash Advance paths to /cashadvance/v4/ (v4.1 endpoints do not exist; live spec is v4) - Travel Profile v2 summary has no Active/Status query param — drop the filter from tool, types, and block - Report Comments v4 contextType is TRAVELER or PROXY only (NOT MANAGER) — move create_report_comment + list_report_comments into the TRAVELER/PROXY context group - Trip v1.1 query keys: userid_type / userid_value / ItemsPerPage / Page (snake/Pascal per docs) — already correct, kept Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Re-verified against live developer.concur.com docs at /api-reference/cash-advance/v4-1.cash-advance.html — only v4.1 endpoints are documented:
- POST /cashadvance/v4.1/cashadvances
- GET /cashadvance/v4.1/cashadvances/{cashAdvanceId}
- POST /cashadvance/v4.1/cashadvances/{cashAdvanceId}/issue
The /cashadvance/v4/ docs page returns 404. Reverts the prior local rollback in 9ef3a11.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
A_PurchaseRequisitionHeaderoutputs, removed phantomto_Textexpand onA_BillingDocument, corrected several response envelope and field nullability declarations across BP / Customer / Supplier / Product / Sales Order / Delivery / Material / Billing groups, fixed Cash Advance API version pathsType of Change
Testing
Tested manually. Live-API-docs validation pass against developer.concur.com and SAP help.sap.com OData specs across all tool groups.
Checklist