From 27aca712dfcbaaaf5fc5c688b5bf9737d6df9445 Mon Sep 17 00:00:00 2001 From: Guillaume Jacquart Date: Wed, 3 Jun 2026 10:02:51 +0200 Subject: [PATCH] refactor(editor): Rename Dynamic credentials to Private credentials in the UI (#31555) Co-authored-by: Claude Opus 4.8 --- .../__tests__/telemetry-event-relay.test.ts | 6 ++--- .../events/relays/telemetry.event-relay.ts | 8 +++--- packages/cli/src/interfaces.ts | 2 +- packages/cli/src/telemetry/index.ts | 4 +-- .../frontend/@n8n/i18n/src/locales/en.json | 27 +++++++++---------- .../src/app/components/WorkflowCard.vue | 2 +- .../credentials/components/CredentialCard.vue | 6 ++--- .../components/NodeCredentials.vue | 4 +-- .../components/RedactedDataState.test.ts | 2 +- .../features/resolvers/ResolversView.test.ts | 4 +-- .../src/features/resolvers/ResolversView.vue | 2 +- .../DynamicCredentialCheck.node.ts | 2 +- 12 files changed, 34 insertions(+), 35 deletions(-) diff --git a/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts b/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts index 59c64b42fc9..a0b81a356cf 100644 --- a/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts +++ b/packages/cli/src/events/__tests__/telemetry-event-relay.test.ts @@ -909,7 +909,7 @@ describe('TelemetryEventRelay', () => { credential_id: 'cred123', project_id: 'project123', project_type: 'personal', - is_dynamic: false, + is_private: false, uses_external_secrets: false, jwe_enabled: false, }); @@ -965,7 +965,7 @@ describe('TelemetryEventRelay', () => { user_role: GLOBAL_OWNER_ROLE.slug, credential_type: 'github', credential_id: 'cred123', - is_dynamic: true, + is_private: true, uses_external_secrets: false, jwe_enabled: false, }); @@ -1491,7 +1491,7 @@ describe('TelemetryEventRelay', () => { user_id: 'user123', version_cli: N8N_VERSION, workflow_id: 'workflow123', - used_dynamic_credentials: false, + used_private_credentials: false, }); }); diff --git a/packages/cli/src/events/relays/telemetry.event-relay.ts b/packages/cli/src/events/relays/telemetry.event-relay.ts index c8dc9948c1d..bcd9b01b39a 100644 --- a/packages/cli/src/events/relays/telemetry.event-relay.ts +++ b/packages/cli/src/events/relays/telemetry.event-relay.ts @@ -574,7 +574,7 @@ export class TelemetryEventRelay extends EventRelay { project_id: projectId, project_type: projectType, uiContext, - is_dynamic: isDynamic ?? false, + is_private: isDynamic ?? false, uses_external_secrets: usesExternalSecrets ?? false, jwe_enabled: jweEnabled ?? false, }); @@ -612,7 +612,7 @@ export class TelemetryEventRelay extends EventRelay { user_role: user.role?.slug, credential_type: credentialType, credential_id: credentialId, - is_dynamic: isDynamic ?? false, + is_private: isDynamic ?? false, uses_external_secrets: usesExternalSecrets ?? false, jwe_enabled: jweEnabled ?? false, }); @@ -1007,7 +1007,7 @@ export class TelemetryEventRelay extends EventRelay { version_cli: N8N_VERSION, success: false, ...executionTelemetryProperties, - used_dynamic_credentials: Object.values(runData?.data?.resultData?.runData ?? {}).some( + used_private_credentials: Object.values(runData?.data?.resultData?.runData ?? {}).some( (taskDataList) => taskDataList.some((taskData) => taskData.usedDynamicCredentials), ), }; @@ -1106,7 +1106,7 @@ export class TelemetryEventRelay extends EventRelay { is_managed: false, eval_rows_left: null, meta: JSON.stringify(workflow.meta), - used_dynamic_credentials: telemetryProperties.used_dynamic_credentials, + used_private_credentials: telemetryProperties.used_private_credentials, ...executionTelemetryProperties, ...TelemetryHelpers.resolveAIMetrics(workflow.nodes, this.nodeTypes), ...TelemetryHelpers.resolveVectorStoreMetrics(workflow.nodes, this.nodeTypes, runData), diff --git a/packages/cli/src/interfaces.ts b/packages/cli/src/interfaces.ts index f7e9488a960..81a4e12e712 100644 --- a/packages/cli/src/interfaces.ts +++ b/packages/cli/src/interfaces.ts @@ -185,7 +185,7 @@ export interface IExecutionTrackProperties extends ITelemetryTrackProperties { error_node_type?: string; is_manual: boolean; crashed?: boolean; - used_dynamic_credentials?: boolean; + used_private_credentials?: boolean; execution_source?: WorkflowExecutionSource; mock_data_sources?: string; } diff --git a/packages/cli/src/telemetry/index.ts b/packages/cli/src/telemetry/index.ts index 13505ec6cb0..644d1d80af7 100644 --- a/packages/cli/src/telemetry/index.ts +++ b/packages/cli/src/telemetry/index.ts @@ -306,8 +306,8 @@ export class Telemetry { this.addExecutionTrackData(workflowId, sourceKey, execTime); } - if (properties.used_dynamic_credentials) { - this.track('Workflow execution with dynamic credentials', properties); + if (properties.used_private_credentials) { + this.track('Workflow execution with private credentials', properties); } if ( diff --git a/packages/frontend/@n8n/i18n/src/locales/en.json b/packages/frontend/@n8n/i18n/src/locales/en.json index 4425f621d28..91aad511bae 100644 --- a/packages/frontend/@n8n/i18n/src/locales/en.json +++ b/packages/frontend/@n8n/i18n/src/locales/en.json @@ -1037,7 +1037,7 @@ "credentialEdit.credentialConfig.switchTo": "Use {name}", "credentialEdit.credentialConfig.externalSecrets": "Enterprise plan users can pull in credentials from external vaults.", "credentialEdit.credentialConfig.externalSecrets.moreInfo": "More info", - "credentialEdit.credentialConfig.dynamicCredentials.title": "Set up for dynamic credentials", + "credentialEdit.credentialConfig.dynamicCredentials.title": "Set up for private credentials", "credentialEdit.credentialConfig.dynamicCredentials.infoTip": "When enabled, each execution uses the triggering user's credentials instead of a single fixed credential. Requires a webhook trigger with user identity extraction enabled. The credentials you connect are only used for manual testing or when the workflow uses a non-webhook trigger.", "credentialEdit.credentialConfig.oauthDisabledTooltip": "Complete all fields to connect", "credentialEdit.credentialEdit.confirmMessage.beforeClose1.cancelButtonText": "Close", @@ -1067,7 +1067,7 @@ "credentialEdit.credentialEdit.couldNotFindCredentialWithId": "Could not find credential with ID", "credentialEdit.credentialEdit.delete": "Delete", "credentialEdit.credentialEdit.details": "Details", - "credentialEdit.credentialEdit.dynamic": "Dynamic", + "credentialEdit.credentialEdit.dynamic": "Private", "credentialEdit.credentialEdit.saving": "Saving", "credentialEdit.credentialEdit.showError.createCredential.title": "Problem creating credential", "credentialEdit.credentialEdit.showError.deleteCredential.title": "Problem deleting credential", @@ -1142,9 +1142,8 @@ "credentials.item.connect": "Connect", "credentials.item.connect.tooltip": "Connect your own account to use this credential in workflows. Only you can use your private credential.", "credentials.item.connected": "Connected", - "credentials.dynamic.tooltip": "This credential uses a resolver to pick the right account at runtime based on who runs the workflow.", - "credentials.dynamic.tooltipTitle": "Dynamic credentials", - "credentials.dynamic.badge": "Dynamic", + "credentials.private.tooltip": "This credential uses a resolver to pick the right account at runtime based on who runs the workflow.", + "credentials.private.tooltipTitle": "Private credentials", "credentials.private.badge": "Private", "credentials.private.callout.title": "This node is set up to use end user accounts", "credentials.private.callout.connected": "Your account is connected", @@ -1855,7 +1854,7 @@ "ndv.redacted.description.sentence2": "Adjust redaction rules in {link}.", "ndv.redacted.description.link": "workflow settings", "ndv.redacted.noPermission.description": "Execution data has been redacted. You do not have the permissions to reveal it.", - "ndv.redacted.dynamicCredentials.description": "This execution used dynamic credentials. Data from dynamic credential executions cannot be revealed.", + "ndv.redacted.dynamicCredentials.description": "This execution used private credentials. Data from private credential executions cannot be revealed.", "ndv.redacted.revealButton": "Reveal data", "ndv.redacted.revealModal.title": "Reveal redacted data", "ndv.redacted.revealModal.warning": "This data is redacted, because it likely contains sensitive information. Please read the following before proceeding.", @@ -1975,7 +1974,7 @@ "node.settings.retriesOnFailure": "This node will automatically retry if it fails", "node.settings.executeOnce": "This node executes only once, no matter how many input items there are", "node.settings.alwaysOutputData": "This node will output an empty item if nothing would normally be returned", - "node.settings.dynamicCredentials": "This node uses dynamic credentials that are resolved at runtime.", + "node.settings.dynamicCredentials": "This node uses private credentials that are resolved at runtime.", "node.settings.contextEstablishmentHooks": "This webhook extracts the triggering user's identity token to resolve credentials at runtime.", "sticky.markdownHint": "Markdown supported", "nodeBase.clickToAddNodeOrDragToConnect": "Click to add node \n or drag to connect", @@ -2213,7 +2212,7 @@ "nodeSettings.executeButtonTooltip.times": "Will execute {inputSize} times, once for each input item", "nodeSettings.executeOnce.description": "If active, the node executes only once, with data from the first item it receives", "nodeSettings.executeOnce.displayName": "Execute Once", - "nodeSettings.dynamicCredentials.displayName": "Dynamic Credentials", + "nodeSettings.dynamicCredentials.displayName": "Private Credentials", "nodeSettings.maxTries.description": "Number of times to attempt to execute the node before failing the execution", "nodeSettings.maxTries.displayName": "Max. Tries", "nodeSettings.noDescriptionFound": "No description found", @@ -3937,7 +3936,7 @@ "workflowSettings.saveExecutionProgressOptions.doNotSave": "Do not save", "workflowSettings.saveExecutionProgressOptions.save": "@:_reusableBaseText.save", "workflowSettings.redactProductionData": "Redact production execution data", - "workflowSettings.redactProductionData.dynamicCredentialsHint": "Prod. execution data is always redacted in workflows that use dynamic credentials.", + "workflowSettings.redactProductionData.dynamicCredentialsHint": "Prod. execution data is always redacted in workflows that use private credentials.", "workflowSettings.redactManualData": "Redact manual execution data", "workflowSettings.redactManualData.requiresProductionHint": "Manual execution data can only be redacted when production execution data is also redacted.", "workflowSettings.redactionOptions.default": "Default - Do not redact", @@ -3970,15 +3969,15 @@ "workflowSettings.executionTimeout": "Timeout Workflow", "workflowSettings.tags": "Tags", "workflowSettings.timezone": "Timezone", - "workflowSettings.credentialResolver": "Dynamic credential resolver", + "workflowSettings.credentialResolver": "Private credential resolver", "workflowSettings.credentialResolver.placeholder": "Select resolver", "workflowSettings.credentialResolver.createNew": "Create new resolver", "workflowSettings.credentialResolver.edit": "Edit resolver", "workflowSettings.credentialResolver.none": "Default - None", - "workflowSettings.helpTexts.credentialResolver": "The resolver uses the identity of the user triggering the workflow to pick the right account for all dynamic credentials in this workflow.", + "workflowSettings.helpTexts.credentialResolver": "The resolver uses the identity of the user triggering the workflow to pick the right account for all private credentials in this workflow.", "credentialResolver.addNew": "Add Resolver", "credentialResolver.view.title": "Credential resolvers", - "credentialResolver.view.description": "Resolvers take an incoming user identity and pick the account used by dynamic credentials when the workflow runs. Select a resolver in Workflow settings.", + "credentialResolver.view.description": "Resolvers take an incoming user identity and pick the account used by private credentials when the workflow runs. Select a resolver in Workflow settings.", "credentialResolver.view.learnMore": "You can learn more in the ", "credentialResolver.action.edit": "Edit", "credentialResolver.action.delete": "Delete", @@ -4000,7 +3999,7 @@ "credentialResolverEdit.delete": "Delete", "credentialResolverEdit.confirmMessage.deleteResolver.headline": "Delete Credential Resolver?", "credentialResolverEdit.confirmMessage.deleteResolver.message": "Are you sure you want to delete the credential resolver {savedResolverName}?", - "credentialResolverEdit.confirmMessage.deleteResolver.messageWithWorkflows": "Are you sure you want to delete the credential resolver {savedResolverName}? The following workflows use this resolver and will no longer resolve dynamic credentials:", + "credentialResolverEdit.confirmMessage.deleteResolver.messageWithWorkflows": "Are you sure you want to delete the credential resolver {savedResolverName}? The following workflows use this resolver and will no longer resolve private credentials:", "credentialResolverEdit.confirmMessage.deleteResolver.andMore": "and {count} more...", "credentialResolverEdit.confirmMessage.deleteResolver.confirmButtonText": "Delete", "credentialResolverEdit.sidebar.configuration": "Configuration", @@ -4146,7 +4145,7 @@ "workflows.item.archived": "Archived", "workflows.item.availableInMCP": "Available in MCP", "workflows.dynamic.tooltip": "This workflow resolves credentials at runtime based on who executes it.", - "workflows.dynamic.tooltipTitle": "Dynamic credentials", + "workflows.dynamic.tooltipTitle": "Private credentials", "workflows.dependencies.tooltip.workflow": "Click to view resources referenced by this workflow", "workflows.dependencies.tooltip.credential": "Click to view resources referencing this credential", "workflows.dependencies.tooltip.dataTable": "Click to view resources referencing this data table", diff --git a/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue b/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue index 153dd2a7b1d..5bb1d73b428 100644 --- a/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue +++ b/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue @@ -632,7 +632,7 @@ const tags = computed( > - {{ locale.baseText('credentials.dynamic.badge') }} + {{ locale.baseText('credentials.private.badge') }} diff --git a/packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue b/packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue index dc1e05b5138..0747e44d9b7 100644 --- a/packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue +++ b/packages/frontend/editor-ui/src/features/credentials/components/CredentialCard.vue @@ -248,8 +248,8 @@ function moveResource() { - {{ locale.baseText('credentials.dynamic.badge') }} + {{ locale.baseText('credentials.private.badge') }} diff --git a/packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue b/packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue index fc435853dbd..4eee1908f8e 100644 --- a/packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue +++ b/packages/frontend/editor-ui/src/features/credentials/components/NodeCredentials.vue @@ -820,7 +820,7 @@ async function onQuickConnectSignIn(credentialTypeName: string) { placement="top" >
- + { expect( getByText( - 'This execution used dynamic credentials. Data from dynamic credential executions cannot be revealed.', + 'This execution used private credentials. Data from private credential executions cannot be revealed.', ), ).toBeInTheDocument(); expect(queryByText('Execution data has been redacted.')).not.toBeInTheDocument(); diff --git a/packages/frontend/editor-ui/src/features/resolvers/ResolversView.test.ts b/packages/frontend/editor-ui/src/features/resolvers/ResolversView.test.ts index c3095aac383..1078aa99dc7 100644 --- a/packages/frontend/editor-ui/src/features/resolvers/ResolversView.test.ts +++ b/packages/frontend/editor-ui/src/features/resolvers/ResolversView.test.ts @@ -124,7 +124,7 @@ describe('ResolversView', () => { const { getByText } = renderComponent({ pinia }); await waitFor(() => { - expect(getByText('Resolve dynamic credentials from user identity')).toBeInTheDocument(); + expect(getByText('Resolve private credentials from user identity')).toBeInTheDocument(); }); }); @@ -135,7 +135,7 @@ describe('ResolversView', () => { // Wait for empty state to be displayed (after loading completes) await waitFor(() => { - expect(getByText('Resolve dynamic credentials from user identity')).toBeInTheDocument(); + expect(getByText('Resolve private credentials from user identity')).toBeInTheDocument(); }); // Now the Add Resolver button should be available diff --git a/packages/frontend/editor-ui/src/features/resolvers/ResolversView.vue b/packages/frontend/editor-ui/src/features/resolvers/ResolversView.vue index 5f4e353f9d6..d83f73a0e66 100644 --- a/packages/frontend/editor-ui/src/features/resolvers/ResolversView.vue +++ b/packages/frontend/editor-ui/src/features/resolvers/ResolversView.vue @@ -117,7 +117,7 @@ async function onAction(action: string, resolver: CredentialResolver) {
- Resolve dynamic credentials from user identity + Resolve private credentials from user identity
{{ i18n.baseText('credentialResolver.view.description') }} diff --git a/packages/nodes-base/nodes/DynamicCredentialCheck/DynamicCredentialCheck.node.ts b/packages/nodes-base/nodes/DynamicCredentialCheck/DynamicCredentialCheck.node.ts index 442aef2155a..107f5b8758e 100644 --- a/packages/nodes-base/nodes/DynamicCredentialCheck/DynamicCredentialCheck.node.ts +++ b/packages/nodes-base/nodes/DynamicCredentialCheck/DynamicCredentialCheck.node.ts @@ -14,7 +14,7 @@ export class DynamicCredentialCheck implements INodeType { group: ['transform'], version: 1, description: - 'Checks whether the triggering user has the required Dynamic credential configured. Routes to "Ready" or "Not Ready" and returns auth URLs when the credential is missing.', + 'Checks whether the triggering user has the required Private credential configured. Routes to "Ready" or "Not Ready" and returns auth URLs when the credential is missing.', defaults: { name: 'Check Credential Status', },