Commit 38075ad
authored
fix(sap_concur): align the integration with SAP Concur's documented API (#6790)
* fix(sap_concur): align the integration with SAP Concur's documented API
Validated all 70 tools, the block, and both proxy routes against SAP's
published API docs.
Auth:
- add the password and companyUuid to the token cache key so a request
with the wrong password can no longer be served a cached token minted
from someone else's
- wire the documented company-level flow (username = company UUID,
credtype = authtoken) so companyUuid actually scopes a token
- expand the datacenter allowlist to the documented set (adds glz, apj1,
usg, the impl hosts, and the www- twins) and drop the undocumented cn
host; validate the returned geolocation by shape instead of membership
- coalesce concurrent token fetches so a fan-out mints one token
- forward Retry-After so 429 retries pace off Concur's own hint
- handle the errorMessageList, SCIM detail, and legacy Error.Message
shapes instead of falling through to a generic HTTP message
- pin redirects and cap the response body
Block:
- collapse six contextType subBlocks that disagreed on their default, so
a new block no longer seeds MANAGER for every operation
- clamp contextType to each operation's documented set
- stop requiring a userId and contextType that the default operation's
tool does not accept, and scope the receipt fields to the upload ops
- reach six params that had no subBlock, and pass userId on travel
request updates so a stale value cannot impersonate
Tools:
- correct response shapes that resolved to undefined: budget headers,
budget categories, allocations, receipts, SCIM nextCursor, and the
delete endpoints that return a bare boolean
- use the Travel Request Amount schema (currency, not currencyCode)
- narrow the four XML-only travel tools to a documented string payload
and request application/xml
- surface real errors instead of a JSON parse failure when the proxy
returns a non-JSON body
- cap receipt uploads at the documented sizes before downloading
Adds 106 tests covering the token cache, geolocation validation, path
traversal, and error extraction.
* fix(sap_concur): drop the removed forwardId subblock via a migration
Removing the `forwardId` subblock without a migration entry breaks
deployed workflows that still carry a value under that key.
It fed a `concur-forwardid` request header that is documented nowhere in
Concur's Receipts v4 or Image v1 references, so it was never honored.
There is no replacement subblock and the value is an opaque
caller-chosen string rather than a secret, so it is dropped outright.
* fix(sap_concur): stop swallowing upload response-read failures
The upload route caught every error from the bounded response read and
continued down the success path, so a size-limit breach or a stream
failure surfaced as an upstream success with a null or header-only body.
Concur returns Content-Length: 0 on a successful image-only upload, and
readResponseTextWithLimit already returns an empty string for that
without throwing, so dropping the catch keeps the legitimate empty-body
case working while letting real read failures reach the route's handler.
* fix(sap_concur): unblock company auth and correct the body wand prompt
The password grant marked username required, so the company-level flow —
which sends the company UUID as the token username and has no user login
— could not be configured at all, even though the request schema and
token fetch already accept companyUuid without a username. Username is
now optional for that grant and the server-side check reports which of
the two is missing. Relabels the password and companyUuid fields to say
what they carry in the company flow.
The shared body wand prompt also still described several payloads the
way they looked before this branch: quick expenses in PascalCase rather
than v4 camelCase, travel requests and expected expenses using
currencyCode where the Request v4 Amount schema uses currency, the
standard SCIM SearchRequest URN instead of Concur's, startIndex as a
search parameter when it is unsupported, and a cash advance shape that
does not match the documented request. A wand-generated body was
therefore rejected for most of the create operations it covers.
* fix(sap_concur): keep Concur's status when an error body fails to read
Removing the blanket catch from the upload read fixed one failure mode
and introduced its inverse: a cap breach or stream error while reading a
non-success body threw before the route reached the branch that
preserves Concur's status, so an upstream 4xx surfaced as a Sim 500 and
could trigger a retry the caller should not make.
Both routes now split the two cases. On a success status the body is the
result, so a read failure still propagates. On an error status the body
only supplies the message, so a read failure resolves empty and the
upstream status survives, with the message falling back to the generic
HTTP-status form.
Adds 21 tests covering both helpers over success, error, empty-body and
boundary statuses; inverting the status check turns 14 of them red.1 parent 60097c8 commit 38075ad
73 files changed
Lines changed: 3724 additions & 1240 deletions
File tree
- apps
- docs/content/docs/en/integrations
- sim
- app/api/tools/sap_concur
- proxy
- upload
- blocks/blocks
- lib
- integrations
- workflows/migrations
- tools
- generated
- sap_concur
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
7 | 10 | | |
8 | 11 | | |
9 | 12 | | |
10 | 13 | | |
| 14 | + | |
11 | 15 | | |
12 | 16 | | |
| 17 | + | |
13 | 18 | | |
14 | 19 | | |
15 | 20 | | |
| |||
39 | 44 | | |
40 | 45 | | |
41 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
42 | 59 | | |
43 | 60 | | |
44 | 61 | | |
45 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
46 | 93 | | |
47 | 94 | | |
48 | 95 | | |
| |||
54 | 101 | | |
55 | 102 | | |
56 | 103 | | |
57 | | - | |
| 104 | + | |
58 | 105 | | |
59 | 106 | | |
60 | | - | |
| 107 | + | |
61 | 108 | | |
62 | 109 | | |
63 | 110 | | |
| |||
70 | 117 | | |
71 | 118 | | |
72 | 119 | | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
73 | 123 | | |
74 | 124 | | |
75 | 125 | | |
76 | 126 | | |
77 | | - | |
| 127 | + | |
78 | 128 | | |
79 | 129 | | |
80 | 130 | | |
| |||
83 | 133 | | |
84 | 134 | | |
85 | 135 | | |
86 | | - | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
87 | 142 | | |
88 | 143 | | |
89 | 144 | | |
| |||
108 | 163 | | |
109 | 164 | | |
110 | 165 | | |
111 | | - | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
112 | 170 | | |
113 | 171 | | |
114 | 172 | | |
| |||
117 | 175 | | |
118 | 176 | | |
119 | 177 | | |
120 | | - | |
| 178 | + | |
121 | 179 | | |
122 | 180 | | |
123 | 181 | | |
| |||
128 | 186 | | |
129 | 187 | | |
130 | 188 | | |
131 | | - | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
132 | 193 | | |
133 | 194 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
0 commit comments