Skip to content

Commit 9c1b2f5

Browse files
waleedlatif1claude
andcommitted
fix(cloudtrail): make the default lookup configuration runnable
A dropdown with no value() seeds and persists its first option, so attributeKey auto-selected Username while attributeValue stayed empty and the both-or-neither guard threw before any AWS call — a freshly dropped block could not run. Adds a selectable no-filter sentinel, applies the same fix to SSM parameterTier (which silently forced Standard over the account default), and records SQS's authMode so the catalog stops reporting it as unauthenticated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LJV2dCcAYvf1JuxquCMZAd
1 parent c192be3 commit 9c1b2f5

9 files changed

Lines changed: 230 additions & 2 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* @vitest-environment node
3+
*
4+
* A dropdown subBlock with no `value()` seeds and persists its first selectable option,
5+
* so a block's *default* configuration is not necessarily one that runs. These tests
6+
* exercise the default the user actually gets on drop, which no other suite covers.
7+
*/
8+
import { describe, expect, it } from 'vitest'
9+
import { CloudTrailBlock } from '@/blocks/blocks/cloudtrail'
10+
11+
type SubBlock = (typeof CloudTrailBlock.subBlocks)[number]
12+
13+
function subBlock(id: string): SubBlock {
14+
const found = CloudTrailBlock.subBlocks.find((block) => block.id === id)
15+
if (!found) throw new Error(`missing subBlock ${id}`)
16+
return found
17+
}
18+
19+
/** Mirrors the dropdown's seeding rule: an explicit `value()` wins, else the first option. */
20+
function seededValue(block: SubBlock): unknown {
21+
if (typeof block.value === 'function') return block.value()
22+
const options = block.options
23+
if (!Array.isArray(options)) return undefined
24+
const first = options[0] as { id?: unknown } | undefined
25+
return first?.id
26+
}
27+
28+
describe('CloudTrail block defaults', () => {
29+
it('seeds no lookup filter attribute, so the default run is unfiltered', () => {
30+
expect(seededValue(subBlock('attributeKey'))).toBe('')
31+
})
32+
33+
it('offers a selectable no-filter option so the choice can be undone', () => {
34+
const options = subBlock('attributeKey').options as Array<{ id: string; label: string }>
35+
expect(options[0]).toMatchObject({ id: '' })
36+
expect(options.filter((option) => option.id === '')).toHaveLength(1)
37+
})
38+
39+
it('does not throw on the configuration a freshly dropped block produces', () => {
40+
const params = {
41+
operation: 'lookup_events',
42+
awsRegion: 'us-east-1',
43+
awsAccessKeyId: 'AKIAIOSFODNN7EXAMPLE',
44+
awsSecretAccessKey: 'secret',
45+
attributeKey: seededValue(subBlock('attributeKey')),
46+
attributeValue: '',
47+
}
48+
49+
expect(() => CloudTrailBlock.tools.config?.params?.(params)).not.toThrow()
50+
})
51+
52+
it('still rejects a half-supplied filter', () => {
53+
const params = {
54+
operation: 'lookup_events',
55+
awsRegion: 'us-east-1',
56+
awsAccessKeyId: 'AKIAIOSFODNN7EXAMPLE',
57+
awsSecretAccessKey: 'secret',
58+
attributeKey: 'Username',
59+
attributeValue: '',
60+
}
61+
62+
expect(() => CloudTrailBlock.tools.config?.params?.(params)).toThrow(/filter/i)
63+
})
64+
})

apps/sim/blocks/blocks/cloudtrail.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,16 @@ export const CloudTrailBlock: BlockConfig<
171171
id: 'attributeKey',
172172
title: 'Filter By',
173173
type: 'dropdown',
174+
/**
175+
* Every LookupEvents attribute is optional, so an unfiltered Region-wide lookup is
176+
* the correct default. A dropdown with no `value()` seeds and persists its first
177+
* selectable option, which would pair an attribute with an empty value and trip the
178+
* both-or-neither guard before any AWS call — so the no-filter sentinel has to be a
179+
* real, selectable option the user can also return to.
180+
*/
181+
value: () => '',
174182
options: [
183+
{ label: 'No filter', id: '' },
175184
{ label: 'User Name', id: 'Username' },
176185
{ label: 'Event Name', id: 'EventName' },
177186
{ label: 'Event Source', id: 'EventSource' },

apps/sim/blocks/blocks/sqs.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getErrorMessage } from '@sim/utils/errors'
22
import { SQSIcon } from '@/components/icons'
33
import type { BlockConfig, BlockMeta } from '@/blocks/types'
4-
import { IntegrationType } from '@/blocks/types'
4+
import { AuthMode, IntegrationType } from '@/blocks/types'
55
import type { SqsResponse } from '@/tools/sqs/types'
66

77
export const SQSBlock: BlockConfig<SqsResponse> = {
@@ -16,6 +16,7 @@ export const SQSBlock: BlockConfig<SqsResponse> = {
1616
bgColor: 'linear-gradient(45deg, #2E27AD 0%, #527FFF 100%)',
1717
iconColor: '#527FFF',
1818
icon: SQSIcon,
19+
authMode: AuthMode.ApiKey,
1920
canvasPresentation: {
2021
defaultTitle: 'Amazon SQS',
2122
sentences: {

apps/sim/blocks/blocks/ssm.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,15 @@ export const SSMBlock: BlockConfig<SsmSendCommandResponse> = {
492492
id: 'parameterTier',
493493
title: 'Parameter Tier',
494494
type: 'dropdown',
495+
/**
496+
* `Tier` is optional, and omitting it lets the account's own default apply —
497+
* which may be Intelligent-Tiering. A dropdown with no `value()` seeds and
498+
* persists its first option, so without this sentinel the block would silently
499+
* force `Standard` on every write.
500+
*/
501+
value: () => '',
495502
options: [
503+
{ label: 'Account default', id: '' },
496504
{ label: 'Standard', id: 'Standard' },
497505
{ label: 'Advanced', id: 'Advanced' },
498506
{ label: 'Intelligent-Tiering', id: 'Intelligent-Tiering' },

gate-checks1.txt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
=== api-validation ===
2+
apps/sim raw same-origin /api/ fetch() callsites: 0
3+
apps/sim raw same-origin /api/ fetch() exemptions (annotated): 19
4+
as unknown as double-casts (non-test): 6
5+
as unknown as double-cast exemptions (annotated): 54
6+
route files with raw await request.json() reads: 5 (baseline 5)
7+
route raw await request.json() reads (callsites): 5
8+
route raw await request.json() annotated exemptions: 1
9+
contract untyped response schemas (z.unknown / z.object({}).passthrough / z.record): 0
10+
contract untyped response annotated exemptions: 21
11+
audit annotations missing reason: 0
12+
raw fetch examples:
13+
same-origin /api/ fetch examples:
14+
double-cast examples:
15+
apps/sim/tools/hosting.ts:9 const value = (params as unknown as Record<string, unknown>)[condition.field]
16+
apps/sim/executor/utils/errors.ts:203 const candidate = current as unknown as { statusCode?: unknown }
17+
apps/sim/executor/utils/errors.ts:286 const attached = error as unknown as AttachedBlockContext
18+
packages/logger/src/index.ts:149 errorObj[key] = (error as unknown as Record<string, unknown>)[key]
19+
packages/ts-sdk/src/index.ts:511 const errorData = (await response.json().catch(() => ({}))) as unknown as any
20+
packages/ts-sdk/src/index.ts:687 const errorData = (await response.json().catch(() => ({}))) as unknown as any
21+
raw await request.json() examples:
22+
apps/sim/app/api/organizations/route.ts:93 const rawBody = await request.json().catch(() => ({}))
23+
apps/sim/app/api/copilot/chat/abort/route.ts:40 const body = await request.json().catch((err) => {
24+
apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts:45 payload = await request.json()
25+
apps/sim/app/api/workspaces/[id]/route.ts:245 const rawBody = await request.json().catch(() => ({}))
26+
apps/sim/app/api/billing/portal/route.ts:24 const body = await request.json().catch(() => ({}))
27+
untyped response schema examples:
28+
annotations missing reason (must be 0 for --enforce-boundary-baseline):
29+
annotation forms: `// boundary-raw-fetch: <reason>` (raw fetch in client hook OR same-origin /api/ fetch outside an API route handler), `// double-cast-allowed: <reason>` (double-cast), `// boundary-raw-json: <reason>` (raw request.json read), `// untyped-response: <reason>` (z.unknown() / z.object({}).passthrough() / z.record(z.string(), z.unknown()) response schema)
30+
31+
API validation audit passed.
32+
EXIT:0
33+
=== canvas-sentences ===
34+
$ bun run apps/sim/scripts/check-canvas-sentences.ts --require-coverage
35+
✓ Canvas sentence check passed (346 block(s))
36+
37+
Coverage: 5648/5648 operations (100%) across 346/346 blocks
38+
EXIT:0
39+
=== docs:check ===
40+
Getting info for tool: zoom_delete_meeting
41+
Getting info for tool: zoom_get_meeting_invitation
42+
Getting info for tool: zoom_list_recordings
43+
Getting info for tool: zoom_get_meeting_recordings
44+
Getting info for tool: zoom_delete_recording
45+
Getting info for tool: zoom_list_past_participants
46+
Getting info for tool: zoominfo_search_companies
47+
Getting info for tool: zoominfo_search_contacts
48+
Getting info for tool: zoominfo_enrich_companies
49+
Getting info for tool: zoominfo_enrich_contacts
50+
Getting info for tool: zoominfo_search_intent
51+
Getting info for tool: zoominfo_search_news
52+
Generating trigger documentation...
53+
✓ Loaded full config for 403 triggers
54+
Skipping trigger provider: generic
55+
Skipping trigger provider: slack
56+
Skipping trigger provider: table
57+
Skipping trigger provider: rss
58+
✓ Trigger sections merged into 61 integration pages
59+
✓ Generated integration docs are in sync
60+
EXIT:0

gate-checks2.txt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
=== audits ===
2+
✓ check:trigger-block-cycle (100ms)
3+
✓ check:cli-api (708ms)
4+
✓ check:realtime-prune (752ms)
5+
✓ check:tool-registry-boundary (550ms)
6+
✓ check:fork-dependent-coverage (780ms)
7+
✓ check:block-successors (898ms)
8+
✓ check:api-contract-routes (1287ms)
9+
✓ check:tool-param-reachability (1002ms)
10+
✓ check:bare-icons (118ms)
11+
✓ check:egress-boundary (1687ms)
12+
✓ check:icon-paths (27ms)
13+
✓ check:canonical-index (2144ms)
14+
✓ check:icon-path-precision (482ms)
15+
✓ check:byok-providers (960ms)
16+
✓ check:spec-example-ids (22ms)
17+
✓ check:canvas-sentences (1205ms)
18+
✓ check:skills (27ms)
19+
✓ check:react-query (1772ms)
20+
✓ check:api-validation:strict (2537ms)
21+
✓ check:desktop-ipc (31ms)
22+
✓ check:desktop-bridge (138ms)
23+
✓ deployment-config:check (74ms)
24+
✓ check:script-tests (386ms)
25+
✓ check:zustand-v5 (2209ms)
26+
✓ agent-stream-docs:check (35ms)
27+
✓ check:route-verbs (524ms)
28+
✓ integration-catalog:check (562ms)
29+
✓ check:pending-drop-tables (2786ms)
30+
✓ check:native-typecheck (1443ms)
31+
✓ tool-metadata:check (1061ms)
32+
✓ check:utils (2669ms)
33+
✓ check:sql-date-binding (3309ms)
34+
✓ check:client-boundary (3070ms)
35+
✓ check:source-text (1658ms)
36+
✓ check:import-specifiers (3817ms)
37+
✓ check:tool-request-boundary (5110ms)
38+
✓ docs:check (2700ms)
39+
✓ check:openapi (6280ms)
40+
41+
45 audits in 6.3s wall (56.3s serial, 14-way)
42+
EXIT:0
43+
=== lint ===
44+
@sim/workflow-renderer:lint: Checked 41 files in 103ms. No fixes applied.
45+
@sim/platform-authz:lint: cache hit, replaying logs 73395b4e7eeb68f3
46+
@sim/platform-authz:lint: $ biome check --write --unsafe .
47+
@sim/platform-authz:lint: Checked 7 files in 28ms. No fixes applied.
48+
@sim/desktop:lint: cache hit, replaying logs b091199e60e068ec
49+
@sim/desktop:lint: $ biome check --write --unsafe .
50+
@sim/desktop:lint: Checked 151 files in 472ms. No fixes applied.
51+
@sim/auth:lint: cache hit, replaying logs 7127fd081aa8ea29
52+
@sim/auth:lint: $ biome check --write --unsafe .
53+
@sim/auth:lint: Checked 4 files in 53ms. No fixes applied.
54+
@sim/workflow-persistence:lint: cache hit, replaying logs f95340178462088d
55+
@sim/workflow-persistence:lint: $ biome check --write --unsafe .
56+
@sim/workflow-persistence:lint: Checked 11 files in 35ms. No fixes applied.
57+
@sim/audit:lint: cache hit, replaying logs a6444e9df75a5204
58+
@sim/audit:lint: $ biome check --write --unsafe .
59+
@sim/audit:lint: Checked 9 files in 40ms. No fixes applied.
60+
docs:lint: cache hit, replaying logs 565d1a6fd3549e13
61+
@sim/realtime:lint: cache hit, replaying logs 2b83130fbd406515
62+
@sim/realtime:lint: $ biome check --write --unsafe .
63+
@sim/realtime:lint: Checked 51 files in 206ms. No fixes applied.
64+
docs:lint: $ biome check --write --unsafe .
65+
docs:lint: Checked 111 files in 183ms. No fixes applied.
66+
@sim/app:lint: cache hit, replaying logs e90a315e08073392
67+
@sim/app:lint: $ biome check --write --unsafe .
68+
@sim/app:lint: Checked 16090 files in 4s. No fixes applied.
69+
70+
Tasks: 26 successful, 26 total
71+
Cached: 26 cached, 26 total
72+
Time: 359ms >>> FULL TURBO
73+
74+
EXIT:0

gate-typecheck.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
$ tsc --noEmit
2+
EXIT:0

gate-vitest.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
RUN v4.1.9 /private/tmp/aws-all/apps/sim
3+
4+
5+
Test Files 31 passed (31)
6+
Tests 988 passed (988)
7+
Start at 19:12:37
8+
Duration 2.93s (transform 3.36s, setup 3.42s, import 3.73s, tests 3.06s, environment 181ms)
9+
10+
EXIT:0

packages/deployment-config/src/integrations.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@
11261126
"operationCount": 21,
11271127
"triggers": [],
11281128
"triggerCount": 0,
1129-
"authType": "none",
1129+
"authType": "api-key",
11301130
"category": "tools",
11311131
"integrationType": "devops",
11321132
"tags": ["cloud", "messaging", "automation"]

0 commit comments

Comments
 (0)