Skip to content

Commit ffa7acb

Browse files
committed
fix(integrations): isolate QuickBooks record versions
1 parent 2ccb55f commit ffa7acb

13 files changed

Lines changed: 235 additions & 100 deletions

File tree

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

Lines changed: 76 additions & 36 deletions
Large diffs are not rendered by default.

apps/sim/blocks/blocks/quickbooks.ts

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2944,9 +2944,24 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
29442944
},
29452945
syncToken: {
29462946
type: 'string',
2947-
description: 'Latest QuickBooks sync token for a subsequent update',
2947+
description: 'Native QuickBooks SyncToken returned by the mutation',
29482948
condition: { field: 'operation', value: [...MUTATION_OPERATIONS] },
29492949
},
2950+
recordVersion: {
2951+
type: 'string',
2952+
description:
2953+
'QuickBooks record version returned by a mutation or by-ID read; connect this value to the Sync Token input',
2954+
condition: {
2955+
field: 'operation',
2956+
value: [
2957+
...MUTATION_OPERATIONS,
2958+
MASTER_DATA_OPERATION,
2959+
SALES_READ_OPERATION,
2960+
PURCHASING_READ_OPERATION,
2961+
ACCOUNTING_READ_OPERATION,
2962+
],
2963+
},
2964+
},
29502965
voided: {
29512966
type: 'boolean',
29522967
description: 'True when QuickBooks successfully voided the transaction',
@@ -3065,7 +3080,7 @@ export const QuickBooksBlockMeta = {
30653080
icon: QuickBooksIcon,
30663081
title: 'QuickBooks customer onboarding',
30673082
prompt:
3068-
'Build a workflow that receives an approved customer profile, creates the QuickBooks customer, and stores its ID and sync token in a Sim table.',
3083+
'Build a workflow that receives an approved customer profile, creates the QuickBooks customer, and stores its ID and record version in a Sim table.',
30693084
modules: ['tables', 'agent', 'workflows'],
30703085
category: 'operations',
30713086
tags: ['finance', 'customers', 'onboarding'],
@@ -3074,7 +3089,7 @@ export const QuickBooksBlockMeta = {
30743089
icon: QuickBooksIcon,
30753090
title: 'QuickBooks vendor onboarding',
30763091
prompt:
3077-
'Create a workflow that receives approved vendor identity, contact, address, and 1099 details, creates the QuickBooks vendor, and stores the returned ID and sync token.',
3092+
'Create a workflow that receives approved vendor identity, contact, address, and 1099 details, creates the QuickBooks vendor, and stores the returned ID and record version.',
30783093
modules: ['tables', 'agent', 'workflows'],
30793094
category: 'operations',
30803095
tags: ['finance', 'vendors', 'procurement'],
@@ -3083,7 +3098,7 @@ export const QuickBooksBlockMeta = {
30833098
icon: QuickBooksIcon,
30843099
title: 'QuickBooks catalogue maintenance',
30853100
prompt:
3086-
'Build a workflow that reads filtered QuickBooks master data, creates approved non-payroll employees or Service and Non-inventory items, and safely updates exposed fields while retaining returned IDs and sync tokens.',
3101+
'Build a workflow that reads filtered QuickBooks master data, creates approved non-payroll employees or Service and Non-inventory items, and safely updates exposed fields while retaining returned IDs and record versions.',
30873102
modules: ['tables', 'agent', 'workflows'],
30883103
category: 'operations',
30893104
tags: ['finance', 'catalogue', 'operations'],
@@ -3101,7 +3116,7 @@ export const QuickBooksBlockMeta = {
31013116
icon: QuickBooksIcon,
31023117
title: 'QuickBooks estimate preparation',
31033118
prompt:
3104-
'Build a workflow that receives an approved customer quote and line items, creates a QuickBooks estimate, and stores its ID and sync token for controlled revisions.',
3119+
'Build a workflow that receives an approved customer quote and line items, creates a QuickBooks estimate, and stores its ID and record version for controlled revisions.',
31053120
modules: ['tables', 'agent', 'workflows'],
31063121
category: 'operations',
31073122
tags: ['finance', 'estimates', 'sales'],
@@ -3110,7 +3125,7 @@ export const QuickBooksBlockMeta = {
31103125
icon: QuickBooksIcon,
31113126
title: 'QuickBooks invoice creation and delivery',
31123127
prompt:
3113-
'Create a workflow that validates approved customer and item IDs, creates a QuickBooks invoice, stores its ID and sync token, then—after explicit approval—emails it or downloads its PDF for controlled delivery and archiving.',
3128+
'Create a workflow that validates approved customer and item IDs, creates a QuickBooks invoice, stores its ID and record version, then—after explicit approval—emails it or downloads its PDF for controlled delivery and archiving.',
31143129
modules: ['tables', 'agent', 'workflows'],
31153130
category: 'operations',
31163131
tags: ['finance', 'invoices', 'receivables'],
@@ -3164,47 +3179,47 @@ export const QuickBooksBlockMeta = {
31643179
skills: [
31653180
{
31663181
name: 'onboard-quickbooks-customers',
3167-
description: 'Create approved QuickBooks customers and retain their IDs and sync tokens.',
3182+
description: 'Create approved QuickBooks customers and retain their IDs and record versions.',
31683183
content:
3169-
'# Onboard QuickBooks Customers\n\n## Steps\n1. Validate the approved customer identity and contact details.\n2. Use Create Customer with a unique display name.\n3. Store the returned `recordId` and `syncToken` for later updates.\n\n## Output\nReturn the created customer, ID, and sync token. Report duplicate-name faults for human review.',
3184+
'# Onboard QuickBooks Customers\n\n## Steps\n1. Validate the approved customer identity and contact details.\n2. Use Create Customer with a unique display name.\n3. Store the returned `recordId` and `recordVersion`; connect `recordVersion` to the Sync Token input for later updates.\n\n## Output\nReturn the created customer, ID, and record version. Report duplicate-name faults for human review.',
31703185
},
31713186
{
31723187
name: 'onboard-quickbooks-vendors',
31733188
description: 'Create approved QuickBooks vendors with bounded contact and 1099 fields.',
31743189
content:
3175-
'# Onboard QuickBooks Vendors\n\n## Steps\n1. Validate the approved vendor identity, contact, address, and optional 1099 status.\n2. Use Create Vendor.\n3. Store the returned `recordId` and `syncToken`.\n\n## Output\nReturn the created vendor and identifiers. Do not claim to merge vendors or administer tax identifiers.',
3190+
'# Onboard QuickBooks Vendors\n\n## Steps\n1. Validate the approved vendor identity, contact, address, and optional 1099 status.\n2. Use Create Vendor.\n3. Store the returned `recordId` and `recordVersion`; connect `recordVersion` to the Sync Token input for later updates.\n\n## Output\nReturn the created vendor and identifiers. Do not claim to merge vendors or administer tax identifiers.',
31763191
},
31773192
{
31783193
name: 'maintain-products-and-services',
31793194
description: 'Create supported items or update exposed item fields without changing types.',
31803195
content:
3181-
'# Maintain QuickBooks Products and Services\n\n## Steps\n1. Read Account master data to obtain approved account IDs.\n2. Create a Service or Non-inventory Item, or update exposed basic fields without changing the existing item Type.\n3. Store the latest item ID and sync token.\n\n## Output\nReturn the native Item record. Do not claim to create Inventory, Category, or Group items or manage their specialized fields.',
3196+
'# Maintain QuickBooks Products and Services\n\n## Steps\n1. Read Account master data to obtain approved account IDs.\n2. Create a Service or Non-inventory Item, or update exposed basic fields without changing the existing item Type.\n3. Store the latest item ID and record version; connect the record version to the Sync Token input for updates.\n\n## Output\nReturn the native Item record and record version. Do not claim to create Inventory, Category, or Group items or manage their specialized fields.',
31823197
},
31833198
{
31843199
name: 'record-quickbooks-accounting-adjustments',
31853200
description: 'Post approved balanced journal entries, record deposits, and review transfers.',
31863201
content:
3187-
'# Record QuickBooks Accounting Adjustments\n\n## Steps\n1. Read the approved account IDs from Master Data.\n2. For a journal entry, verify that positive debit and credit lines balance and require explicit posting confirmation; for a deposit, verify the destination and source account IDs.\n3. Store the returned `recordId` and `syncToken`; use Read Accounting Transactions to review journal entries, deposits, or read-only transfers.\n4. Run an approved Trial Balance or financial statement on cash or accrual basis when an accountant requests post-adjustment review.\n\n## Output\nReturn the native accounting transaction and identifiers plus the native report hierarchy when requested. Do not claim to create transfers, replace transaction lines, or administer currencies.',
3202+
'# Record QuickBooks Accounting Adjustments\n\n## Steps\n1. Read the approved account IDs from Master Data.\n2. For a journal entry, verify that positive debit and credit lines balance and require explicit posting confirmation; for a deposit, verify the destination and source account IDs.\n3. Store the returned `recordId` and `recordVersion`; connect `recordVersion` to the Sync Token input for later updates, and use Read Accounting Transactions to review journal entries, deposits, or read-only transfers.\n4. Run an approved Trial Balance or financial statement on cash or accrual basis when an accountant requests post-adjustment review.\n\n## Output\nReturn the native accounting transaction and identifiers plus the native report hierarchy when requested. Do not claim to create transfers, replace transaction lines, or administer currencies.',
31883203
},
31893204
{
31903205
name: 'prepare-quickbooks-estimates',
31913206
description: 'Create and revise bounded QuickBooks estimates from approved quote details.',
31923207
content:
3193-
'# Prepare QuickBooks Estimates\n\n## Steps\n1. Validate the customer, item IDs, amounts, and dates.\n2. Use Create Estimate with bounded item or description lines.\n3. For a revision, use the estimate ID and latest `syncToken` with Update Estimate.\n\n## Output\nReturn the native Estimate, ID, and latest sync token. Do not claim to email or accept the estimate.',
3208+
'# Prepare QuickBooks Estimates\n\n## Steps\n1. Validate the customer, item IDs, amounts, and dates.\n2. Use Create Estimate with bounded item or description lines.\n3. For a revision, use the estimate ID and latest `recordVersion` as the Update Estimate Sync Token input.\n\n## Output\nReturn the native Estimate, ID, and latest record version. Do not claim to email or accept the estimate.',
31943209
},
31953210
{
31963211
name: 'create-quickbooks-invoices',
31973212
description:
31983213
'Create approved QuickBooks invoices and explicitly deliver or archive their documents.',
31993214
content:
3200-
'# Create and Deliver QuickBooks Invoices\n\n## Steps\n1. Validate the approved customer, item IDs, positive amounts, and optional dates.\n2. Use Create Invoice with at least one bounded line.\n3. Store the returned `recordId` and `syncToken`.\n4. Only after explicit approval, use Email Transaction for one recipient or Download Transaction PDF for controlled archiving.\n5. Use Add Attachment for one approved receipt or audit note when needed, and Read Attachments to verify the metadata.\n\n## Output\nReturn the native Invoice and identifiers plus any sent status, downloaded file, or attachment ID. Do not claim bulk email, automatic resend, attachment deletion, or automatic payment collection.',
3215+
'# Create and Deliver QuickBooks Invoices\n\n## Steps\n1. Validate the approved customer, item IDs, positive amounts, and optional dates.\n2. Use Create Invoice with at least one bounded line.\n3. Store the returned `recordId` and `recordVersion`; connect `recordVersion` to the Sync Token input for later updates.\n4. Only after explicit approval, use Email Transaction for one recipient or Download Transaction PDF for controlled archiving.\n5. Use Add Attachment for one approved receipt or audit note when needed, and Read Attachments to verify the metadata.\n\n## Output\nReturn the native Invoice and identifiers plus any sent status, downloaded file, or attachment ID. Do not claim bulk email, automatic resend, attachment deletion, or automatic payment collection.',
32013216
},
32023217
{
32033218
name: 'record-quickbooks-payables',
32043219
description:
32053220
'Create standalone or PO-linked bills and record bounded payments to approved Bill IDs.',
32063221
content:
3207-
'# Record QuickBooks Payables\n\n## Steps\n1. Validate the vendor, expense lines, and optional A/P account.\n2. For PO-linked billing, use Read Purchasing Transactions by ID and copy each approved Purchase Order `Line[].Id` into the matching Create Bill line with its PO ID.\n3. Use Create Bill, store its ID and sync token, and inspect `linkingSucceeded` and `missingLinks`; QuickBooks may create the Bill while omitting an invalid or unavailable link.\n4. When payment is separately approved, use Create Bill Payment with bounded Bill allocations whose amounts equal the payment total.\n5. Run A/P Aging Summary or Detail with supported vendor, department, date, and aging controls for accountant review.\n\n## Output\nAlways return the created Bill ID and linkage result. Preserve the native aging report when requested. Never imply that a missing link prevented Bill creation, and never create a payment implicitly.',
3222+
'# Record QuickBooks Payables\n\n## Steps\n1. Validate the vendor, expense lines, and optional A/P account.\n2. For PO-linked billing, use Read Purchasing Transactions by ID and copy each approved Purchase Order `Line[].Id` into the matching Create Bill line with its PO ID.\n3. Use Create Bill, store its ID and record version, and inspect `linkingSucceeded` and `missingLinks`; QuickBooks may create the Bill while omitting an invalid or unavailable link.\n4. When payment is separately approved, use Create Bill Payment with bounded Bill allocations whose amounts equal the payment total.\n5. Run A/P Aging Summary or Detail with supported vendor, department, date, and aging controls for accountant review.\n\n## Output\nAlways return the created Bill ID, record version, and linkage result. Preserve the native aging report when requested. Never imply that a missing link prevented Bill creation, and never create a payment implicitly.',
32083223
},
32093224
{
32103225
name: 'analyze-quickbooks-financial-reports',

apps/sim/lib/core/security/redaction.test.ts

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ describe('isSensitiveKey', () => {
5454
expect(isSensitiveKey('refresh_token')).toBe(true)
5555
expect(isSensitiveKey('auth_token')).toBe(true)
5656
expect(isSensitiveKey('accessToken')).toBe(true)
57-
expect(isSensitiveKey('sessionToken')).toBe(true)
58-
expect(isSensitiveKey('webIdentityToken')).toBe(true)
59-
expect(isSensitiveKey('verificationToken')).toBe(true)
60-
expect(isSensitiveKey('githubToken')).toBe(true)
6157
})
6258

6359
it.concurrent('should match secret variations', () => {
@@ -112,28 +108,9 @@ describe('isSensitiveKey', () => {
112108
it.concurrent('should match ssh passphrases', () => {
113109
expect(isSensitiveKey('passphrase')).toBe(true)
114110
})
115-
116-
it.concurrent('should not allow arbitrary keys ending in workflow token names', () => {
117-
expect(isSensitiveKey('asyncToken')).toBe(true)
118-
expect(isSensitiveKey('homepageToken')).toBe(true)
119-
})
120111
})
121112

122113
describe('non-sensitive keys (no false positives)', () => {
123-
it.concurrent('should bypass the exact allowlisted non-secret token fields', () => {
124-
expect(isSensitiveKey('nextPageToken')).toBe(false)
125-
expect(isSensitiveKey('syncToken')).toBe(false)
126-
expect(isSensitiveKey('SyncToken')).toBe(false)
127-
expect(isSensitiveKey('subjectFromWebIdentityToken')).toBe(false)
128-
})
129-
130-
it.concurrent('should keep the allowlist exact rather than suffix-based', () => {
131-
expect(isSensitiveKey('nextSyncToken')).toBe(true)
132-
expect(isSensitiveKey('pageToken')).toBe(true)
133-
expect(isSensitiveKey('nextToken')).toBe(true)
134-
expect(isSensitiveKey('webIdentityToken')).toBe(true)
135-
})
136-
137114
it.concurrent('should not match keys with sensitive words as prefix only', () => {
138115
expect(isSensitiveKey('tokenCount')).toBe(false)
139116
expect(isSensitiveKey('tokenizer')).toBe(false)
@@ -546,24 +523,6 @@ describe('redactApiKeys', () => {
546523
expect(result.config.normalField).toBe('normal-value')
547524
})
548525

549-
it.concurrent('should preserve allowlisted token fields while redacting credentials', () => {
550-
const result = redactApiKeys({
551-
nextPageToken: 'page-2',
552-
subjectFromWebIdentityToken: 'arn-subject',
553-
record: { Id: '42', SyncToken: '3' },
554-
accessToken: 'access-secret',
555-
sessionToken: 'session-secret',
556-
})
557-
558-
expect(result).toEqual({
559-
nextPageToken: 'page-2',
560-
subjectFromWebIdentityToken: 'arn-subject',
561-
record: { Id: '42', SyncToken: '3' },
562-
accessToken: REDACTED_MARKER,
563-
sessionToken: REDACTED_MARKER,
564-
})
565-
})
566-
567526
it.concurrent('should redact sensitive keys in arrays', () => {
568527
const arr = [{ apiKey: 'secret-key-1' }, { apiKey: 'secret-key-2' }]
569528

apps/sim/lib/core/security/redaction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { filterUserFileForDisplay, isUserFile } from '@/lib/core/utils/user-file
77
export const REDACTED_MARKER = '[REDACTED]'
88
export const TRUNCATED_MARKER = '[TRUNCATED]'
99

10-
const BYPASS_REDACTION_KEYS = new Set(['nextpagetoken', 'synctoken', 'subjectfromwebidentitytoken'])
10+
const BYPASS_REDACTION_KEYS = new Set(['nextpagetoken'])
1111

1212
/** Keys that contain large binary/encoded data that should be truncated in logs */
1313
const LARGE_DATA_KEYS = new Set(['base64'])

apps/sim/tools/generated/tool-outputs.ts

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)