refactor(editor): Rename Dynamic credentials to Private credentials in the UI (#31555)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Guillaume Jacquart 2026-06-03 10:02:51 +02:00 committed by GitHub
parent 8376a4f2a4
commit 27aca712df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 34 additions and 35 deletions

View File

@ -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,
});
});

View File

@ -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),

View File

@ -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;
}

View File

@ -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 (

View File

@ -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": "<a target=\"_blank\" href=\"https://docs.n8n.io/workflows/sticky-notes/\">Markdown</a> 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",

View File

@ -632,7 +632,7 @@ const tags = computed(
>
<span :class="$style.dynamicBadgeText">
<N8nIcon icon="key-round" size="medium" />
{{ locale.baseText('credentials.dynamic.badge') }}
{{ locale.baseText('credentials.private.badge') }}
</span>
</N8nBadge>
</N8nTooltip>

View File

@ -248,8 +248,8 @@ function moveResource() {
<N8nTooltip v-if="isDynamicCredentialsEnabled && data.isResolvable" placement="top">
<template #content>
<div :class="$style.tooltipContent">
<strong>{{ locale.baseText('credentials.dynamic.tooltipTitle') }}</strong>
<span>{{ locale.baseText('credentials.dynamic.tooltip') }}</span>
<strong>{{ locale.baseText('credentials.private.tooltipTitle') }}</strong>
<span>{{ locale.baseText('credentials.private.tooltip') }}</span>
</div>
</template>
<N8nBadge
@ -259,7 +259,7 @@ function moveResource() {
>
<span :class="$style.dynamicBadgeText">
<N8nIcon icon="key-round" size="medium" />
{{ locale.baseText('credentials.dynamic.badge') }}
{{ locale.baseText('credentials.private.badge') }}
</span>
</N8nBadge>
</N8nTooltip>

View File

@ -820,7 +820,7 @@ async function onQuickConnectSignIn(credentialTypeName: string) {
placement="top"
>
<template #content>{{
i18n.baseText('credentials.dynamic.tooltip')
i18n.baseText('credentials.private.tooltip')
}}</template>
<N8nBadge
theme="tertiary"
@ -853,7 +853,7 @@ async function onQuickConnectSignIn(credentialTypeName: string) {
</N8nSelect>
<div v-if="isCredentialResolvable(type.name)" :class="$style.dynamicIndicator">
<N8nTooltip placement="top">
<template #content>{{ i18n.baseText('credentials.dynamic.tooltip') }}</template>
<template #content>{{ i18n.baseText('credentials.private.tooltip') }}</template>
<N8nBadge
theme="tertiary"
class="pl-3xs pr-3xs"

View File

@ -20,7 +20,7 @@ describe('RedactedDataState', () => {
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();

View File

@ -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

View File

@ -117,7 +117,7 @@ async function onAction(action: string, resolver: CredentialResolver) {
<div :class="$style.iconCard"><N8nIcon icon="user" /></div>
</div>
<N8nHeading tag="h2" size="medium" align="center" class="mb-2xs">
Resolve dynamic credentials from user identity
Resolve private credentials from user identity
</N8nHeading>
<div>
{{ i18n.baseText('credentialResolver.view.description') }}

View File

@ -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',
},