Skip to content

Commit 0587ab1

Browse files
Merge remote-tracking branch 'origin/staging' into feat/openrouter-kb-fallback
# Conflicts: # apps/sim/tools/generated/tool-ids.ts # apps/sim/tools/generated/tool-metadata.ts # apps/sim/tools/generated/tool-outputs.ts
2 parents f23b9c7 + 2e7e5ae commit 0587ab1

328 files changed

Lines changed: 21866 additions & 5938 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/docs/components/icons.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6048,6 +6048,37 @@ export function RDSIcon(props: SVGProps<SVGSVGElement>) {
60486048
)
60496049
}
60506050

6051+
export function DynatraceIcon(props: SVGProps<SVGSVGElement>) {
6052+
return (
6053+
<svg {...props} viewBox='0 0 89 90' xmlns='http://www.w3.org/2000/svg'>
6054+
<path
6055+
fill='#1496FF'
6056+
d='M29.9672771,7.52412666 C28.8124385,13.6191079 27.4009692,22.6653432 26.6310768,31.8398939 C25.2837652,48.0076335 26.1178152,58.8502844 26.1178152,58.8502844 L3.34183275,80.4714283 C3.34183275,80.4714283 1.60957493,68.3456235 0.711367168,54.680034 C0.198105592,46.211218 0.00563250016,38.7689252 0.00563250016,34.2778864 C0.00563250016,34.0212556 0.133947894,33.7646248 0.133947894,33.507994 C0.133947894,33.1872055 0.518894077,30.1717937 3.47014814,27.3488551 C6.678033,24.2692856 30.3522232,5.72771114 29.9672771,7.52412666 Z'
6057+
/>
6058+
<path
6059+
fill='#1284EA'
6060+
d='M29.9672771,7.52412666 C28.8124385,13.6191079 27.4009692,22.6653432 26.6310768,31.8398939 C26.6310768,31.8398939 1.41710184,28.8244821 0.00563250016,34.9194633 C0.00563250016,34.5986748 0.45473638,30.8775284 3.40599045,28.0545897 C6.6138753,24.9750203 30.3522232,5.72771114 29.9672771,7.52412666 L29.9672771,7.52412666 Z'
6061+
/>
6062+
<path
6063+
fill='#B4DC00'
6064+
d='M0.00563250016,33.4438363 L0.00563250016,34.8553056 C0.262263289,33.7646248 0.711367168,32.9947324 1.60957493,31.7757362 C3.47014814,29.4019014 6.48555991,28.7603244 7.70455615,28.632009 C13.8636951,27.797959 22.9740881,26.8355935 32.1486388,26.5789627 C48.3805361,26.0657011 59.0948715,27.4130128 59.0948715,27.4130128 L81.870854,5.79186884 C81.870854,5.79186884 69.9375224,3.54634944 56.3360906,1.94240701 C47.4181707,0.851726163 39.5909316,0.274306889 35.1640505,0.0176761002 C34.843262,0.0176761002 31.6995349,-0.367270083 28.7482808,2.45566859 C25.540396,5.53523805 9.24434089,20.9972431 2.70025578,27.2205397 C-0.250998288,30.0434784 0.00563250016,33.1872055 0.00563250016,33.4438363 Z'
6065+
/>
6066+
<path
6067+
fill='#6F2DA8'
6068+
d='M81.036804,61.0958038 C74.877665,61.9298538 65.767272,62.956377 56.5927214,63.2771655 C40.360824,63.790427 29.5823309,62.4431154 29.5823309,62.4431154 L6.8063484,84.128417 C6.8063484,84.128417 18.8679955,86.5022518 32.4694272,88.0420366 C40.8099279,89.004402 48.188063,89.5176636 52.6791018,89.7742944 C52.9998903,89.7742944 53.5131519,89.5176636 53.8339404,89.5176636 C54.1547289,89.5176636 57.298456,88.9402443 60.2497101,86.1173056 C63.457595,83.0377362 82.8332195,60.9033307 81.036804,61.0958038 L81.036804,61.0958038 Z'
6069+
/>
6070+
<path
6071+
fill='#591F91'
6072+
d='M81.036804,61.0958038 C74.877665,61.9298538 65.767272,62.956377 56.5927214,63.2771655 C56.5927214,63.2771655 58.3249792,88.6194558 52.229998,89.7101367 C52.5507864,89.7101367 56.7210368,89.5176636 59.6722908,86.6947249 C62.8801757,83.6151554 82.8332195,60.9033307 81.036804,61.0958038 L81.036804,61.0958038 Z'
6073+
/>
6074+
<path
6075+
fill='#73BE28'
6076+
d='M53.5773096,89.8384521 C53.1282057,89.8384521 52.6791018,89.7742944 52.1658403,89.7742944 C53.3206788,89.5818213 54.0905712,89.1968751 55.3095674,88.2986673 C57.7475599,86.5664095 58.5174523,83.5509978 58.7740831,82.3320015 C59.8647639,76.2370203 61.3403909,67.190785 62.0461256,58.0162343 C63.3292796,41.8484946 62.5593872,31.0700015 62.5593872,31.0700015 L85.3353697,9.38469988 C85.3353697,9.38469988 87.0034698,21.4463469 87.9658353,35.1119364 C88.5432545,44.0298563 88.7357276,51.9212531 88.7998853,56.2839765 C88.7998853,56.604765 89.0565161,59.7484921 86.105262,62.5714308 C82.8973772,65.6510003 66.6013221,81.177163 60.1213947,87.4004596 C57.0418252,90.2233983 53.8980981,89.8384521 53.5773096,89.8384521 L53.5773096,89.8384521 Z'
6077+
/>
6078+
</svg>
6079+
)
6080+
}
6081+
60516082
export function DynamoDBIcon(props: SVGProps<SVGSVGElement>) {
60526083
return (
60536084
<svg

apps/docs/components/ui/icon-mapping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import {
6363
DubIcon,
6464
DuckDuckGoIcon,
6565
DynamoDBIcon,
66+
DynatraceIcon,
6667
ElasticsearchIcon,
6768
ElevenLabsIcon,
6869
EmailBisonIcon,
@@ -316,6 +317,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
316317
dub: DubIcon,
317318
duckduckgo: DuckDuckGoIcon,
318319
dynamodb: DynamoDBIcon,
320+
dynatrace: DynatraceIcon,
319321
elasticsearch: ElasticsearchIcon,
320322
elevenlabs: ElevenLabsIcon,
321323
emailbison: EmailBisonIcon,

apps/docs/content/docs/en/integrations/dynatrace.mdx

Lines changed: 601 additions & 0 deletions
Large diffs are not rendered by default.

apps/docs/content/docs/en/integrations/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"dub",
6565
"duckduckgo",
6666
"dynamodb",
67+
"dynatrace",
6768
"elasticsearch",
6869
"elevenlabs",
6970
"emailbison",

apps/sim/app/api/function/execute/route.test.ts

Lines changed: 175 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ describe('Function Execute API Route', () => {
590590
createMockRequest(
591591
'POST',
592592
{
593-
code: 'return environmentVariables.API_KEY',
593+
code: 'return {{API_KEY}}',
594594
envVars: { API_KEY: 'secret-at-the-end' },
595595
workflowId: 'workflow-1',
596596
workspaceId: 'workspace-1',
@@ -686,7 +686,7 @@ describe('Function Execute API Route', () => {
686686
createMockRequest(
687687
'POST',
688688
{
689-
code: 'print("done")',
689+
code: 'print("{{API_KEY}}")',
690690
language: 'python',
691691
workspaceId: 'workspace-1',
692692
envVars: { API_KEY: 'secret-value' },
@@ -821,6 +821,54 @@ describe('Function Execute API Route', () => {
821821
expect(mockExecuteInSandbox).not.toHaveBeenCalled()
822822
})
823823

824+
it('runs with authenticated incomplete mount provenance and marks exported bytes unknown', async () => {
825+
envFlagsMock.isRemoteSandboxEnabled = true
826+
mockExecuteInSandbox.mockResolvedValueOnce({
827+
result: 'raw result',
828+
stdout: '',
829+
sandboxId: 'sandbox-123',
830+
exportedFiles: { '/home/user/output.txt': 'raw output' },
831+
})
832+
833+
const response = await POST(
834+
createMockRequest(
835+
'POST',
836+
{
837+
code: 'print("done")',
838+
language: 'python',
839+
workspaceId: 'workspace-1',
840+
outputs: {
841+
files: [
842+
{
843+
path: 'files/output.txt',
844+
sandboxPath: '/home/user/output.txt',
845+
mimeType: 'text/plain',
846+
},
847+
],
848+
},
849+
[PRIVATE_SECRET_PROVENANCE_FIELD]: {
850+
version: 1,
851+
complete: false,
852+
selections: [],
853+
},
854+
},
855+
{ [PRIVATE_SECRET_PROVENANCE_HEADER]: PRIVATE_SECRET_PROVENANCE_BUNDLE_V1 }
856+
)
857+
)
858+
859+
expect(response.status).toBe(200)
860+
expect((await response.json()).output.result).toEqual(
861+
expect.objectContaining({ fileId: 'wf_output_txt', vfsPath: 'files/output.txt' })
862+
)
863+
expect(mockExecuteInSandbox).toHaveBeenCalledOnce()
864+
expect(mockWriteWorkspaceFileByPath).toHaveBeenCalledWith(
865+
expect.objectContaining({
866+
buffer: Buffer.from('raw output'),
867+
secretProvenance: { status: 'unknown' },
868+
})
869+
)
870+
})
871+
824872
it('does not rewrite a static export path that happens to equal a resolved secret', async () => {
825873
envFlagsMock.isRemoteSandboxEnabled = true
826874
mockExecuteInSandbox.mockResolvedValueOnce({
@@ -853,6 +901,7 @@ describe('Function Execute API Route', () => {
853901
expect(mockWriteWorkspaceFileByPath).toHaveBeenCalledWith(
854902
expect.objectContaining({
855903
target: expect.objectContaining({ path: 'files/report-secret-value.txt' }),
904+
secretProvenance: { status: 'exact', entries: [] },
856905
})
857906
)
858907
expect(JSON.stringify(data)).toContain('files/report-secret-value.txt')
@@ -890,7 +939,7 @@ describe('Function Execute API Route', () => {
890939
)
891940
})
892941

893-
it('keeps a binary export unknown when files were mounted without a provenance envelope', async () => {
942+
it('classifies a binary export exact-empty when ordinary files were mounted without secret provenance', async () => {
894943
envFlagsMock.isRemoteSandboxEnabled = true
895944
mockExecuteInSandbox.mockResolvedValueOnce({
896945
result: 'done',
@@ -919,7 +968,7 @@ describe('Function Execute API Route', () => {
919968

920969
expect(response.status).toBe(200)
921970
expect(mockWriteWorkspaceFileByPath).toHaveBeenCalledWith(
922-
expect.objectContaining({ secretProvenance: { status: 'unknown' } })
971+
expect.objectContaining({ secretProvenance: { status: 'exact', entries: [] } })
923972
)
924973
})
925974

@@ -987,7 +1036,7 @@ describe('Function Execute API Route', () => {
9871036

9881037
const response = await POST(
9891038
createMockRequest('POST', {
990-
code: 'print("done")',
1039+
code: 'print("{{API_KEY}}")',
9911040
language: 'python',
9921041
workspaceId: 'workspace-1',
9931042
envVars: { API_KEY: 'secret-value' },
@@ -2002,6 +2051,117 @@ describe('Function Execute API Route', () => {
20022051
expect(Object.values(request.contextVariables)).not.toContain('must-not-bind')
20032052
})
20042053

2054+
it('does not infer provenance from an unused low-entropy environment value', async () => {
2055+
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result: 'Box eSign', stdout: '' })
2056+
2057+
const response = await POST(
2058+
createMockRequest(
2059+
'POST',
2060+
{
2061+
code: 'return "Box eSign"',
2062+
envVars: { SERVICENOW_PASSWORD: 'x' },
2063+
},
2064+
{ 'x-sim-request-private-tool-metadata': 'resolved-secret-names-v1' }
2065+
)
2066+
)
2067+
const data = await response.json()
2068+
2069+
expect(response.status).toBe(200)
2070+
expect(data.output.result).toBe('Box eSign')
2071+
expect(data.__resolvedSecretNames).toEqual([])
2072+
})
2073+
2074+
it('does not build provenance matchers for unused oversized environment values', async () => {
2075+
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result: 'safe', stdout: '' })
2076+
2077+
const response = await POST(
2078+
createMockRequest(
2079+
'POST',
2080+
{
2081+
code: 'return "safe"',
2082+
envVars: { UNUSED: 'x'.repeat(65 * 1024) },
2083+
},
2084+
{ 'x-sim-request-private-tool-metadata': 'resolved-secret-names-v1' }
2085+
)
2086+
)
2087+
2088+
expect(response.status).toBe(200)
2089+
expect((await response.json()).__resolvedSecretNames).toEqual([])
2090+
})
2091+
2092+
it('conservatively reports only compiled secrets when bounded output classification is exceeded', async () => {
2093+
const result = Array.from({ length: 100_001 }, () => 'ordinary')
2094+
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result, stdout: '' })
2095+
2096+
const response = await POST(
2097+
createMockRequest(
2098+
'POST',
2099+
{
2100+
code: 'const key = {{API_KEY}}; return params.items',
2101+
params: { items: result },
2102+
envVars: { API_KEY: 'secret-value', UNUSED: 'x' },
2103+
},
2104+
{ 'x-sim-request-private-tool-metadata': 'resolved-secret-names-v1' }
2105+
)
2106+
)
2107+
const data = await response.json()
2108+
2109+
expect(response.status).toBe(200)
2110+
expect(response.headers.get('x-sim-private-tool-metadata')).toBe('resolved-secret-names-v1')
2111+
expect(data.output.result).toHaveLength(100_001)
2112+
expect(data.output.result[0]).toBe('ordinary')
2113+
expect(data.__resolvedSecretNames).toEqual(['API_KEY'])
2114+
})
2115+
2116+
it('conservatively reports a compiled secret whose value exceeds matcher capacity', async () => {
2117+
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result: 'ordinary', stdout: '' })
2118+
2119+
const response = await POST(
2120+
createMockRequest(
2121+
'POST',
2122+
{
2123+
code: 'const key = {{OVERSIZED_SECRET}}; return "ordinary"',
2124+
envVars: { OVERSIZED_SECRET: 's'.repeat(64 * 1024 + 1), UNUSED: 'x' },
2125+
},
2126+
{ 'x-sim-request-private-tool-metadata': 'resolved-secret-names-v1' }
2127+
)
2128+
)
2129+
const data = await response.json()
2130+
2131+
expect(response.status).toBe(200)
2132+
expect(data.output.result).toBe('ordinary')
2133+
expect(data.__resolvedSecretNames).toEqual(['OVERSIZED_SECRET'])
2134+
})
2135+
2136+
it('tracks only compiled names when configured secrets share the same value', async () => {
2137+
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result: 'true', stdout: '' })
2138+
const oneResponse = await POST(
2139+
createMockRequest(
2140+
'POST',
2141+
{
2142+
code: 'return {{SECOND}}',
2143+
envVars: { FIRST: 'true', SECOND: 'true' },
2144+
},
2145+
{ 'x-sim-request-private-tool-metadata': 'resolved-secret-names-v1' }
2146+
)
2147+
)
2148+
2149+
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result: 'true', stdout: '' })
2150+
const bothResponse = await POST(
2151+
createMockRequest(
2152+
'POST',
2153+
{
2154+
code: 'const first = {{FIRST}}; return {{SECOND}}',
2155+
envVars: { FIRST: 'true', SECOND: 'true' },
2156+
},
2157+
{ 'x-sim-request-private-tool-metadata': 'resolved-secret-names-v1' }
2158+
)
2159+
)
2160+
2161+
expect((await oneResponse.json()).__resolvedSecretNames).toEqual(['SECOND'])
2162+
expect((await bothResponse.json()).__resolvedSecretNames).toEqual(['FIRST', 'SECOND'])
2163+
})
2164+
20052165
it('lowers missing shell placeholders while preserving comments and heredoc delimiters', async () => {
20062166
envFlagsMock.isRemoteSandboxEnabled = true
20072167
const response = await POST(
@@ -2134,7 +2294,7 @@ describe('Function Execute API Route', () => {
21342294
expect(mockExecuteInSandbox).not.toHaveBeenCalled()
21352295
})
21362296

2137-
it('reports exact secret values returned through placeholders and the environment map', async () => {
2297+
it('reports exact secret values returned through placeholders without inferring direct environment reads', async () => {
21382298
mockExecuteInIsolatedVM.mockResolvedValueOnce({
21392299
result: 'secret-valueother-secret',
21402300
stdout: '',
@@ -2171,14 +2331,15 @@ describe('Function Execute API Route', () => {
21712331
const directData = await directResponse.json()
21722332

21732333
expect(envData.__resolvedSecretNames).toEqual(['ENV_ONLY', 'SHARED'])
2174-
expect(directData.__resolvedSecretNames).toEqual(['API_KEY'])
2334+
expect(directData.output.result).toBe('secret-value')
2335+
expect(directData.__resolvedSecretNames).toEqual([])
21752336
})
21762337

21772338
it.each([
21782339
{ name: 'numeric', secret: '123', result: 123 },
21792340
{ name: 'boolean', secret: 'true', result: true },
21802341
])(
2181-
'records provenance for a typed $name secret returned through direct environment access',
2342+
'preserves a typed $name value returned through legacy direct environment access without inferred provenance',
21822343
async ({ secret, result }) => {
21832344
mockExecuteInIsolatedVM.mockResolvedValueOnce({ result, stdout: '' })
21842345

@@ -2197,11 +2358,11 @@ describe('Function Execute API Route', () => {
21972358
const data = await response.json()
21982359

21992360
expect(data.output.result).toBe(result)
2200-
expect(data.__resolvedSecretNames).toEqual(['API_KEY'])
2361+
expect(data.__resolvedSecretNames).toEqual([])
22012362
}
22022363
)
22032364

2204-
it('reports shell substitutions and exact secret output from direct environment access', async () => {
2365+
it('reports placeholder output without inferring provenance from legacy shell environment access', async () => {
22052366
envFlagsMock.isRemoteSandboxEnabled = true
22062367
mockExecuteShellInSandbox.mockResolvedValueOnce({
22072368
result: null,
@@ -2245,7 +2406,8 @@ describe('Function Execute API Route', () => {
22452406
const directData = await directResponse.json()
22462407

22472408
expect(referencedData.__resolvedSecretNames).toEqual(['API_KEY'])
2248-
expect(directData.__resolvedSecretNames).toEqual(['API_KEY'])
2409+
expect(directData.output.stdout).toBe('secret-value')
2410+
expect(directData.__resolvedSecretNames).toEqual([])
22492411
})
22502412

22512413
it('returns nonzero shell stderr as a visible 422 error and diagnostic output', async () => {
@@ -2289,8 +2451,8 @@ describe('Function Execute API Route', () => {
22892451
)
22902452

22912453
expect(response.status).toBe(200)
2292-
expect((await response.json()).__resolvedSecretNames).toBeUndefined()
2293-
expect(response.headers.get('x-sim-private-tool-metadata')).toBeNull()
2454+
expect((await response.json()).__resolvedSecretNames).toEqual([])
2455+
expect(response.headers.get('x-sim-private-tool-metadata')).toBe('resolved-secret-names-v1')
22942456
expect(mockExecuteInIsolatedVM).toHaveBeenCalled()
22952457
})
22962458

0 commit comments

Comments
 (0)