Skip to content

Commit 43acf8d

Browse files
committed
fix(connectors): flag WIQL truncation unconditionally; stop swallowing docusign form-data failures
azure-devops: the 20,000-item WIQL ceiling was probed by asking for a matching item with an id beyond the largest returned. That probe is unsound — buildWiql orders by ChangedDate DESC while ids are assigned in creation order, so the highest-id match is almost always inside the returned window. The probe came back empty for genuinely truncated projects, left the listing unflagged, and let deletion reconciliation remove every indexed item outside it. Flag unconditionally instead; the cost is a project sitting exactly at the ceiling not reconciling deletions until a full resync. docusign: fetchFormValues threw on a non-404 status and then caught its own throw, returning []. The earlier fix was a no-op. The catch now rethrows, so a transient failure produces a failed row instead of a permanently incomplete document under a metadata-only hash.
1 parent 3275393 commit 43acf8d

2 files changed

Lines changed: 38 additions & 28 deletions

File tree

apps/sim/connectors/azure-devops/azure-devops.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -541,14 +541,19 @@ function readWorkItemFilters(sourceConfig: Record<string, unknown>): WorkItemFil
541541
/**
542542
* Builds the WIQL query for the configured work-item filters. User-supplied
543543
* values are escaped against WIQL string-literal injection. `lastSyncAt`
544-
* narrows results to items changed since the previous sync, and `idAfter`
545-
* restricts to items with a greater id (used to probe past the 20,000-item
546-
* WIQL cap).
544+
* narrows results to items changed since the previous sync.
547545
*
548-
* A custom WIQL query is used verbatim: neither the incremental changed-date
549-
* filter nor the probe condition can be injected into arbitrary user WIQL
550-
* safely, so custom queries always run as full listings on every sync. Change
551-
* detection still short-circuits unchanged items via the content hash.
546+
* `idAfter` restricts to items with a greater id. It currently has no caller:
547+
* it is the seam for paginating past Azure DevOps' 20,000-item WIQL ceiling by
548+
* ordering on `[System.Id] ASC` and looping until a call returns fewer than
549+
* 20,000 ids. Until that lands, a project at the ceiling is flagged
550+
* {@link https://learn.microsoft.com/azure/devops/boards/queries | truncated}
551+
* so deletion reconciliation cannot act on a partial listing.
552+
*
553+
* A custom WIQL query is used verbatim: the incremental changed-date filter
554+
* cannot be injected into arbitrary user WIQL safely, so custom queries always
555+
* run as full listings on every sync. Change detection still short-circuits
556+
* unchanged items via the content hash.
552557
*/
553558
function buildWiql(filters: WorkItemFilters, lastSyncAt?: Date, idAfter?: number): string {
554559
if (filters.customWiql) return filters.customWiql
@@ -1391,27 +1396,25 @@ async function listWorkItems(
13911396

13921397
if (ids.length >= WIQL_MAX_RESULTS && syncContext) {
13931398
/**
1394-
* The WIQL result filled the 20,000-item cap. Distinguish an exact fit
1395-
* from genuine truncation: for structured filters, probe for any
1396-
* matching item with an id beyond the largest returned one and only
1397-
* flag the listing incomplete when one exists — otherwise deletion
1398-
* reconciliation would be disabled forever for a project with exactly
1399-
* 20,000 matching items. Custom WIQL cannot be probed (no safe clause
1400-
* injection), so it is flagged conservatively.
1399+
* The WIQL result filled the documented 20,000-item ceiling — Azure DevOps
1400+
* truncates there and returns no error ("Query results: Results are
1401+
* truncated at 20,000 items - no error is shown").
1402+
*
1403+
* A previous revision tried to tell an exact fit from real truncation by
1404+
* probing for a matching item with an id beyond the largest returned one.
1405+
* That probe is unsound: {@link buildWiql} orders by `[System.ChangedDate]
1406+
* DESC`, while work-item ids are assigned in creation order, so the
1407+
* highest-id match is the most recently created item and is essentially
1408+
* always inside the most-recently-changed 20,000. The probe therefore
1409+
* returned empty for a genuinely truncated project, left the listing
1410+
* unflagged, and let deletion reconciliation remove every indexed item
1411+
* outside the current window.
1412+
*
1413+
* Flag unconditionally instead. The cost is that a project with exactly
1414+
* 20,000 matching items stops reconciling deletions until a full resync;
1415+
* the cost of the probe was silent data loss on every scheduled sync.
14011416
*/
1402-
let truncated = true
1403-
if (!filters.customWiql) {
1404-
let maxId = 0
1405-
for (const id of ids) {
1406-
if (id > maxId) maxId = id
1407-
}
1408-
const probeWiql = buildWiql(filters, lastSyncAt, maxId)
1409-
const beyond = await queryWorkItemIds(accessToken, organization, project, probeWiql, 1)
1410-
truncated = beyond.length > 0
1411-
}
1412-
if (truncated) {
1413-
syncContext.listingCapped = true
1414-
}
1417+
syncContext.listingCapped = true
14151418
}
14161419
}
14171420

apps/sim/connectors/docusign/docusign.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,18 @@ async function fetchFormValues(
405405
}
406406
return values
407407
} catch (error) {
408+
/**
409+
* Rethrow rather than degrading to `[]`. Returning an empty list here would
410+
* defeat the 404-only rule above: `buildContentHash` is metadata-only, so a
411+
* document stored without its form data computes the identical hash on the
412+
* next sync, classifies `unchanged`, and never recovers the missing section.
413+
* A throw reaches `getDocument`, which the engine records as a failed row.
414+
*/
408415
logger.warn('Failed to fetch DocuSign form data', {
409416
envelopeId,
410417
error: toError(error).message,
411418
})
412-
return []
419+
throw error
413420
}
414421
}
415422

0 commit comments

Comments
 (0)