chore: Align private/dynamic credential wording to "end-user credentials" (#33865)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guillaume Jacquart
2026-07-09 11:24:39 +02:00
committed by GitHub
parent 993e1c8b72
commit 31e75b9022
11 changed files with 48 additions and 48 deletions
@@ -96,7 +96,7 @@ export const scopeInformation: Partial<Record<Scope, ScopeInformation>> = {
},
'credential:connect': {
displayName: 'Connect Credential',
description: 'Allows connecting an own account to a private credential.',
description: 'Allows connecting an own account to an end-user credential.',
},
'insights:read': {
displayName: 'Read Insights',
@@ -1074,7 +1074,7 @@ describe('TelemetryEventRelay', () => {
eventService.emit('private-credential-created', event);
expect(telemetry.track).toHaveBeenCalledWith('User created private credential', {
expect(telemetry.track).toHaveBeenCalledWith('User created end-user credential', {
user_id: 'user123',
user_role: GLOBAL_OWNER_ROLE.slug,
credential_type: 'gmailOAuth2',
@@ -1099,7 +1099,7 @@ describe('TelemetryEventRelay', () => {
eventService.emit('private-credential-toggled-to-private', event);
expect(telemetry.track).toHaveBeenCalledWith('User made credential private', {
expect(telemetry.track).toHaveBeenCalledWith('User made credential end-user', {
user_id: 'user123',
user_role: GLOBAL_OWNER_ROLE.slug,
credential_type: 'gmailOAuth2',
@@ -1122,7 +1122,7 @@ describe('TelemetryEventRelay', () => {
eventService.emit('private-credential-toggled-to-static', event);
expect(telemetry.track).toHaveBeenCalledWith('User made credential static', {
expect(telemetry.track).toHaveBeenCalledWith('User made credential fixed', {
user_id: 'user123',
user_role: GLOBAL_OWNER_ROLE.slug,
credential_type: 'gmailOAuth2',
@@ -1145,7 +1145,7 @@ describe('TelemetryEventRelay', () => {
eventService.emit('private-credential-deleted', event);
expect(telemetry.track).toHaveBeenCalledWith('User deleted private credential', {
expect(telemetry.track).toHaveBeenCalledWith('User deleted end-user credential', {
user_id: 'user123',
user_role: GLOBAL_OWNER_ROLE.slug,
credential_type: 'gmailOAuth2',
@@ -1164,7 +1164,7 @@ describe('TelemetryEventRelay', () => {
eventService.emit('private-credential-user-connected', event);
expect(telemetry.track).toHaveBeenCalledWith('User connected to private credential', {
expect(telemetry.track).toHaveBeenCalledWith('User connected to end-user credential', {
user_id: 'user123',
user_role: undefined,
credential_type: 'gmailOAuth2',
@@ -1667,13 +1667,13 @@ describe('TelemetryEventRelay', () => {
user_id: 'user123',
version_cli: N8N_VERSION,
workflow_id: 'workflow123',
used_private_credentials: false,
private_credentials_attempted_count: 0,
private_credentials_resolved_count: 0,
used_end_user_credentials: false,
end_user_credentials_attempted_count: 0,
end_user_credentials_resolved_count: 0,
});
});
it('should set `used_private_credentials` when a private credential resolution was attempted but failed', async () => {
it('should set `used_end_user_credentials` when an end-user credential resolution was attempted but failed', async () => {
const event: RelayEventMap['workflow-post-execute'] = {
workflow: mock<IWorkflowDb>({
id: 'workflow123',
@@ -1701,14 +1701,14 @@ describe('TelemetryEventRelay', () => {
expect(telemetry.trackWorkflowExecution).toHaveBeenCalledWith(
expect.objectContaining({
used_private_credentials: true,
private_credentials_attempted_count: 1,
private_credentials_resolved_count: 0,
used_end_user_credentials: true,
end_user_credentials_attempted_count: 1,
end_user_credentials_resolved_count: 0,
}),
);
});
it('should count attempted vs resolved private credentials and the effective resolver', async () => {
it('should count attempted vs resolved end-user credentials and the effective resolver', async () => {
dynamicCredentialsProxy.getEffectiveResolverId.mockReturnValueOnce('system-n8n');
const event: RelayEventMap['workflow-post-execute'] = {
@@ -1738,9 +1738,9 @@ describe('TelemetryEventRelay', () => {
expect(telemetry.trackWorkflowExecution).toHaveBeenCalledWith(
expect.objectContaining({
used_private_credentials: true,
private_credentials_attempted_count: 2,
private_credentials_resolved_count: 1,
used_end_user_credentials: true,
end_user_credentials_attempted_count: 2,
end_user_credentials_resolved_count: 1,
credential_resolver_id: 'system-n8n',
}),
);
@@ -721,7 +721,7 @@ export class TelemetryEventRelay extends EventRelay {
projectId,
projectType,
}: RelayEventMap['private-credential-created']) {
this.telemetry.track('User created private credential', {
this.telemetry.track('User created end-user credential', {
user_id: user.id,
user_role: user.role?.slug,
credential_type: credentialType,
@@ -736,7 +736,7 @@ export class TelemetryEventRelay extends EventRelay {
credentialId,
credentialType,
}: RelayEventMap['private-credential-toggled-to-private']) {
this.telemetry.track('User made credential private', {
this.telemetry.track('User made credential end-user', {
user_id: user.id,
user_role: user.role?.slug,
credential_type: credentialType,
@@ -749,7 +749,7 @@ export class TelemetryEventRelay extends EventRelay {
credentialId,
credentialType,
}: RelayEventMap['private-credential-toggled-to-static']) {
this.telemetry.track('User made credential static', {
this.telemetry.track('User made credential fixed', {
user_id: user.id,
user_role: user.role?.slug,
credential_type: credentialType,
@@ -762,7 +762,7 @@ export class TelemetryEventRelay extends EventRelay {
credentialId,
credentialType,
}: RelayEventMap['private-credential-connections-cleared']) {
this.telemetry.track('User cleared private credential connections', {
this.telemetry.track('User cleared end-user credential connections', {
user_id: user.id,
user_role: user.role?.slug,
credential_type: credentialType,
@@ -775,7 +775,7 @@ export class TelemetryEventRelay extends EventRelay {
credentialId,
credentialType,
}: RelayEventMap['private-credential-deleted']) {
this.telemetry.track('User deleted private credential', {
this.telemetry.track('User deleted end-user credential', {
user_id: user.id,
user_role: user.role?.slug,
credential_type: credentialType,
@@ -790,7 +790,7 @@ export class TelemetryEventRelay extends EventRelay {
supportsManagedAuth,
usesManagedAuth,
}: RelayEventMap['private-credential-user-connected']) {
this.telemetry.track('User connected to private credential', {
this.telemetry.track('User connected to end-user credential', {
user_id: user.id,
user_role: user.role?.slug,
credential_type: credentialType,
@@ -1194,9 +1194,9 @@ export class TelemetryEventRelay extends EventRelay {
version_cli: N8N_VERSION,
success: false,
...executionTelemetryProperties,
used_private_credentials: privateCredentialsAttemptedCount > 0,
private_credentials_attempted_count: privateCredentialsAttemptedCount,
private_credentials_resolved_count: privateCredentialsResolvedCount,
used_end_user_credentials: privateCredentialsAttemptedCount > 0,
end_user_credentials_attempted_count: privateCredentialsAttemptedCount,
end_user_credentials_resolved_count: privateCredentialsResolvedCount,
};
if (privateCredentialsAttemptedCount > 0) {
@@ -1300,11 +1300,11 @@ export class TelemetryEventRelay extends EventRelay {
is_managed: false,
eval_rows_left: null,
meta: JSON.stringify(workflow.meta),
used_private_credentials: telemetryProperties.used_private_credentials,
private_credentials_attempted_count:
telemetryProperties.private_credentials_attempted_count,
private_credentials_resolved_count:
telemetryProperties.private_credentials_resolved_count,
used_end_user_credentials: telemetryProperties.used_end_user_credentials,
end_user_credentials_attempted_count:
telemetryProperties.end_user_credentials_attempted_count,
end_user_credentials_resolved_count:
telemetryProperties.end_user_credentials_resolved_count,
credential_resolver_id: telemetryProperties.credential_resolver_id,
...executionTelemetryProperties,
...TelemetryHelpers.resolveAIMetrics(workflow.nodes, this.nodeTypes),
+5 -5
View File
@@ -187,11 +187,11 @@ export interface IExecutionTrackProperties extends ITelemetryTrackProperties {
error_node_type?: string;
is_manual: boolean;
crashed?: boolean;
used_private_credentials?: boolean;
/** Number of nodes that attempted to resolve a private credential (regardless of success). */
private_credentials_attempted_count?: number;
/** Number of nodes that successfully resolved a private credential. */
private_credentials_resolved_count?: number;
used_end_user_credentials?: boolean;
/** Number of nodes that attempted to resolve an end-user credential (regardless of success). */
end_user_credentials_attempted_count?: number;
/** Number of nodes that successfully resolved an end-user credential. */
end_user_credentials_resolved_count?: number;
/** Effective resolver id the execution ran with (workflow override or seeded system resolver). */
credential_resolver_id?: string;
execution_source?: WorkflowExecutionSource;
@@ -455,7 +455,7 @@ export class LoadNodesAndCredentials {
// Create the main context establishment hooks property as a fixedCollection
const contextHooksProperty: INodeProperties = {
displayName: 'Identify user for dynamic credentials',
displayName: 'Identify user for end-user credentials',
name: 'contextEstablishmentHooks',
type: 'fixedCollection',
placeholder: 'Add User Identifier',
+2 -2
View File
@@ -382,8 +382,8 @@ export class Telemetry {
this.addExecutionTrackData(workflowId, sourceKey, execTime);
}
if (properties.used_private_credentials) {
this.track('Workflow execution with private credentials', properties);
if (properties.used_end_user_credentials) {
this.track('Workflow execution with end-user credentials', properties);
}
if (
@@ -742,7 +742,7 @@ describe('WorkflowValidationService', () => {
const result = await service.validateDynamicCredentials(nodes, mockNodeTypes);
expect(result.isValid).toBe(false);
expect(result.error).toContain('dynamic credentials');
expect(result.error).toContain('end-user credentials');
expect(result.error).toContain('"My OAuth2"');
expect(result.error).toContain('resolver');
});
@@ -816,7 +816,7 @@ describe('WorkflowValidationService', () => {
const result = await service.validateDynamicCredentials(nodes, mockNodeTypes);
expect(result.isValid).toBe(false);
expect(result.error).toContain('dynamic credentials');
expect(result.error).toContain('end-user credentials');
expect(result.error).toContain('"My OAuth2"');
expect(result.error).toContain('identity extractor');
});
@@ -842,7 +842,7 @@ describe('WorkflowValidationService', () => {
const result = await service.validateDynamicCredentials(nodes, mockNodeTypes);
expect(result.isValid).toBe(false);
expect(result.error).toContain('dynamic credentials');
expect(result.error).toContain('end-user credentials');
expect(result.error).toContain('identity extractor');
});
@@ -346,7 +346,7 @@ export class WorkflowValidationService {
triggers: { hasExternalIdentityTrigger: boolean; hasN8nIdentityTrigger: boolean },
): string | undefined {
if (!workflowResolverId) {
return `dynamic credentials (${credNames}) require a resolver to be configured.`;
return `end-user credentials (${credNames}) require a resolver to be configured.`;
}
const { hasExternalIdentityTrigger, hasN8nIdentityTrigger } = triggers;
@@ -361,7 +361,7 @@ export class WorkflowValidationService {
// Custom resolver: needs an external identity from the trigger.
return hasExternalIdentityTrigger
? undefined
: `dynamic credentials (${credNames}) require a trigger with an identity extractor configured. Please configure an identity extractor on the trigger node.`;
: `end-user credentials (${credNames}) require a trigger with an identity extractor configured. Please configure an identity extractor on the trigger node.`;
}
/** Collects the ids of all credentials referenced by enabled nodes. */
@@ -124,7 +124,7 @@ describe('ResolversView', () => {
const { getByText } = renderComponent({ pinia });
await waitFor(() => {
expect(getByText('Resolve private credentials from user identity')).toBeInTheDocument();
expect(getByText('Resolve end-user 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 private credentials from user identity')).toBeInTheDocument();
expect(getByText('Resolve end-user credentials from user identity')).toBeInTheDocument();
});
// Now the Add Resolver button should be available
@@ -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 private credentials from user identity
Resolve end-user credentials from user identity
</N8nHeading>
<div>
{{ i18n.baseText('credentialResolver.view.description') }}
@@ -14,7 +14,7 @@ export class DynamicCredentialCheck implements INodeType {
group: ['transform'],
version: 1,
description:
'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.',
'Checks whether the triggering user has the required end-user credential configured. Routes to "Ready" or "Not Ready" and returns auth URLs when the credential is missing.',
defaults: {
name: 'Check Credential Status',
},