From 9244b0ad13aac83d780d9a8f446f0ed93af83b28 Mon Sep 17 00:00:00 2001 From: Daniel Sklyar Date: Thu, 23 Jul 2026 16:33:02 -0700 Subject: [PATCH 1/3] feat(mcp-server-consent): add consent triage filters and cookie occurrences sort Adds agent-facing triage capabilities to the consent inventory tools: - consent_list_data_flows: unmappedOnly (orphaned/unmapped approved flows via service=""), type (DataFlowScope, e.g. CSP), and minOccurrences filters - consent_list_cookies: minOccurrences filter and occurrences sort - CookieOrderField gains Occurrences (mirrors backend cm-types change) - Clarify showZeroActivity so default NEEDS_REVIEW totals reconcile with consent_get_inventory_stats needReviewCount Closes ZEL-8105 --- .changeset/consent-triage-filters.md | 6 ++ .../src/tools/consent_list_cookies.ts | 25 ++++++- .../src/tools/consent_list_data_flows.ts | 39 ++++++++++- .../mcp-server-consent/tests/consent.test.ts | 68 +++++++++++++++++++ packages/privacy-types/src/consentManager.ts | 2 + schema.graphql | 1 + 6 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 .changeset/consent-triage-filters.md diff --git a/.changeset/consent-triage-filters.md b/.changeset/consent-triage-filters.md new file mode 100644 index 000000000..ad5a40c9f --- /dev/null +++ b/.changeset/consent-triage-filters.md @@ -0,0 +1,6 @@ +--- +"@transcend-io/mcp-server-consent": minor +"@transcend-io/privacy-types": patch +--- + +Add consent triage filters and sorting: `unmappedOnly` (orphaned/unmapped approved data flows), `type` (data flow scope, e.g. CSP), and `minOccurrences` on `consent_list_data_flows`; `minOccurrences` and `occurrences` sorting on `consent_list_cookies`. Clarify `showZeroActivity` semantics so the default `NEEDS_REVIEW` totals reconcile with `consent_get_inventory_stats`. diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts index 50a5a7cad..ccc37ca0b 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts @@ -26,10 +26,25 @@ export const ListCookiesSchema = z.object({ .nativeEnum(ConsentTrackerStatus) .describe('Filter by status: NEEDS_REVIEW (triage) or LIVE (approved)'), isJunk: z.boolean().optional().describe('Filter by junk status'), - showZeroActivity: z.boolean().optional().describe('Include items with zero activity'), + showZeroActivity: z + .boolean() + .optional() + .describe( + 'Include items with zero activity. Omit (default) so the NEEDS_REVIEW total matches ' + + 'consent_get_inventory_stats needReviewCount; set true for the full triage backlog ' + + 'including never-active cookies.', + ), text: z.string().optional().describe('Search text filter'), service: z.string().optional().describe('Filter by service name'), - orderField: z.nativeEnum(CookieOrderField).optional().describe('Field to sort by'), + minOccurrences: z + .number() + .min(0) + .optional() + .describe('Only return cookies with at least this many occurrences (traffic)'), + orderField: z + .nativeEnum(CookieOrderField) + .optional() + .describe('Field to sort by (e.g. occurrences to rank by traffic)'), orderDirection: z.nativeEnum(OrderDirection).optional().describe('Sort direction: ASC or DESC'), }); export type ListCookiesInput = z.infer; @@ -40,7 +55,9 @@ export function createConsentListCookiesTool(clients: ToolClients) { description: 'List cookies in your consent manager. ' + 'Requires a status filter: NEEDS_REVIEW for triage backlog, LIVE for approved cookies. ' + - 'Returns name, service, tracking purposes, activity (occurrences), junk status, and more.', + 'Returns name, service, tracking purposes, activity (occurrences), junk status, and more. ' + + 'Sort by occurrences (orderField=occurrences, orderDirection=DESC) to surface ' + + 'top-traffic cookies, and use minOccurrences to filter low-traffic noise.', category: 'Consent Management', readOnly: true, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, @@ -53,6 +70,7 @@ export function createConsentListCookiesTool(clients: ToolClients) { showZeroActivity, text, service, + minOccurrences, orderField, orderDirection, }) => { @@ -67,6 +85,7 @@ export function createConsentListCookiesTool(clients: ToolClients) { ...(showZeroActivity !== undefined ? { showZeroActivity } : {}), ...(text ? { text } : {}), ...(service ? { service } : {}), + ...(minOccurrences !== undefined ? { minOccurrences } : {}), }, ...(orderField && orderDirection ? { orderBy: [{ field: orderField, direction: orderDirection }] } diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts index 63c5ca23b..aa4380960 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts @@ -2,6 +2,7 @@ import { createListResult, defineTool, z, type ToolClients } from '@transcend-io import { ConsentTrackerStatus, DataFlowOrderField, + DataFlowScope, OrderDirection, } from '@transcend-io/privacy-types'; import { DATA_FLOWS, type TranscendCliDataFlowsResponse } from '@transcend-io/sdk'; @@ -26,9 +27,32 @@ export const ListDataFlowsSchema = z.object({ .nativeEnum(ConsentTrackerStatus) .describe('Filter by status: NEEDS_REVIEW (triage) or LIVE (approved)'), isJunk: z.boolean().optional().describe('Filter by junk status'), - showZeroActivity: z.boolean().optional().describe('Include items with zero activity'), + showZeroActivity: z + .boolean() + .optional() + .describe( + 'Include items with zero activity. Omit (default) so the NEEDS_REVIEW total matches ' + + 'consent_get_inventory_stats needReviewCount; set true for the full triage backlog ' + + 'including never-active flows.', + ), text: z.string().optional().describe('Search text filter'), service: z.string().optional().describe('Filter by service name'), + unmappedOnly: z + .boolean() + .optional() + .describe( + 'Return only unmapped/orphaned flows with no associated service (catalog integration). ' + + 'Useful with status=LIVE to find approved flows that are not mapped to a service.', + ), + type: z + .nativeEnum(DataFlowScope) + .optional() + .describe('Filter by data flow scope type (e.g. HOST, PATH, REGEX, CSP)'), + minOccurrences: z + .number() + .min(0) + .optional() + .describe('Only return flows with at least this many occurrences (traffic)'), orderField: z.nativeEnum(DataFlowOrderField).optional().describe('Field to sort by'), orderDirection: z.nativeEnum(OrderDirection).optional().describe('Sort direction: ASC or DESC'), }); @@ -40,7 +64,9 @@ export function createConsentListDataFlowsTool(clients: ToolClients) { description: 'List data flows (network requests) in your consent manager. ' + 'Requires a status filter: NEEDS_REVIEW for triage backlog, LIVE for approved flows. ' + - 'Returns value (URL/host), service, tracking purposes, activity (occurrences), and more.', + 'Returns value (URL/host), service, tracking purposes, activity (occurrences), and more. ' + + 'Use unmappedOnly to find approved flows with no service, type to filter by scope ' + + '(e.g. CSP), and minOccurrences to focus on high-traffic flows.', category: 'Consent Management', readOnly: true, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, @@ -53,6 +79,9 @@ export function createConsentListDataFlowsTool(clients: ToolClients) { showZeroActivity, text, service, + unmappedOnly, + type, + minOccurrences, orderField, orderDirection, }) => { @@ -66,7 +95,11 @@ export function createConsentListDataFlowsTool(clients: ToolClients) { ...(isJunk !== undefined ? { isJunk } : {}), ...(showZeroActivity !== undefined ? { showZeroActivity } : {}), ...(text ? { text } : {}), - ...(service ? { service } : {}), + // An empty-string service maps to `catalogIntegrationName IS NULL` + // server-side, so unmappedOnly takes precedence over a named service filter. + ...(unmappedOnly ? { service: '' } : service ? { service } : {}), + ...(type ? { type } : {}), + ...(minOccurrences !== undefined ? { minOccurrences } : {}), }, ...(orderField && orderDirection ? { orderBy: [{ field: orderField, direction: orderDirection }] } diff --git a/packages/mcp/mcp-server-consent/tests/consent.test.ts b/packages/mcp/mcp-server-consent/tests/consent.test.ts index a35823a84..da50b77a5 100644 --- a/packages/mcp/mcp-server-consent/tests/consent.test.ts +++ b/packages/mcp/mcp-server-consent/tests/consent.test.ts @@ -93,6 +93,74 @@ describe('Consent Tools', () => { }); }); + describe('consent_list_data_flows', () => { + const mockBundle = () => + mockGraphql.makeRequest.mockResolvedValueOnce({ + consentManager: { consentManager: { id: 'bundle-1' } }, + }); + + const runDataFlows = async (input: Record) => { + mockBundle(); + mockGraphql.makeRequest.mockResolvedValueOnce({ + dataFlows: { nodes: [], totalCount: 0 }, + }); + const tool = getTools().find((t) => t.name === 'consent_list_data_flows')!; + await tool.handler(tool.zodSchema.parse(input)); + // Second call is the DATA_FLOWS query; grab its variables. + return mockGraphql.makeRequest.mock.calls[1][1]; + }; + + it('sends filterBy.service = "" when unmappedOnly is set (takes precedence over service)', async () => { + const variables = await runDataFlows({ + status: 'LIVE', + unmappedOnly: true, + service: 'Google Analytics', + }); + expect(variables.filterBy.service).toBe(''); + }); + + it('passes through type and minOccurrences filters', async () => { + const variables = await runDataFlows({ + status: 'NEEDS_REVIEW', + type: 'CSP', + minOccurrences: 10, + }); + expect(variables.filterBy).toMatchObject({ type: 'CSP', minOccurrences: 10 }); + }); + + it('omits showZeroActivity by default for NEEDS_REVIEW so counts match inventory stats', async () => { + const variables = await runDataFlows({ status: 'NEEDS_REVIEW' }); + expect(variables.filterBy).not.toHaveProperty('showZeroActivity'); + }); + }); + + describe('consent_list_cookies', () => { + it('forwards orderBy when sorting by occurrences', async () => { + mockGraphql.makeRequest.mockResolvedValueOnce({ + consentManager: { consentManager: { id: 'bundle-1' } }, + }); + mockGraphql.makeRequest.mockResolvedValueOnce({ + cookies: { nodes: [], totalCount: 0 }, + }); + const tool = getTools().find((t) => t.name === 'consent_list_cookies')!; + await tool.handler( + tool.zodSchema.parse({ + status: 'LIVE', + orderField: 'occurrences', + orderDirection: 'DESC', + }), + ); + const variables = mockGraphql.makeRequest.mock.calls[1][1]; + expect(variables.orderBy).toEqual([{ field: 'occurrences', direction: 'DESC' }]); + }); + + it('zodSchema accepts occurrences as an orderField', () => { + const tool = getTools().find((t) => t.name === 'consent_list_cookies')!; + const result = tool.zodSchema.safeParse({ status: 'LIVE', orderField: 'occurrences' }); + expect(result.success).toBe(true); + }); + }); + describe('consent_get_aggregate_analytics', () => { it('queries aggregate analytics with resolved bundle id', async () => { mockGraphql.makeRequest diff --git a/packages/privacy-types/src/consentManager.ts b/packages/privacy-types/src/consentManager.ts index cc044b1df..a59d25bb8 100644 --- a/packages/privacy-types/src/consentManager.ts +++ b/packages/privacy-types/src/consentManager.ts @@ -221,6 +221,8 @@ export const CookieOrderField = makeEnum({ CreatedAt: 'createdAt', /** The time the cookie was updated */ UpdatedAt: 'updatedAt', + /** The number of occurrences (traffic) of this cookie */ + Occurrences: 'occurrences', }); /** Type override */ diff --git a/schema.graphql b/schema.graphql index 8033fc1bb..e9da3d310 100644 --- a/schema.graphql +++ b/schema.graphql @@ -2237,6 +2237,7 @@ enum CookieOrderField { createdAt updatedAt lastDiscoveredAt + occurrences } enum DataFlowType { From 4a80415df76921eef0f5406735654f4d761d84a7 Mon Sep 17 00:00:00 2001 From: Daniel Sklyar Date: Fri, 24 Jul 2026 09:44:33 -0700 Subject: [PATCH 2/3] refactor(mcp-server-consent): migrate GraphQL operations to typed codegen path Author all 13 consent GraphQL operations with the generated graphql() tag in src/graphql.ts and consume the resulting TypedDocumentNodes via makeRequest, replacing the plain gql strings and hand-written response types imported from @transcend-io/sdk. Add consent to the codegen SERVERS list (and drop the stale "consent hits REST endpoints" comment) so operations are validated against the committed schema at compile time. Drop the now-unused @transcend-io/sdk dependency. No change to tool behavior. --- .changeset/consent-typed-graphql-codegen.md | 5 + codegen.ts | 16 +- packages/mcp/mcp-server-consent/package.json | 3 +- .../mcp/mcp-server-consent/src/graphql.ts | 374 ++++++++++++++++++ .../src/resolveAirgapBundleId.ts | 11 +- .../src/tools/consent_bulk_triage.ts | 40 +- .../tools/consent_get_aggregate_analytics.ts | 32 +- .../src/tools/consent_get_analytics_data.ts | 6 +- .../src/tools/consent_get_inventory_stats.ts | 11 +- .../tools/consent_get_timeseries_analytics.ts | 32 +- .../src/tools/consent_list_airgap_bundles.ts | 11 +- .../src/tools/consent_list_cookies.ts | 4 +- .../src/tools/consent_list_data_flows.ts | 4 +- .../src/tools/consent_list_purposes.ts | 5 +- .../src/tools/consent_list_regimes.ts | 5 +- .../src/tools/consent_update_cookies.ts | 19 +- .../src/tools/consent_update_data_flows.ts | 19 +- pnpm-lock.yaml | 9 +- 18 files changed, 470 insertions(+), 136 deletions(-) create mode 100644 .changeset/consent-typed-graphql-codegen.md create mode 100644 packages/mcp/mcp-server-consent/src/graphql.ts diff --git a/.changeset/consent-typed-graphql-codegen.md b/.changeset/consent-typed-graphql-codegen.md new file mode 100644 index 000000000..bcc310230 --- /dev/null +++ b/.changeset/consent-typed-graphql-codegen.md @@ -0,0 +1,5 @@ +--- +"@transcend-io/mcp-server-consent": patch +--- + +Migrate all consent MCP GraphQL operations to the typed `graphql()` codegen path (matching the other MCP servers) instead of importing plain `gql` strings and hand-written response types from `@transcend-io/sdk`. Operations now live in `src/graphql.ts` and are validated against the committed `schema.graphql` at compile time, so schema drift fails `tsc` rather than surfacing as a runtime error. No change to tool behavior. diff --git a/codegen.ts b/codegen.ts index 9bd218dce..08c4c90b6 100644 --- a/codegen.ts +++ b/codegen.ts @@ -18,12 +18,20 @@ const SCHEMA_PATH = './schema.graphql'; /** * GraphQL-backed MCP servers. Each entry corresponds to a package directory * `packages/mcp/mcp-server-${name}` containing a `src/graphql.ts` file with - * embedded operations. The `mcp-server-base`, `mcp-server-consent`, and - * `mcp-server-preferences` packages are intentionally excluded: + * embedded operations. The `mcp-server-base` and `mcp-server-preferences` + * packages are intentionally excluded: * - base has no GraphQL operations of its own. - * - consent/preferences hit REST endpoints, not GraphQL. + * - preferences hits REST endpoints, not GraphQL. */ -const SERVERS = ['admin', 'assessment', 'discovery', 'dsr', 'inventory', 'workflows'] as const; +const SERVERS = [ + 'admin', + 'assessment', + 'consent', + 'discovery', + 'dsr', + 'inventory', + 'workflows', +] as const; const config: CodegenConfig = { schema: SCHEMA_PATH, diff --git a/packages/mcp/mcp-server-consent/package.json b/packages/mcp/mcp-server-consent/package.json index ca938c20d..156a5fd4a 100644 --- a/packages/mcp/mcp-server-consent/package.json +++ b/packages/mcp/mcp-server-consent/package.json @@ -37,10 +37,11 @@ "check:publint": "publint --level warning --strict --pack pnpm" }, "dependencies": { + "@graphql-typed-document-node/core": "catalog:", "@modelcontextprotocol/sdk": "catalog:", "@transcend-io/mcp-server-base": "workspace:*", "@transcend-io/privacy-types": "workspace:*", - "@transcend-io/sdk": "workspace:*", + "graphql": "catalog:", "zod": "catalog:" }, "devDependencies": { diff --git a/packages/mcp/mcp-server-consent/src/graphql.ts b/packages/mcp/mcp-server-consent/src/graphql.ts new file mode 100644 index 000000000..f3c5447cd --- /dev/null +++ b/packages/mcp/mcp-server-consent/src/graphql.ts @@ -0,0 +1,374 @@ +/** + * GraphQL operations for the Consent Management MCP server. + * + * Operations are authored with the generated `graphql()` tag so they are + * validated against the committed `schema.graphql` at compile time — drift + * between an operation (or the variables/enums we send) and the schema fails + * `tsc` rather than surfacing as a runtime error. `TranscendGraphQLBase.makeRequest` + * consumes the returned `TypedDocumentNode` natively. + * + * Run `pnpm codegen` after editing to regenerate `./__generated__/`. + */ +import { graphql } from './__generated__/gql.js'; + +// Input types (generated from the schema) used to build mutation variables. +export type { UpdateOrCreateCookieInput, UpdateDataFlowInput } from './__generated__/graphql.js'; + +export const FetchConsentManagerIdDoc = graphql(/* GraphQL */ ` + query TranscendCliFetchConsentManagerId { + consentManager { + consentManager { + id + } + } + } +`); + +export const FetchConsentManagerDoc = graphql(/* GraphQL */ ` + query TranscendCliFetchConsentManager { + consentManager { + consentManager { + id + bundleURL + testBundleURL + configuration { + domains + consentPrecedence + unknownRequestPolicy + unknownCookiePolicy + syncEndpoint + telemetryPartitioning + signedIabAgreement + syncGroups + partition + } + partition { + partition + } + } + } + } +`); + +export const CookiesDoc = graphql(/* GraphQL */ ` + query TranscendCliCookies( + $input: AirgapBundleInput! + $first: Int! + $offset: Int! + $filterBy: CookiesFiltersInput + $orderBy: [CookieOrder!] + ) { + cookies( + input: $input + first: $first + offset: $offset + filterBy: $filterBy + orderBy: $orderBy + useMaster: false + ) { + totalCount + nodes { + id + name + isRegex + description + trackingPurposes + purposes { + id + name + trackingType + } + frequency + service { + id + title + integrationName + } + isJunk + source + status + owners { + id + name + email + } + teams { + id + name + } + attributeValues { + id + name + attributeKey { + id + name + } + } + createdAt + updatedAt + lastDiscoveredAt + domains { + id + domain + occurrences + } + occurrences + consentSiteCountAllTime + consentSiteCountLastWeek + } + } + } +`); + +export const DataFlowsDoc = graphql(/* GraphQL */ ` + query TranscendCliDataFlows( + $input: AirgapBundleInput! + $first: Int! + $offset: Int! + $filterBy: DataFlowsFiltersInput + $orderBy: [DataFlowOrder!] + ) { + dataFlows( + input: $input + first: $first + offset: $offset + filterBy: $filterBy + orderBy: $orderBy + useMaster: false + ) { + totalCount + nodes { + id + value + type + description + trackingType + purposes { + id + name + trackingType + } + frequency + service { + id + title + integrationName + } + isJunk + source + status + owners { + id + name + email + } + teams { + id + name + } + attributeValues { + id + name + attributeKey { + id + name + } + } + createdAt + updatedAt + lastDiscoveredAt + occurrences + consentSiteCountAllTime + consentSiteCountLastWeek + } + } + } +`); + +export const CookieStatsDoc = graphql(/* GraphQL */ ` + query TranscendCliCookieStats($input: AirgapBundleInput!) { + cookieStats(input: $input) { + liveCount + needReviewCount + junkCount + } + } +`); + +export const DataFlowStatsDoc = graphql(/* GraphQL */ ` + query TranscendCliDataFlowStats($input: AirgapBundleInput!) { + dataFlowStats(input: $input) { + liveCount + needReviewCount + junkCount + } + } +`); + +export const PurposesDoc = graphql(/* GraphQL */ ` + query TranscendCliPurposes($first: Int!) { + purposes(first: $first) { + nodes { + id + name + description + defaultConsent + trackingType + configurable + essential + showInConsentManager + isActive + displayOrder + optOutSignals + deletedAt + authLevel + showInPrivacyCenter + title + preferenceTopics { + id + slug + title { + description + } + color + } + purposeDataPointCount + preferenceTopicOptionValueDataPointCount + mappedDataSilos { + id + title + type + } + } + totalCount + } + } +`); + +export const ExperiencesDoc = graphql(/* GraphQL */ ` + query TranscendCliExperiences($first: Int!, $offset: Int!) { + experiences(first: $first, offset: $offset, useMaster: false) { + totalCount + nodes { + id + name + displayName + regions { + countrySubDivision + country + } + operator + displayPriority + onConsentExpiry + consentExpiry + viewState + purposes { + name + trackingType + } + optedOutPurposes { + name + trackingType + } + browserLanguages + browserTimeZones + consentUiVariant { + id + slug + } + } + } + } +`); + +export const UpdateOrCreateCookiesDoc = graphql(/* GraphQL */ ` + mutation TranscendCliUpdateOrCreateCookies( + $cookies: [UpdateOrCreateCookieInput!]! + $airgapBundleId: ID! + ) { + updateOrCreateCookies(input: { airgapBundleId: $airgapBundleId, cookies: $cookies }) { + clientMutationId + } + } +`); + +export const UpdateDataFlowsDoc = graphql(/* GraphQL */ ` + mutation TranscendCliUpdateDataFlows($airgapBundleId: ID!, $dataFlows: [UpdateDataFlowInput!]!) { + updateDataFlows(input: { airgapBundleId: $airgapBundleId, dataFlows: $dataFlows }) { + dataFlows { + id + value + type + description + trackingType + purposes { + id + name + trackingType + } + frequency + service { + id + title + integrationName + } + isJunk + source + status + createdAt + updatedAt + lastDiscoveredAt + occurrences + consentSiteCountAllTime + consentSiteCountLastWeek + } + } + } +`); + +export const ConsentManagerAnalyticsDataDoc = graphql(/* GraphQL */ ` + query TranscendCliConsentManagerAnalyticsData($input: AnalyticsInput!) { + analyticsData(input: $input) { + series { + name + points { + key + value + } + } + } + } +`); + +export const AggregateAnalyticsDoc = graphql(/* GraphQL */ ` + query TranscendCliAirgapBundleAggregateAnalytics( + $id: ID! + $input: AirgapBundleAggregateAnalyticsInput! + ) { + airgapBundleAggregateAnalytics(id: $id, input: $input) { + items { + measure + dimensions { + NEW_VALUE + REGIME + PURPOSE + } + } + } + } +`); + +export const TimeseriesAnalyticsDoc = graphql(/* GraphQL */ ` + query TranscendCliAirgapBundleTimeseriesAnalytics( + $id: ID! + $input: AirgapBundleTimeseriesAnalyticsInput! + ) { + airgapBundleTimeseriesAnalytics(id: $id, input: $input) { + items { + time + metric + measure + } + } + } +`); diff --git a/packages/mcp/mcp-server-consent/src/resolveAirgapBundleId.ts b/packages/mcp/mcp-server-consent/src/resolveAirgapBundleId.ts index 8b7c18d90..a8fe0a39f 100644 --- a/packages/mcp/mcp-server-consent/src/resolveAirgapBundleId.ts +++ b/packages/mcp/mcp-server-consent/src/resolveAirgapBundleId.ts @@ -1,8 +1,6 @@ import type { TranscendGraphQLBase } from '@transcend-io/mcp-server-base'; -import { - FETCH_CONSENT_MANAGER_ID, - type TranscendCliFetchConsentManagerIdResponse, -} from '@transcend-io/sdk'; + +import { FetchConsentManagerIdDoc } from './graphql.js'; const bundleIdCache = new WeakMap(); @@ -15,10 +13,7 @@ export async function resolveAirgapBundleId(graphql: TranscendGraphQLBase): Prom const cached = bundleIdCache.get(graphql); if (cached) return cached; - const data = await graphql.makeRequest( - FETCH_CONSENT_MANAGER_ID, - {}, - ); + const data = await graphql.makeRequest(FetchConsentManagerIdDoc); const id = data.consentManager.consentManager.id; bundleIdCache.set(graphql, id); diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_bulk_triage.ts b/packages/mcp/mcp-server-consent/src/tools/consent_bulk_triage.ts index 44f7a74bb..ad74af94d 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_bulk_triage.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_bulk_triage.ts @@ -4,15 +4,13 @@ import { ConsentTrackerType, TriageAction, } from '@transcend-io/privacy-types'; -import { - UPDATE_OR_CREATE_COOKIES, - UPDATE_DATA_FLOWS, - type TranscendUpdateCookieInputGql, - type TranscendUpdateDataFlowInputGql, - type TranscendCliUpdateOrCreateCookiesResponse, - type TranscendCliUpdateDataFlowsResponse, -} from '@transcend-io/sdk'; +import { + UpdateDataFlowsDoc, + UpdateOrCreateCookiesDoc, + type UpdateDataFlowInput, + type UpdateOrCreateCookieInput, +} from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const BulkTriageItemSchema = z.object({ @@ -57,7 +55,7 @@ export function createConsentBulkTriageTool(clients: ToolClients) { } = { cookies: [], dataFlows: [] }; if (cookieItems.length > 0) { - const cookieInputs: TranscendUpdateCookieInputGql[] = cookieItems.map((item) => ({ + const cookieInputs: UpdateOrCreateCookieInput[] = cookieItems.map((item) => ({ name: item.id, ...(item.action === 'APPROVE' ? { status: ConsentTrackerStatus.Live, isJunk: false } @@ -65,13 +63,10 @@ export function createConsentBulkTriageTool(clients: ToolClients) { ...(item.trackingPurposes ? { trackingPurposes: item.trackingPurposes } : {}), ...(item.service ? { service: item.service } : {}), })); - await clients.graphql.makeRequest( - UPDATE_OR_CREATE_COOKIES, - { - airgapBundleId, - cookies: cookieInputs, - }, - ); + await clients.graphql.makeRequest(UpdateOrCreateCookiesDoc, { + airgapBundleId, + cookies: cookieInputs, + }); results.cookies = cookieInputs.map((c) => ({ name: c.name, action: c.isJunk ? 'JUNKED' : 'APPROVED', @@ -80,7 +75,7 @@ export function createConsentBulkTriageTool(clients: ToolClients) { } if (dfItems.length > 0) { - const dfInputs: TranscendUpdateDataFlowInputGql[] = dfItems.map((item) => ({ + const dfInputs: UpdateDataFlowInput[] = dfItems.map((item) => ({ id: item.id, ...(item.action === 'APPROVE' ? { status: ConsentTrackerStatus.Live, isJunk: false } @@ -88,13 +83,10 @@ export function createConsentBulkTriageTool(clients: ToolClients) { ...(item.trackingPurposes ? { purposeIds: item.trackingPurposes } : {}), ...(item.service ? { service: item.service } : {}), })); - const dfResult = await clients.graphql.makeRequest( - UPDATE_DATA_FLOWS, - { - airgapBundleId, - dataFlows: dfInputs, - }, - ); + const dfResult = await clients.graphql.makeRequest(UpdateDataFlowsDoc, { + airgapBundleId, + dataFlows: dfInputs, + }); results.dataFlows = dfResult.updateDataFlows.dataFlows.map((df) => ({ id: df.id, action: df.isJunk ? 'JUNKED' : 'APPROVED', diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_get_aggregate_analytics.ts b/packages/mcp/mcp-server-consent/src/tools/consent_get_aggregate_analytics.ts index c04c2b557..b201cb029 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_get_aggregate_analytics.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_get_aggregate_analytics.ts @@ -1,14 +1,8 @@ import { createToolResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; -import { - AirgapBundleAnalyticsDimension, - AirgapBundleAnalyticsMetric, -} from '@transcend-io/privacy-types'; -import { - AIRGAP_BUNDLE_AGGREGATE_ANALYTICS, - type TranscendCliAirgapBundleAggregateAnalyticsResponse, -} from '@transcend-io/sdk'; +import { AirgapBundleAnalyticsDimension } from '@transcend-io/privacy-types'; import { resolveAnalyticsDateRange } from '../analyticsDateRange.js'; +import { AggregateAnalyticsDoc } from '../graphql.js'; import { airgapBundleAnalyticsMetricSchema } from '../normalizeAnalyticsMetric.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; @@ -50,19 +44,15 @@ export function createConsentGetAggregateAnalyticsTool(clients: ToolClients) { handler: async ({ metric, start, end, days, include_dimensions }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); const range = resolveAnalyticsDateRange({ start, end, days }); - const data = - await clients.graphql.makeRequest( - AIRGAP_BUNDLE_AGGREGATE_ANALYTICS, - { - id: airgapBundleId, - input: { - metric, - start: range.startEpoch, - end: range.endEpoch, - ...(include_dimensions?.length ? { includeDimensions: include_dimensions } : {}), - }, - }, - ); + const data = await clients.graphql.makeRequest(AggregateAnalyticsDoc, { + id: airgapBundleId, + input: { + metric, + start: range.startEpoch, + end: range.endEpoch, + ...(include_dimensions?.length ? { includeDimensions: include_dimensions } : {}), + }, + }); const items = data.airgapBundleAggregateAnalytics.items; return createToolResult(true, { diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_get_analytics_data.ts b/packages/mcp/mcp-server-consent/src/tools/consent_get_analytics_data.ts index 87b349f0e..1d9eea810 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_get_analytics_data.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_get_analytics_data.ts @@ -3,9 +3,9 @@ import { ConsentManagerAnalyticsDataSource, ConsentManagerMetricBin, } from '@transcend-io/privacy-types'; -import { CONSENT_MANAGER_ANALYTICS_DATA, type ConsentManagerMetric } from '@transcend-io/sdk'; import { resolveAnalyticsDateRange } from '../analyticsDateRange.js'; +import { ConsentManagerAnalyticsDataDoc } from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const GetAnalyticsDataSchema = z.object({ @@ -48,9 +48,7 @@ export function createConsentGetAnalyticsDataTool(clients: ToolClients) { handler: async ({ data_source, start, end, days, bin }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); const range = resolveAnalyticsDateRange({ start, end, days }); - const data = await clients.graphql.makeRequest<{ - analyticsData: { series: ConsentManagerMetric[] }; - }>(CONSENT_MANAGER_ANALYTICS_DATA, { + const data = await clients.graphql.makeRequest(ConsentManagerAnalyticsDataDoc, { input: { dataSource: data_source, startDate: range.startIso, diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_get_inventory_stats.ts b/packages/mcp/mcp-server-consent/src/tools/consent_get_inventory_stats.ts index abfad90c2..810b5742d 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_get_inventory_stats.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_get_inventory_stats.ts @@ -1,11 +1,6 @@ import { createToolResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; -import { - COOKIE_STATS, - DATA_FLOW_STATS, - type TranscendCliCookieStatsResponse, - type TranscendCliDataFlowStatsResponse, -} from '@transcend-io/sdk'; +import { CookieStatsDoc, DataFlowStatsDoc } from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const GetInventoryStatsSchema = z.object({}); @@ -26,8 +21,8 @@ export function createConsentGetInventoryStatsTool(clients: ToolClients) { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); const variables = { input: { airgapBundleId } }; const [cookieData, dfData] = await Promise.all([ - clients.graphql.makeRequest(COOKIE_STATS, variables), - clients.graphql.makeRequest(DATA_FLOW_STATS, variables), + clients.graphql.makeRequest(CookieStatsDoc, variables), + clients.graphql.makeRequest(DataFlowStatsDoc, variables), ]); return createToolResult(true, { cookies: cookieData.cookieStats, diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_get_timeseries_analytics.ts b/packages/mcp/mcp-server-consent/src/tools/consent_get_timeseries_analytics.ts index 2fce705f8..734a2f4fe 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_get_timeseries_analytics.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_get_timeseries_analytics.ts @@ -1,14 +1,8 @@ import { createToolResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; -import { - AirgapBundleAnalyticsBinInterval, - AirgapBundleAnalyticsMetric, -} from '@transcend-io/privacy-types'; -import { - AIRGAP_BUNDLE_TIMESERIES_ANALYTICS, - type TranscendCliAirgapBundleTimeseriesAnalyticsResponse, -} from '@transcend-io/sdk'; +import { AirgapBundleAnalyticsBinInterval } from '@transcend-io/privacy-types'; import { resolveAnalyticsDateRange } from '../analyticsDateRange.js'; +import { TimeseriesAnalyticsDoc } from '../graphql.js'; import { airgapBundleAnalyticsMetricSchema } from '../normalizeAnalyticsMetric.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; @@ -50,19 +44,15 @@ export function createConsentGetTimeseriesAnalyticsTool(clients: ToolClients) { handler: async ({ metric, start, end, days, bin_interval }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); const range = resolveAnalyticsDateRange({ start, end, days }); - const data = - await clients.graphql.makeRequest( - AIRGAP_BUNDLE_TIMESERIES_ANALYTICS, - { - id: airgapBundleId, - input: { - metric, - start: range.startEpoch, - end: range.endEpoch, - binInterval: bin_interval, - }, - }, - ); + const data = await clients.graphql.makeRequest(TimeseriesAnalyticsDoc, { + id: airgapBundleId, + input: { + metric, + start: range.startEpoch, + end: range.endEpoch, + binInterval: bin_interval, + }, + }); const items = data.airgapBundleTimeseriesAnalytics.items; return createToolResult(true, { diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_airgap_bundles.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_airgap_bundles.ts index 1b82634bb..0383762e6 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_airgap_bundles.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_airgap_bundles.ts @@ -4,10 +4,8 @@ import { EmptySchema, type ToolClients, } from '@transcend-io/mcp-server-base'; -import { - FETCH_CONSENT_MANAGER, - type TranscendCliFetchConsentManagerResponse, -} from '@transcend-io/sdk'; + +import { FetchConsentManagerDoc } from '../graphql.js'; export const ListAirgapBundlesSchema = EmptySchema; export type ListAirgapBundlesInput = Record; @@ -23,10 +21,7 @@ export function createConsentListAirgapBundlesTool(clients: ToolClients) { annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, zodSchema: ListAirgapBundlesSchema, handler: async (_args) => { - const data = await clients.graphql.makeRequest( - FETCH_CONSENT_MANAGER, - {}, - ); + const data = await clients.graphql.makeRequest(FetchConsentManagerDoc); return createToolResult(true, data.consentManager.consentManager); }, }); diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts index ccc37ca0b..d02cb155e 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_cookies.ts @@ -4,8 +4,8 @@ import { CookieOrderField, OrderDirection, } from '@transcend-io/privacy-types'; -import { COOKIES, type TranscendCliCookiesResponse } from '@transcend-io/sdk'; +import { CookiesDoc } from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const ListCookiesSchema = z.object({ @@ -75,7 +75,7 @@ export function createConsentListCookiesTool(clients: ToolClients) { orderDirection, }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); - const data = await clients.graphql.makeRequest(COOKIES, { + const data = await clients.graphql.makeRequest(CookiesDoc, { input: { airgapBundleId }, first: limit, offset, diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts index aa4380960..37bdc10a3 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_data_flows.ts @@ -5,8 +5,8 @@ import { DataFlowScope, OrderDirection, } from '@transcend-io/privacy-types'; -import { DATA_FLOWS, type TranscendCliDataFlowsResponse } from '@transcend-io/sdk'; +import { DataFlowsDoc } from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const ListDataFlowsSchema = z.object({ @@ -86,7 +86,7 @@ export function createConsentListDataFlowsTool(clients: ToolClients) { orderDirection, }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); - const data = await clients.graphql.makeRequest(DATA_FLOWS, { + const data = await clients.graphql.makeRequest(DataFlowsDoc, { input: { airgapBundleId }, first: limit, offset, diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_purposes.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_purposes.ts index 0cfb9f15f..8a667f471 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_purposes.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_purposes.ts @@ -1,5 +1,6 @@ import { createListResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; -import { PURPOSES, type TranscendCliPurposesResponse } from '@transcend-io/sdk'; + +import { PurposesDoc } from '../graphql.js'; export const ListPurposesSchema = z.object({ limit: z.coerce @@ -21,7 +22,7 @@ export function createConsentListPurposesTool(clients: ToolClients) { annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, zodSchema: ListPurposesSchema, handler: async ({ limit }) => { - const data = await clients.graphql.makeRequest(PURPOSES, { + const data = await clients.graphql.makeRequest(PurposesDoc, { first: Math.min(limit, 100), }); const { nodes, totalCount } = data.purposes; diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_list_regimes.ts b/packages/mcp/mcp-server-consent/src/tools/consent_list_regimes.ts index f510ac28d..ece6fda1d 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_list_regimes.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_list_regimes.ts @@ -1,5 +1,6 @@ import { createListResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; -import { EXPERIENCES, type TranscendCliExperiencesResponse } from '@transcend-io/sdk'; + +import { ExperiencesDoc } from '../graphql.js'; export const ListRegimesSchema = z.object({ limit: z.coerce @@ -29,7 +30,7 @@ export function createConsentListRegimesTool(clients: ToolClients) { annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }, zodSchema: ListRegimesSchema, handler: async ({ limit, offset }) => { - const data = await clients.graphql.makeRequest(EXPERIENCES, { + const data = await clients.graphql.makeRequest(ExperiencesDoc, { first: limit, offset, }); diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_update_cookies.ts b/packages/mcp/mcp-server-consent/src/tools/consent_update_cookies.ts index 2517e7624..32ebb8deb 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_update_cookies.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_update_cookies.ts @@ -1,11 +1,7 @@ import { createToolResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; import { ConsentTrackerStatus } from '@transcend-io/privacy-types'; -import { - UPDATE_OR_CREATE_COOKIES, - type TranscendUpdateCookieInputGql, - type TranscendCliUpdateOrCreateCookiesResponse, -} from '@transcend-io/sdk'; +import { UpdateOrCreateCookiesDoc, type UpdateOrCreateCookieInput } from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const UpdateCookieItemSchema = z.object({ @@ -43,7 +39,7 @@ export function createConsentUpdateCookiesTool(clients: ToolClients) { zodSchema: UpdateCookiesSchema, handler: async ({ cookies }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); - const cookieInputs: TranscendUpdateCookieInputGql[] = cookies.map((c) => ({ + const cookieInputs: UpdateOrCreateCookieInput[] = cookies.map((c) => ({ name: c.name, ...(c.trackingPurposes ? { trackingPurposes: c.trackingPurposes } : {}), ...(c.description !== undefined ? { description: c.description } : {}), @@ -51,13 +47,10 @@ export function createConsentUpdateCookiesTool(clients: ToolClients) { ...(c.isJunk !== undefined ? { isJunk: c.isJunk } : {}), ...(c.status !== undefined ? { status: c.status } : {}), })); - await clients.graphql.makeRequest( - UPDATE_OR_CREATE_COOKIES, - { - airgapBundleId, - cookies: cookieInputs, - }, - ); + await clients.graphql.makeRequest(UpdateOrCreateCookiesDoc, { + airgapBundleId, + cookies: cookieInputs, + }); return createToolResult(true, { updated: cookieInputs.length, cookies: cookieInputs.map((c) => ({ diff --git a/packages/mcp/mcp-server-consent/src/tools/consent_update_data_flows.ts b/packages/mcp/mcp-server-consent/src/tools/consent_update_data_flows.ts index 30c9d4140..b676373e4 100644 --- a/packages/mcp/mcp-server-consent/src/tools/consent_update_data_flows.ts +++ b/packages/mcp/mcp-server-consent/src/tools/consent_update_data_flows.ts @@ -1,11 +1,7 @@ import { createToolResult, defineTool, z, type ToolClients } from '@transcend-io/mcp-server-base'; import { ConsentTrackerStatus } from '@transcend-io/privacy-types'; -import { - UPDATE_DATA_FLOWS, - type TranscendUpdateDataFlowInputGql, - type TranscendCliUpdateDataFlowsResponse, -} from '@transcend-io/sdk'; +import { UpdateDataFlowsDoc, type UpdateDataFlowInput } from '../graphql.js'; import { resolveAirgapBundleId } from '../resolveAirgapBundleId.js'; export const UpdateDataFlowItemSchema = z.object({ @@ -39,7 +35,7 @@ export function createConsentUpdateDataFlowsTool(clients: ToolClients) { zodSchema: UpdateDataFlowsSchema, handler: async ({ dataFlows }) => { const airgapBundleId = await resolveAirgapBundleId(clients.graphql); - const dfInputs: TranscendUpdateDataFlowInputGql[] = dataFlows.map((df) => ({ + const dfInputs: UpdateDataFlowInput[] = dataFlows.map((df) => ({ id: df.id, ...(df.trackingPurposes ? { purposeIds: df.trackingPurposes } : {}), ...(df.description !== undefined ? { description: df.description } : {}), @@ -47,13 +43,10 @@ export function createConsentUpdateDataFlowsTool(clients: ToolClients) { ...(df.isJunk !== undefined ? { isJunk: df.isJunk } : {}), ...(df.status !== undefined ? { status: df.status } : {}), })); - const data = await clients.graphql.makeRequest( - UPDATE_DATA_FLOWS, - { - airgapBundleId, - dataFlows: dfInputs, - }, - ); + const data = await clients.graphql.makeRequest(UpdateDataFlowsDoc, { + airgapBundleId, + dataFlows: dfInputs, + }); return createToolResult(true, { updated: data.updateDataFlows.dataFlows.length, dataFlows: data.updateDataFlows.dataFlows.map((df) => ({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25dd0ad10..f59045374 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -635,6 +635,9 @@ importers: packages/mcp/mcp-server-consent: dependencies: + '@graphql-typed-document-node/core': + specifier: 'catalog:' + version: 3.2.0(graphql@16.14.2) '@modelcontextprotocol/sdk': specifier: 'catalog:' version: 1.29.0(zod@4.4.3) @@ -644,9 +647,9 @@ importers: '@transcend-io/privacy-types': specifier: workspace:* version: link:../../privacy-types - '@transcend-io/sdk': - specifier: workspace:* - version: link:../../sdk + graphql: + specifier: 'catalog:' + version: 16.14.2 zod: specifier: 'catalog:' version: 4.4.3 From b3592cafe530f75615e6fddd82652c54eab84029 Mon Sep 17 00:00:00 2001 From: Daniel Sklyar Date: Fri, 24 Jul 2026 12:15:31 -0700 Subject: [PATCH 3/3] chore: refresh schema.graphql from staging introspection Replace the hand-edited CookieOrderField.occurrences entry with an authentic `pnpm graphql:refresh-schema` snapshot now that the backend change (occurrences sort) has deployed to staging. Also picks up other schema drift accumulated since the last refresh; all MCP servers typecheck against the new snapshot. --- schema.graphql | 732 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 699 insertions(+), 33 deletions(-) diff --git a/schema.graphql b/schema.graphql index e9da3d310..de6dfa466 100644 --- a/schema.graphql +++ b/schema.graphql @@ -434,6 +434,7 @@ enum ScopeName { manageIntlMessages viewIntlMessages llmLogTransfer + viewWorkflows manageWorkflows viewDataSubCategories manageDataSubCategories @@ -507,6 +508,7 @@ enum IdentifierType { adobeAudienceManagerId adobeExperienceCloudId adobeTargetId + adobeCampaignRecipientId transcend } @@ -676,6 +678,8 @@ enum DatabaseModelName { CatalogCatalogCategory CatalogAiFeature ComplianceReportToken + CustomFunctionUser + CustomFunctionTeam DataPointLevelUser SubDataPointSubject DataPointUser @@ -921,6 +925,11 @@ enum DatabaseModelName { dataSubCategory dataCollection dataSilo + DropArtifact + dropBrokerCredential + DropRunRequest + dropRun + DropSubmissionDiscrepancy dataPoint subDataPoint unstructuredSubDataPointRecommendation @@ -1006,7 +1015,9 @@ enum DatabaseModelName { catalogCategory aiFeature aiUsageEvidenceItem + aiBaseModelDeveloperEvidenceItem customAiFeature + inaccurateAiFeatureReport vendorAiDraft saaSVendor aiDocumentationLink @@ -2376,6 +2387,11 @@ enum PostCompileStatus { DOWNLOADABLE } +enum AiBaseModelDeveloperEvidenceSourceType { + NAMED_SUB_PROCESSOR + OTHER_PUBLIC_DOCUMENTATION +} + enum AiDocumentationLinkType { AI_POLICY AI_DISCLOSURE @@ -2386,6 +2402,11 @@ enum AiDocumentationLinkType { OTHER } +enum AiDocumentationLinkTarget { + VENDOR + INTEGRATION +} + enum BusinessEntityOrderField { title createdAt @@ -2786,6 +2807,96 @@ enum DataProcessingAgreementStatus { MISSING } +enum DropBrokerEnvironment { + sandbox + production +} + +enum CppaWireListType { + NDZ + EMAIL + PHONE + MAID + NVIN + CTVID +} + +enum DropListType { + email + phone + maid + ctv + ndz + name_vin +} + +enum DropSubmissionDiscrepancyResult { + failed + missing +} + +enum DropRunSourcePattern { + BROKER_OWNED + TRANSCEND_OWNED +} + +enum DropBrokerMatchMode { + FILE_EXCHANGE + REST_LOOKUP + MANUAL +} + +enum DropRunState { + DOWNLOADED + AWAITING_BROKER_MATCH + INTAKE_IN_PROGRESS + DSRS_CREATED + REPORT_GENERATED + REPORT_SUBMITTED + AMENDED + FORCE_FINALIZED + FAILED +} + +enum DropRunMode { + LIVE + SANDBOX +} + +enum DropArtifactType { + CPPA_DOWNLOAD + MATCHED_RECORDS_UPLOAD + RESPONSE_CSV + AMEND_CSV + SUBMISSION_SUMMARY + RESPONSE_MANIFEST +} + +enum DropArtifactAuthorKind { + USER + DAEMON + CPPA +} + +enum DropSampleRowStatus { + OK + WARNING + ERROR +} + +enum DropSessionIssueLevel { + WARNING + ERROR +} + +enum DropPollInterval { + EVERY_HOUR + EVERY_6_HOURS + EVERY_12_HOURS + DAILY + WEEKLY +} + enum ActivityCode { REQUEST_DATA_SILO_ERROR REQUEST_DATA_SILO_ACTION_REQUIRED @@ -2886,10 +2997,13 @@ enum DownloadAndDecryptError { DECRYPTION_FAILED_FINALIZATION STREAM_PIPELINE_TIMEOUT SINK_STALL_TIMEOUT + SERVICE_WORKER_LOST + SINK_BACKPRESSURE_TIMEOUT STREAMSAVER_INIT_FAILED BROWSER_BLOCKED NETWORK_ERROR SAVE_DIALOG_CANCELLED + SAVE_DIALOG_UNAVAILABLE NATIVE_WRITER_FAILED UNKNOWN } @@ -2903,6 +3017,7 @@ enum DownloadAndDecryptEventType { PHASE_COMPLETE DOWNLOAD_SUCCEEDED ERROR_RECOVERED + STALLED ERROR } @@ -3288,8 +3403,8 @@ enum PlaintextReasonStaticType { } enum CustomFunctionSource { - DSR - RULES_AUTOMATION + UI + API } enum CustomFunctionType { @@ -3656,6 +3771,17 @@ enum PrivacyCenterType { PREVIEW } +enum PrivacyCenterModule { + PRIVACY_CENTER + POLICIES + MESSAGES + SUBJECTS + REQUESTS_PROCESSED_STATS + PURPOSES + WORKFLOW_CONFIGS + TRACKING_TECHNOLOGY +} + enum PrivacyCenterAssetName { logo favicon @@ -3913,6 +4039,7 @@ enum TableId { DATA_INVENTORY_SENSITIVE_CATEGORIES MAESTRO_RULE_EXECUTION_HISTORY ACTION_ITEMS + CUSTOM_FUNCTION_ACTIVITY } enum IntegrationsDataSilosColumnName { @@ -4013,6 +4140,7 @@ enum DataCategoriesColumnName { dataPointCount dataSiloRegions dataSilos + dataSubCategoryId description owners identifier @@ -4036,6 +4164,7 @@ enum PurposesColumnName { owners purpose purposeCategory + purposeSubCategoryId subCategoryName subDataPointCount subDataPointRetentionSchedules @@ -4076,6 +4205,7 @@ enum VendorsColumnName { enum BusinessEntitiesColumnName { address + businessEntityId catalogRecipients dataProtectionOfficerEmail dataProtectionOfficerName @@ -4217,6 +4347,7 @@ enum DsrIncomingRequestColumnName { successfullyCompletedAt replyToEmailAddresses details + dropRecordCount } enum ProcessingActivitiesColumnName { @@ -4226,6 +4357,7 @@ enum ProcessingActivitiesColumnName { owners businessEntities dataSilos + processingActivityId vendors securityMeasureDetails controllerships @@ -4384,6 +4516,7 @@ enum AuditEventCode { VENDOR_TEAM VENDOR_BUSINESS_ENTITY VENDOR_ATTRIBUTE + VENDOR_AI_USAGE SAAS_VENDOR DATA_SUB_CATEGORY IDENTIFIER @@ -4432,6 +4565,10 @@ enum AuditEventCode { CONSENT_SITE AIRGAP_BUNDLE_TCF_STACK AIRGAP_PARTITION + AIRGAP_PREFIX_MODULE + AIRGAP_PREFIX_MODULE_RELEASE + AIRGAP_BUNDLE_AIRGAP_PREFIX_MODULE + AIRGAP_BUNDLE_AIRGAP_PREFIX_MODULE_SETTINGS RISK_FRAMEWORK RISK_LEVEL RISK_CATEGORY @@ -4443,6 +4580,7 @@ enum AuditEventCode { PREFERENCE_TOPIC CONSENT_WORKFLOW_TRIGGER FEATURE + DATA_SUBJECT VENDOR_LIST CONSENT_UI_VARIANT CONSENT_UI_THEME @@ -4459,6 +4597,32 @@ enum AuditEventCode { MAESTRO_RULE_TRIGGER MAESTRO_SECRET MAESTRO_CUSTOM_FUNCTION + DROP_RUN + DROP_BROKER_CREDENTIAL +} + +enum AiFeatureAuditChangeKind { + REPORTED_AS_INACCURATE + REPORTED_AS_INACCURATE_AND_HIDDEN + MARKED_HIGH_RISK + CLEARED_HIGH_RISK + VISIBILITY_SHOWN + VISIBILITY_HIDDEN +} + +enum DropRunLifecycleKind { + RUN_INGESTED + CPPA_DOWNLOADED + DSRS_CREATED + RECORD_MATCHED + RECORD_UNMATCHED + SUPPRESSION_APPLIED + REPORT_GENERATED + REPORT_SUBMITTED + REPORT_AMENDED + SUBMISSION_SUMMARY_RECEIVED + SUBMISSION_DISCREPANCY_FLAGGED + RUN_FORCE_FINALIZED } enum AuditEventBaseModelCode { @@ -4513,6 +4677,7 @@ enum AuditEventBaseModelCode { CONSENT_SITE AIRGAP_BUNDLE_TCF_STACK AIRGAP_PARTITION + AIRGAP_PREFIX_MODULE RISK_FRAMEWORK RISK_LEVEL RISK_CATEGORY @@ -4522,6 +4687,7 @@ enum AuditEventBaseModelCode { PREFERENCE_TOPIC CONSENT_WORKFLOW_TRIGGER FEATURE + DATA_SUBJECT VENDOR_LIST CONSENT_UI_VARIANT CONSENT_UI_THEME @@ -4530,6 +4696,8 @@ enum AuditEventBaseModelCode { MAESTRO_CUSTOM_FUNCTION MAESTRO_RULE_TRIGGER MAESTRO_SECRET + DROP_RUN + DROP_BROKER_CREDENTIAL } enum CONSENT_AUDIT_EVENTS { @@ -4877,6 +5045,8 @@ type Query { currentDnsRecords(input: CurrentDnsRecordsInput!): CurrentDnsRecordsPayload! currentEmailDomains: [EmailDomain!]! currentEmailSenderAddresses(input: CurrentEmailSenderAddressesInput!): CurrentEmailSenderAddressesPayload! + customFunctionRunFileLink(input: CustomFunctionRunFileLinkInput!): CustomFunctionRunFileLinkPayload! + customFunctionRuns(first: Int, offset: Int = 0, last: Int, filterBy: CustomFunctionRunFilterInput): CustomFunctionRunsPayload! customFunctions(first: Int, offset: Int = 0, last: Int, filterBy: CustomFunctionFilterInput): CustomFunctionsPayload! customSyncEndpoints(id: ID!): CustomSyncEndpointsPayload! dataCategories(first: Int, offset: Int = 0, last: Int, filterBy: DataCategoryFiltersInput): DataCategoriesPayload! @@ -4907,6 +5077,10 @@ type Query { discoClassScans(first: Int, offset: Int = 0, last: Int, filterBy: DiscoClassScanFiltersInput): DiscoClassScansPayload! downloadFiles(first: Int, offset: Int = 0, last: Int, dhEncrypted: String, filterBy: DownloadFileFiltersInput!, orderBy: [DownloadFileOrder!], lookup: PrivacyCenterLookupInput): DownloadFilesPayload! downloadFilesCountsOnly(dhEncrypted: String!, filterBy: DownloadFileFiltersInput!, lookup: PrivacyCenterLookupInput): DownloadFilesCountsOnlyPayload! + dropBrokerConfig: DropBrokerConfigPayload! + dropRun(id: ID!): DropRunSummary! + dropRunRequests(first: Int, last: Int, before: String, after: String, filterBy: DropRunRequestFiltersInput!): DropRunRequestsPayload! + dropRuns(first: Int, last: Int, before: String, after: String, filterBy: DropRunFiltersInput): DropRunsPayload! enricher(id: ID!): Enricher! enrichers(first: Int, offset: Int = 0, last: Int, useMaster: Boolean, isExportCsv: Boolean, filterBy: EnricherFiltersInput, orderBy: [EnricherOrder!]): EnrichersPayload! experiences(first: Int, offset: Int = 0, last: Int, useMaster: Boolean, isExportCsv: Boolean, filterBy: ExperienceFiltersInput, orderBy: [ExperienceOrder!]): ExperiencesPayload! @@ -5036,6 +5210,7 @@ type Query { user: CurrentUser users(first: Int, offset: Int = 0, last: Int, filterBy: UserFiltersInput, orderBy: [UserOrder!]): UsersPayload! vendorCommunicationsMetadata(first: Int, offset: Int = 0, last: Int, input: VendorCommunicationsMetadataInput!): VendorCommunicationsMetadataPayload! + vendorModelProviders: VendorModelProviders! vendors(first: Int, offset: Int = 0, last: Int, filterBy: VendorsFiltersInput, orderBy: [VendorOrder!], useMaster: Boolean, isExportCsv: Boolean): VendorsPayload! workflowCommunicationsSettings(input: WorkflowConfigIdInput!): WorkflowCommunicationsSettingsPayload! workflowConfig(input: WorkflowConfigInput!): WorkflowConfigPayload! @@ -5062,7 +5237,7 @@ type Mutation { approveRequests(input: ApproveRequestsInput!): ApproveRequestsPayload! approveRequestSecondary(input: CommunicationInput!): ApproveRequestSecondaryPayload! archiveCustomFunction(input: ArchiveCustomFunctionInput!): ArchiveCustomFunctionPayload! - assignConsentSitesToConsentUiTheme(input: AssignConsentSitesToConsentUiThemeInput!): AssignConsentSitesToConsentUiThemePayload! + assignMaestroRuleCustomFunction(input: AssignMaestroRuleCustomFunctionInput!): AssignMaestroRuleCustomFunctionPayload! assumeRole(id: ID!, publicKey: String!): AssumeRolePayload! bulkRetryProfileDataPoints(input: BulkRetryProfileDataPointsInput!): BulkRetryProfileDataPointsPayload! bulkUnwrapProfileIdentifiers(input: BulkUnwrapProfileIdentifiersInput!, dhEncrypted: String!): BulkUnwrapProfileIdentifiersPayload! @@ -5110,6 +5285,7 @@ type Mutation { createContract(input: CreateContractInput!): CreateContractPayload! createContractScan(input: CreateContractScanInput!): CreateContractScanPayload! createCopiedComplianceReport(useMaster: Boolean, isExportCsv: Boolean, input: CreateCopiedComplianceReportInput!): CreateCopiedComplianceReportPayload! + createCustomFunction(input: CreateCustomFunctionInput!, dhEncrypted: String): CreateCustomFunctionPayload! createDataCollection(input: NewDataCollectionInput!): CreateDataCollectionPayload! createDataFlows(input: CreateDataFlowInput!): CreateDataFlowsPayload! createDataReport(input: CreateDataReportInput!): CreateDataReportPayload! @@ -5240,14 +5416,14 @@ type Mutation { deleteSensitiveCategories(input: DeleteSensitiveCategoriesInput!): DeleteSensitiveCategoriesPayload! deleteSoftwareDevelopmentKits(input: DeleteSoftwareDevelopmentKitsInput!): DeleteSoftwareDevelopmentKitsPayload! deleteSubDataPoints(input: DeleteSubDataPointsInput!): DeleteSubDataPointsPayload! - deleteSubject(id: ID!, skipPublish: Boolean): DeleteSubjectPayload! + deleteSubject(id: ID!, skipPublish: Boolean, confirmDisableWorkflows: Boolean): DeleteSubjectPayload! deleteTeam(id: ID!): DeleteTeamPayload! deleteTemplate(id: ID!): DeleteTemplatePayload! deleteVendors(input: DeleteVendorsInput!): DeleteVendorsPayload! deleteWorkflow(input: DeleteWorkflowInput!): DeleteWorkflowPayload! deployCloudfront(input: PrivacyCenterIdInput!): DeployCloudfrontPayload! deployConsentManagerBundle(id: ID!, input: DeployConsentManagerInput!): DeployConsentManagerBundlePayload! - deployDraftVersionForPrivacyCenter(input: PrivacyCenterIdInput!): DeployDraftVersionForPrivacyCenterPayload! + deployDraftVersionForPrivacyCenter(input: DeployDraftVersionForPrivacyCenterInput!): DeployDraftVersionForPrivacyCenterPayload! destroyAccount(input: DestroyUserInput!): DestroyAccountPayload! determineLoginMethod(input: LoginDetailsInput!): DetermineLoginMethodPayload! disableExperiences(input: DisableExperiencesInput!): DisableExperiencesPayload! @@ -5292,6 +5468,7 @@ type Mutation { oauthRevoke(input: OAuthRevokeInput!): OauthRevokePayload! oauthToken(input: OAuthTokenInput!): OauthTokenPayload! placeRequestOnHold(id: ID!): PlaceRequestOnHoldPayload! + pollDropForRequests: PollDropForRequestsPayload! prepareDataSubjectRequestAttachments(input: PrepareDataSubjectRequestAttachmentsInput!, lookup: PrivacyCenterLookupInput, dhEncrypted: String!): PrepareDataSubjectRequestAttachmentsPayload! prepareRequestAttachments(input: PrepareRequestAttachmentsInput!): PrepareRequestAttachmentsPayload! privacyCenterEmailLogin(lookup: PrivacyCenterLookupInput, input: EmailLoginInput!): PrivacyCenterEmailLoginPayload! @@ -5302,7 +5479,6 @@ type Mutation { reconnectDataSilo(input: ReconnectDataSiloInput!, dhEncrypted: String!): ReconnectDataSiloPayload! redactRequestFiles(input: RedactRequestFilesInput!): RedactRequestFilesPayload! refetchSubDataPointSample(input: RefetchSubDataPointSampleInput!): RefetchSubDataPointSamplePayload! - removeConsentSitesFromConsentUiTheme(input: RemoveConsentSitesFromConsentUiThemeInput!): RemoveConsentSitesFromConsentUiThemePayload! removeDataSiloFromWorkflowConfig(input: WorkflowDataSiloInput!): RemoveDataSiloFromWorkflowConfigPayload! removeEnrichersFromWorkflowConfig(input: RemoveEnrichersFromWorkflowConfigInput!): RemoveEnrichersFromWorkflowConfigPayload! removeFileUploadsFromWorkflowConfig(input: RemoveFileUploadsFromWorkflowConfigInput!): RemoveFileUploadsFromWorkflowConfigPayload! @@ -5310,6 +5486,7 @@ type Mutation { removeSombra(id: ID!): RemoveSombraPayload! removeTCFStacksFromBundle(input: SetTCFStacksInput!): RemoveTcfStacksFromBundlePayload! removeUser(id: ID, input: RemoveUserInput): RemoveUserPayload! + reportAiFeatureAsInaccurate(input: ReportAiFeatureAsInaccurateInput!): ReportAiFeatureAsInaccuratePayload! reportPromptRun(input: ReportPromptRunInput!): ReportPromptRunPayload! reprocessComplianceReport(input: ReprocessComplianceReportInput!): ReprocessComplianceReportPayload! requestCertificate(input: PrivacyCenterIdInput!): RequestCertificatePayload! @@ -5351,6 +5528,7 @@ type Mutation { setAiFeatureHighRiskForVendor(input: SetAiFeatureHighRiskForVendorInput!): SetAiFeatureHighRiskForVendorPayload! setAiFeatureVisibilityForVendor(input: SetAiFeatureVisibilityForVendorInput!): SetAiFeatureVisibilityForVendorPayload! setAirgapBundleTcfStacks(input: SetTCFStacksInput!): SetAirgapBundleTcfStacksPayload! + setDropBrokerConfig(input: SetDropBrokerConfigInput!, dhEncrypted: String): SetDropBrokerConfigPayload! setOrgNotificationDestinationAllowList(input: AllowNotificationDestinationsInput!): SetOrgNotificationDestinationAllowListPayload! setRequestsProcessedDisclosureStatsSettings(input: RequestsProcessedDisclosureStatsSettingsInput!): SetRequestsProcessedDisclosureStatsSettingsPayload! setResourceAttributes(input: SetResourceAttributesInput!): SetResourceAttributesPayload! @@ -5428,7 +5606,7 @@ type Mutation { updateConsentUiVariant(input: UpdateConsentUiVariantInput!): UpdateConsentUiVariantPayload! updateContracts(input: UpdateContractsInput!): UpdateContractsPayload! updateContractScans(input: UpdateContractScansInput!): UpdateContractScansPayload! - updateCustomFunction(input: UpdateCustomFunctionInput!, dhEncrypted: String!): UpdateCustomFunctionPayload! + updateCustomFunction(input: UpdateCustomFunctionInput!, dhEncrypted: String): UpdateCustomFunctionPayload! updateDataFlows(input: UpdateDataFlowsInput!): UpdateDataFlowsPayload! updateDataPointLevel(input: UpdateDataPointLevelInput!): UpdateDataPointLevelPayload! updateDataReports(input: UpdateDataReportsInput!): UpdateDataReportsPayload! @@ -5492,6 +5670,7 @@ type Mutation { updateSombraOAuthConfig(input: UpdateSombraOAuthConfigInput!, dhEncrypted: String!): UpdateSombraOAuthConfigPayload! updateSombraTenantConfig(dhEncrypted: String!): UpdateSombraTenantConfigPayload! updateSsoProvider(input: SsoProviderInput!, dhEncrypted: String!): UpdateSsoProviderPayload! + updateStandaloneCustomFunction(input: UpdateStandaloneCustomFunctionInput!, dhEncrypted: String): UpdateStandaloneCustomFunctionPayload! updateSubDataPoints(input: UpdateSubDataPointsInput!): UpdateSubDataPointsPayload! updateSubject(input: UpdateSubjectInput!): UpdateSubjectPayload! updateSyncEndpoint(input: UpdateSyncEndpointInput!): UpdateSyncEndpointPayload! @@ -6010,11 +6189,22 @@ type AgentsPayload { totalCount: Int! } +type AiBaseModelDeveloperEvidenceItemPreview { + id: ID! + providerName: String! + url: String! + quote: String! + accessedAt: Date! + sourceType: AiBaseModelDeveloperEvidenceSourceType! +} + type AiDocumentationLinkPreview { id: ID! type: AiDocumentationLinkType! name: String! url: String! + catalogId: ID + target: AiDocumentationLinkTarget } type AiFeaturePreview { @@ -6128,6 +6318,41 @@ type AirgapBundleVersion { gpp: String tcfStylesheet: String tcfVendorsList: String + tcfGvlAr: String + tcfGvlBg: String + tcfGvlBs: String + tcfGvlCs: String + tcfGvlDa: String + tcfGvlDe: String + tcfGvlEl: String + tcfGvlEn: String + tcfGvlEs: String + tcfGvlFi: String + tcfGvlFr: String + tcfGvlHe: String + tcfGvlHi: String + tcfGvlHr: String + tcfGvlHu: String + tcfGvlId: String + tcfGvlIs: String + tcfGvlIt: String + tcfGvlJa: String + tcfGvlKo: String + tcfGvlLt: String + tcfGvlMs: String + tcfGvlNl: String + tcfGvlNo: String + tcfGvlPl: String + tcfGvlPtBr: String + tcfGvlRo: String + tcfGvlRu: String + tcfGvlSrLatn: String + tcfGvlSv: String + tcfGvlTh: String + tcfGvlTr: String + tcfGvlUk: String + tcfGvlVi: String + tcfGvlZh: String tcfEn: String tcfHe: String tcfBs: String @@ -6230,6 +6455,7 @@ input AirgapVersionsInput { type AiSetting { id: ID! isAiEnabled: Boolean! + isMcpSombraEnabled: Boolean! } type AiUsageEvidenceItemPreview { @@ -6467,6 +6693,22 @@ type ApplicationUsersPayload { totalCount: Int! } +input ApplyApprovedVendorAiDraftInput { + approvedPayloadJson: String! +} + +type ApplyApprovedVendorAiDraftResult { + draftId: ID! + status: String! + reviewedByUserId: ID + reviewedAt: String + reviewNotes: String + applied: Boolean! + alreadyApproved: Boolean! + saaSVendorId: ID + integrationName: String +} + type ApproveRequestPayload { clientMutationId: String request: Request! @@ -6489,19 +6731,47 @@ input ApproveRequestsInput { isSilent: Boolean } +input ApproveVendorAiDraftInput { + draftId: ID! + reviewNotes: String + proposedFieldsOverrideJson: String + evidenceOverrideJson: String +} + +type ApproveVendorAiDraftResult { + draftId: ID! + status: String! + reviewedByUserId: ID + reviewedAt: String + reviewNotes: String + approved: Boolean! + alreadyApproved: Boolean! + saaSVendorId: ID + integrationName: String + fieldsOverridden: Boolean! + evidenceOverridden: Boolean! + contentfulEntryIds: [String!] + approvedPayloadJson: String! +} + type ArchiveCustomFunctionPayload { clientMutationId: String - customFunction: CustomFunction! - dependencyWarnings: [CustomFunctionLifecycleDependencyWarning!]! + results: [ArchiveCustomFunctionResult!]! blocked: Boolean! success: Boolean! } input ArchiveCustomFunctionInput { - id: ID! + ids: [ID!]! dryRun: Boolean } +type ArchiveCustomFunctionResult { + customFunction: CustomFunction! + dependencyWarnings: [CustomFunctionLifecycleDependencyWarning!]! + blocked: Boolean! +} + type AssessmentAnswer implements AssessmentAnswerInterface { id: ID! index: Int! @@ -7160,15 +7430,14 @@ type AssetFilesPayload { totalCount: Int! } -type AssignConsentSitesToConsentUiThemePayload { +type AssignMaestroRuleCustomFunctionPayload { clientMutationId: String - consentUiTheme: ConsentUiTheme! + maestroRule: MaestroRule! } -input AssignConsentSitesToConsentUiThemeInput { - airgapBundleId: ID! - consentUiThemeId: ID! - consentSiteIds: [ID!]! +input AssignMaestroRuleCustomFunctionInput { + maestroRuleId: ID! + customFunctionId: ID! } input AssociateReplyWithSombraInput { @@ -7508,12 +7777,15 @@ input AuditEventFiltersInput { consentServiceIds: [ID!] consentSiteIds: [ID!] airgapPartitionIds: [ID!] + airgapPrefixModuleIds: [ID!] + airgapPrefixModuleReleaseIds: [ID!] saaSCategoryIds: [ID!] riskFrameworkIds: [ID!] riskLevelIds: [ID!] riskCategoryIds: [ID!] customFunctionIds: [ID!] featureIds: [ID!] + subjectIds: [ID!] consentUiVariantIds: [ID!] workflowConfigIds: [ID!] maestroRuleIds: [ID!] @@ -7573,6 +7845,9 @@ type AuditEventPreviewRaw { consentServiceId: ID consentSiteId: ID airgapPartitionId: ID + airgapPrefixModuleId: ID + airgapPrefixModuleReleaseId: ID + AirgapBundleAirgapPrefixModuleId: ID saaSCategoryId: ID riskFrameworkId: ID riskLevelId: ID @@ -7583,6 +7858,7 @@ type AuditEventPreviewRaw { processingPurposeSubCategoryId: ID processingActivityId: ID subDataPointId: ID + subjectId: ID consentUiVariantId: ID workflowConfigId: ID maestroRuleId: ID @@ -8902,6 +9178,7 @@ input ConsentApplicationUpsertInput { type ConsentHost { id: ID! host: String! + site: String! user: UserPreview lastDiscoveredAt: Date description: String @@ -8912,6 +9189,8 @@ type ConsentHost { dataFlowCountTriageLastWeek: Int! cookieCountApprovedLastWeek: Int! cookieCountTriageLastWeek: Int! + consentUiThemeId: ID + consentUiTheme: ConsentUiThemePreview } type ConsentHostsPayload { @@ -9245,6 +9524,11 @@ input ConsentUiThemeFilterInput { id: ID } +type ConsentUiThemePreview { + id: ID! + name: String! +} + type ConsentUiThemesPayload { clientMutationId: String nodes: [ConsentUiTheme!]! @@ -10112,6 +10396,25 @@ input CreateCopiedComplianceReportInput { description: String } +type CreateCustomFunctionPayload { + clientMutationId: String + customFunction: CustomFunction! + success: Boolean! +} + +input CreateCustomFunctionInput { + type: CustomFunctionType! + dataSiloId: ID + sombraId: ID + setActive: Boolean + name: String + description: String + ownerUserIds: [ID!] + ownerTeamIds: [ID!] + signedCodeJwt: String + signedCodeContextJwt: String +} + type CreatedApiKey implements ApiKeyInterface { apiKey: String! id: ID! @@ -10221,6 +10524,7 @@ type CreatedOauthClient implements OauthClientInterface { preview: String! redirectUris: [String!]! expiresAt: Date + isMcp: Boolean! } type CreateEmailSenderAddressPayload { @@ -10332,6 +10636,7 @@ input CreateOauthClientInput { consentDisplayName: String! redirectUris: [String!]! expiresAt: Date + isMcp: Boolean } type CreateOnPremiseSombraPayload { @@ -10947,11 +11252,24 @@ type CustomAiFeaturePreview { type CustomFunction { id: ID! + name: String! + description: String lastModifiedAt: Date! + createdAt: Date! signedCodeJwt: String! signedCodeContextJwt: String! lifecycleState: CustomFunctionLifecycleState! type: CustomFunctionType! + sombraId: ID + runsLink: String! + owners: [UserPreview!]! + activeVersion: CustomFunctionVersionPreview + draftVersion: CustomFunctionVersionPreview + hasPendingDraft: Boolean! + source: CustomFunctionSource! + lastRunDate: Date + runsLast7Days: Int! + referencedBy: [CustomFunctionReference!]! } type CustomFunctionExecutionError { @@ -10985,6 +11303,9 @@ type CustomFunctionExecutionResult { input CustomFunctionFilterInput { id: ID dataSiloId: ID + type: CustomFunctionType + lifecycleState: CustomFunctionLifecycleState + text: String } type CustomFunctionLifecycleDependencyWarning { @@ -10995,12 +11316,58 @@ type CustomFunctionLifecycleDependencyWarning { message: String! } +type CustomFunctionReference { + id: String! + type: String! + name: String! + status: String! +} + +type CustomFunctionRun { + id: String! + startedAt: Date! + customFunction: CustomFunction! + lifecycleState: CustomFunctionRunLifecycleState + isSuccess: Boolean! + failureAttribution: CustomFunctionRunFailureAttribution + runMetadataS3Path: String! + duration: Int! +} + +type CustomFunctionRunFileLinkPayload { + clientMutationId: String + temporaryLink: String! +} + +input CustomFunctionRunFileLinkInput { + customFunctionRunId: String! +} + +input CustomFunctionRunFilterInput { + customFunctionId: ID + text: String +} + +type CustomFunctionRunsPayload { + clientMutationId: String + nodes: [CustomFunctionRun!]! + totalCount: Int! +} + type CustomFunctionsPayload { clientMutationId: String nodes: [CustomFunction!]! totalCount: Int! } +type CustomFunctionVersionPreview { + id: ID! + versionNumber: String! + lifecycleState: CustomFunctionVersionLifecycleState! + lastModifiedAt: Date! + signedCodeJwt: String! +} + type CustomHeader { name: String! value: String! @@ -11634,6 +12001,7 @@ type DataSilo implements DatamapDataSiloInterface { allowDsrProcessingEndTime: String isPaidIntegration: Boolean! isPausedForDsrs: Boolean! + skipSecondaryIfNoFiles: Boolean! privacyRequestSubdatapointEnabled: Boolean! users: [UserPreview!]! plaintextContext: [PlaintextContext!]! @@ -11740,6 +12108,7 @@ type DataSiloBulkPreview implements DatamapDataSiloInterface { WorkflowConfigDataSilo: WorkflowConfigDataSilo sensitiveCategories: [SensitiveCategory!] isPausedForDsrs: Boolean! + skipSecondaryIfNoFiles: Boolean! } input DataSiloBulkPreviewOrder { @@ -12082,6 +12451,7 @@ type DataSubjectInternal implements DataSubjectInterface { openRequestCount: Int! fulFilledRequestCount: Int! closedRequestCount: Int! + hasRequests: Boolean! } type DataSubjectUpdateConsentPreferencesPayload { @@ -12941,6 +13311,11 @@ type DeployDraftVersionForPrivacyCenterPayload { success: Boolean! } +input DeployDraftVersionForPrivacyCenterInput { + privacyCenterId: ID! + modules: [PrivacyCenterModule!] +} + input DeprecatedRequestIdentifierInput { name: String value: String! @@ -12978,6 +13353,7 @@ input DeprecatedRequestIdentifiersInput { adobeAudienceManagerId: [DeprecatedRequestIdentifierInput!] adobeExperienceCloudId: [DeprecatedRequestIdentifierInput!] adobeTargetId: [DeprecatedRequestIdentifierInput!] + adobeCampaignRecipientId: [DeprecatedRequestIdentifierInput!] transcend: [DeprecatedRequestIdentifierInput!] } @@ -13169,6 +13545,125 @@ type DownloadFilesCountsOnlyPayload { nodes: [DownloadFileCounts!]! } +type DropArtifact { + id: ID! + artifactType: DropArtifactType! + filename: String! + sha256: String! + byteSize: Int! + downloadUrl: String + creator: UserPreview + createdAt: Date! +} + +type DropBrokerConfigPayload { + clientMutationId: String + config: DropBrokerConfig +} + +type DropBrokerConfig { + id: ID! + dataBrokerId: String! + environment: DropBrokerEnvironment! + listTypesEnabled: [DropListType!]! + lastValidatedAt: Date + workflowConfig: WorkflowConfigPreview + apiKeyConfigured: Boolean! + pollingEnabled: Boolean! + pollIntervalMinutes: Int! + autoSubmitReportBack: Boolean! + matchMode: DropBrokerMatchMode! +} + +input DropRecordRefInput { + dropRecordId: Int! + dropListType: DropListType! +} + +type DropRunDsrProcessingStats { + totalDsrs: Int! + completedCount: Int! + pendingCount: Int! + medianCompletionDays: Float + p90CompletionDays: Float +} + +input DropRunFiltersInput { + text: String + states: [DropRunState!] + listTypes: [DropListType!] + sourcePatterns: [DropRunSourcePattern!] +} + +type DropRunReportingFunnel { + cppaDownloadRecordCount: Int! + mappingRowCount: Int! + dsrsCreated: Int! + dsrsCompleted: Int! + dsrsPending: Int! +} + +type DropRunReportingTiming { + downloadedAt: Date! + deadlineAt: Date! + reportGeneratedAt: Date + submittedAt: Date + daysSinceDownload: Int! + daysUntilDeadline: Int! + daysDownloadToReport: Int + daysDownloadToSubmit: Int +} + +input DropRunRequestFiltersInput { + requestIds: [ID!] + dropRunIds: [ID!] + text: String +} + +type DropRunRequestsPayload { + clientMutationId: String + nodes: [DropRunRequestSummary!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type DropRunRequestSummary { + id: ID! + requestId: ID + dropRunId: ID! + dropRecordId: Int! + dropListType: DropListType! + cppaStatusCode: Int +} + +type DropRunsPayload { + clientMutationId: String + nodes: [DropRunSummary!]! + pageInfo: PageInfo! +} + +type DropRunSubmissionDiscrepancyCounts { + failedCount: Int! + missingCount: Int! +} + +type DropRunSummary { + id: ID! + dataBrokerId: String! + listTypes: [DropListType!]! + sourcePattern: DropRunSourcePattern! + cycleNumber: Int! + state: DropRunState! + downloadedAt: Date! + deadlineAt: Date! + submittedAt: Date + totalRecords: Int! + matchedRows: Int! + requestsCount: Int! + pendingRecordsCount: Int! + artifacts: [DropArtifact!]! +} + type DsrFormIdentifier implements IdentifierInterface { id: String! name: String! @@ -13271,7 +13766,9 @@ input EmployeeBulkRequestInput { attributes: [AttributeInput!] partitionKey: String idempotencyKey: String - workflowConfigId: ID + workflowConfigId: ID! + dropRecords: [DropRecordRefInput!] + dropRunId: ID } type EmployeeDownloadCekPayload { @@ -13317,6 +13814,8 @@ input EmployeeRequestInput { idempotencyKey: String subjectType: String! type: RequestAction! + dropRecords: [DropRecordRefInput!] + dropRunId: ID } type EmployeeReSignEncryptedCekContextsPayload { @@ -14136,6 +14635,15 @@ input ImportOnetrustAssessmentsInput { json: String } +type InaccurateAiFeatureReportPreview { + id: ID! + vendorId: ID! + aiFeatureId: ID! + reportedByUserId: ID + reason: String + createdAt: Date! +} + type InitiateSitescanPayload { clientMutationId: String success: Boolean! @@ -14521,7 +15029,7 @@ type MaestroRuleAction { order: Int! customFunctionId: ID sombraId: ID - customFunction: MaestroCustomFunction + customFunction: CustomFunction sendAssessmentMode: MaestroSendAssessmentMode assessmentName: String assessmentDescription: String @@ -14816,6 +15324,7 @@ type OauthClient implements OauthClientInterface { preview: String! redirectUris: [String!]! expiresAt: Date + isMcp: Boolean! } input OauthClientFiltersInput { @@ -14830,6 +15339,7 @@ interface OauthClientInterface { preview: String! redirectUris: [String!]! expiresAt: Date + isMcp: Boolean! } type OauthClientsPayload { @@ -15380,6 +15890,11 @@ input PolicyVersionInput { content: PolicyContentInput } +type PollDropForRequestsPayload { + clientMutationId: String + dropRun: DropRunSummary! +} + type PossibleDataSiloDependenciesPayload { clientMutationId: String nodes: [DataSilo!]! @@ -15499,8 +16014,10 @@ input PreferenceTopicOptionValueDataPointFilterInput { purposeIds: [ID!] preferenceTopicIds: [ID!] preferenceOptionValueIds: [ID!] + preferenceTopicOptionValueIds: [ID!] text: String preferenceState: PreferenceSelectionState + actions: [RequestAction!] dataPointIds: [ID!] notAssociatedWithWorkflowConfigId: ID } @@ -15649,12 +16166,16 @@ type PrivacyCenterFooterLink { displayOrder: Int! title: LocalizedMessage! url: LocalizedMessage! + icon: AssetFile + iconOnly: Boolean } input PrivacyCenterFooterLinkInput { id: ID title: String url: String + iconId: ID + iconOnly: Boolean } input PrivacyCenterIdInput { @@ -16360,6 +16881,8 @@ type PtovDataPointWorkflowMappingsPayload { input PtovDataPointWorkflowMappingsFilterInput { workflowConfigId: ID preferenceTopicOptionValueDataPointIds: [ID!] + preferenceTopicOptionValueIds: [ID!] + text: String isActive: Boolean } @@ -16424,6 +16947,7 @@ input PurposeDataPointsFilterInput { text: String purposeState: PreferenceSelectionState notAssociatedWithWorkflowConfigId: ID + actions: [RequestAction!] } type PurposeDataPoint { @@ -16446,6 +16970,7 @@ type PurposeDataPointWorkflowMappingsPayload { input PurposeDataPointWorkflowMappingsFilterInput { workflowConfigId: ID purposeDataPointIds: [ID!] + text: String isActive: Boolean } @@ -16703,6 +17228,21 @@ input RegionInput { countrySubDivision: String } +input RejectVendorAiDraftInput { + draftId: ID! + reviewNotes: String! +} + +type RejectVendorAiDraftResult { + draftId: ID! + status: String! + reviewedByUserId: ID + reviewedAt: String + reviewNotes: String + rejected: Boolean! + alreadyRejected: Boolean! +} + input ReleaseAirgapPrefixModuleVersionInput { organizationId: ID name: String! @@ -16714,18 +17254,6 @@ input ReleaseAirgapPrefixModuleVersionInput { type ReleaseAirgapPrefixModuleVersionResult { airgapPrefixModuleId: ID! airgapPrefixModuleReleaseId: ID! - created: Boolean! -} - -type RemoveConsentSitesFromConsentUiThemePayload { - clientMutationId: String - consentUiTheme: ConsentUiTheme! -} - -input RemoveConsentSitesFromConsentUiThemeInput { - airgapBundleId: ID! - consentUiThemeId: ID! - consentSiteIds: [ID!]! } type RemoveDataSiloFromWorkflowConfigPayload { @@ -16782,6 +17310,19 @@ input RemoveUserInput { email: String } +type ReportAiFeatureAsInaccuratePayload { + clientMutationId: String + inaccurateAiFeatureReport: InaccurateAiFeatureReportPreview! + customAiFeature: CustomAiFeaturePreview +} + +input ReportAiFeatureAsInaccurateInput { + vendorId: ID! + aiFeatureId: ID! + reason: String + suppressVisibility: Boolean +} + type ReportPromptRunPayload { clientMutationId: String promptRun: PromptRun! @@ -16930,6 +17471,7 @@ type Request implements RequestInterface { isTest: Boolean! isSilent: Boolean! origin: RequestOrigin! + dropRecordCount: Int! link: String! steps: RequestSteps! parentId: ID @deprecated(reason: "Child/parent requests are no longer supported") @@ -17265,6 +17807,7 @@ input RequestFiltersInput { hasEnricherErrors: Boolean identifierValue: String workflowConfigIds: [ID!] + dropRunIds: [ID!] partitionKeys: [String!] partitionIds: [ID!] purposeNames: [String!] @@ -17403,6 +17946,7 @@ input RequestIdentifierOrder { type RequestIdentityEnrichmentJob { id: ID! + isMissingDestinationModel: Boolean status: String! scheduledAt: Date! error: String @@ -17704,6 +18248,7 @@ type RetryDataSiloErrorsPayload { type RetryEnricherErrorsPayload { clientMutationId: String enricher: Enricher! + retriedCount: Int! } type RetryProfileDataPointPayload { @@ -17914,6 +18459,41 @@ input RollbackAirgapBundleInput { gpp: String tcfStylesheet: String tcfVendorsList: String + tcfGvlAr: String + tcfGvlBg: String + tcfGvlBs: String + tcfGvlCs: String + tcfGvlDa: String + tcfGvlDe: String + tcfGvlEl: String + tcfGvlEn: String + tcfGvlEs: String + tcfGvlFi: String + tcfGvlFr: String + tcfGvlHe: String + tcfGvlHi: String + tcfGvlHr: String + tcfGvlHu: String + tcfGvlId: String + tcfGvlIs: String + tcfGvlIt: String + tcfGvlJa: String + tcfGvlKo: String + tcfGvlLt: String + tcfGvlMs: String + tcfGvlNl: String + tcfGvlNo: String + tcfGvlPl: String + tcfGvlPtBr: String + tcfGvlRo: String + tcfGvlRu: String + tcfGvlSrLatn: String + tcfGvlSv: String + tcfGvlTh: String + tcfGvlTr: String + tcfGvlUk: String + tcfGvlVi: String + tcfGvlZh: String tcfEn: String tcfHe: String tcfBs: String @@ -18000,7 +18580,7 @@ type RunCustomFunctionPayload { } input RunCustomFunctionInput { - type: CustomFunctionType + type: CustomFunctionType! id: ID sombraId: ID payload: String! @@ -18069,6 +18649,7 @@ type SaaSVendorPreview { logoSquare: String! aiDocumentationLinks: [AiDocumentationLinkPreview!] aiBaseModel: [String!] + baseModelDeveloperEvidence: [AiBaseModelDeveloperEvidenceItemPreview!] catalogs: [SaaSVendorAttachedCatalog!] } @@ -18631,6 +19212,23 @@ input SetAirgapVersionInput { version: String! } +type SetDropBrokerConfigPayload { + clientMutationId: String + config: DropBrokerConfig! +} + +input SetDropBrokerConfigInput { + dataBrokerId: String + environment: DropBrokerEnvironment + listTypesEnabled: [DropListType!] + workflowConfigId: ID + clearApiKey: Boolean + pollingEnabled: Boolean + pollIntervalMinutes: Int + autoSubmitReportBack: Boolean + matchMode: DropBrokerMatchMode +} + type SetOrgNotificationDestinationAllowListPayload { clientMutationId: String orgNotificationDestinationAllowList: OrgNotificationDestinationAllowList! @@ -18784,6 +19382,7 @@ input SignedRequestIdentifiersInput { adobeAudienceManagerId: [SignedRequestIdentifierInput!] adobeExperienceCloudId: [SignedRequestIdentifierInput!] adobeTargetId: [SignedRequestIdentifierInput!] + adobeCampaignRecipientId: [SignedRequestIdentifierInput!] transcend: [SignedRequestIdentifierInput!] } @@ -19471,6 +20070,7 @@ input TablesPreferencesInput { DATA_INVENTORY_SENSITIVE_CATEGORIES: TablePreferencesInput MAESTRO_RULE_EXECUTION_HISTORY: TablePreferencesInput ACTION_ITEMS: TablePreferencesInput + CUSTOM_FUNCTION_ACTIVITY: TablePreferencesInput } type TCFDataCategory { @@ -20048,6 +20648,7 @@ type UnwrapCustomFunctionPayload { input UnwrapCustomFunctionInput { id: ID! + versionId: ID } type UnwrapEmailContentsPayload { @@ -20264,7 +20865,8 @@ type UpdateAiSettingPayload { } input UpdateAiSettingInput { - isAiEnabled: Boolean! + isAiEnabled: Boolean + isMcpSombraEnabled: Boolean } type UpdateApiKeyPayload { @@ -20748,6 +21350,7 @@ input UpdateConsentUiThemeInput { id: ID! name: String configuration: ConsentUiThemeConfigInput + consentSiteIds: [ID!] } type UpdateConsentUiVariantPayload { @@ -20806,9 +21409,31 @@ type UpdateCustomFunctionPayload { success: Boolean! } +input UpdateCustomFunctionAsAdminInput { + organizationId: ID! + dataSiloId: ID! + customFunctionId: ID + code: String! + userDefinedEnv: [UpdateCustomFunctionUserDefinedEnvInput!]! + name: String + description: String + allowedHosts: [String!] + allowThirdPartyImports: Boolean +} + input UpdateCustomFunctionInput { id: ID dataSiloId: ID! + name: String + description: String + ownerUserIds: [ID!] + signedCodeJwt: String + signedCodeContextJwt: String +} + +input UpdateCustomFunctionUserDefinedEnvInput { + key: String! + value: String! } input UpdateDataFlowInput { @@ -20909,6 +21534,7 @@ input UpdateDataSiloInput { defaultAccessRequestVisibility: Boolean isLive: Boolean isPausedForDsrs: Boolean + skipSecondaryIfNoFiles: Boolean headers: [CustomHeaderInput!] attributes: [AttributeInput!] dependedOnDataSiloIds: [ID!] @@ -21305,6 +21931,7 @@ input UpdateOauthClientInput { consentDisplayName: String! redirectUris: [String!]! expiresAt: Date + isMcp: Boolean } type UpdateOrCreateApplicationUsersPayload { @@ -22067,6 +22694,23 @@ type UpdateSsoProviderPayload { ssoProvider: SsoProvider! } +type UpdateStandaloneCustomFunctionPayload { + clientMutationId: String + customFunction: CustomFunction! + success: Boolean! +} + +input UpdateStandaloneCustomFunctionInput { + id: ID! + versionId: ID + name: String + description: String + ownerUserIds: [ID!] + ownerTeamIds: [ID!] + signedCodeJwt: String + signedCodeContextJwt: String +} + input UpdateSubDataPointInput { id: ID! name: String @@ -22410,6 +23054,14 @@ type Vendor implements VendorInterface { catalogRecipients: [SaaSCategoryBase!]! } +type VendorAiDraftReviewResult { + draftId: ID! + status: String! + reviewedByUserId: ID + reviewedAt: String + reviewNotes: String +} + type VendorCommunicationsMetadataPayload { clientMutationId: String nodes: [CommunicationMetadata!]! @@ -22440,6 +23092,10 @@ interface VendorInterface { saaSVendor: SaaSVendorPreview } +type VendorModelProviders { + providers: [String!]! +} + input VendorOrder { field: VendorOrderField! direction: OrderDirection! @@ -22491,6 +23147,7 @@ input VendorsFiltersInput { dataProcessingAgreementStatus: [DataProcessingAgreementStatus!] aiFeaturesIdentified: Boolean highRiskAiFeaturesIdentified: Boolean + aiBaseModelDevelopers: [String!] } type VerifyPrivacyCenterLoginEmailPayload { @@ -22577,6 +23234,7 @@ type WorkflowConfig { expiryTime: [ExpiryTime!] WorkflowConfigAttributeKeys: [WorkflowConfigAttributeKey!] internalName: String + unresolvedRequiredIdentifierCount: Int } type WorkflowConfigAttributeKey { @@ -22634,6 +23292,13 @@ input WorkflowConfigInput { id: ID! } +type WorkflowConfigPreview { + id: ID! + title: LocalizedMessage! + internalName: String + description: LocalizedMessage +} + type WorkflowDataPoint { exportMode: DataPointExportMode order: Int @@ -22702,6 +23367,7 @@ type WorkflowIdentifier implements WorkflowIdentifierBaseInterface { destinationDataSilos: [IdentifierDestinationDataSilo!]! missingIdBehavior: MissingIdBehavior! isDisabled: Boolean! + hasResolutionPath: Boolean! } type WorkflowIdentifierBase implements WorkflowIdentifierBaseInterface { @@ -22753,7 +23419,7 @@ input WorkflowRequestInput { partitionKey: String attributes: [AttributeInput!] idempotencyKey: String - workflowConfigId: ID + workflowConfigId: ID! } type WorkflowsResponse {