fix(core): Expose 1Password fields for secret preview and autocomplete (#40538)

This commit is contained in:
Nour Alhadi Mahmoud 2026-10-07 16:23:24 +00:00 committed by GitHub
parent c194d22b5c
commit bef5f3f97a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 5 deletions

View File

@ -219,7 +219,12 @@ describe('OnePasswordProvider', () => {
});
expect(provider.getSecret('API Key')).toEqual({ key: 'sk-abc123' });
expect(provider.getSecret('SSH Key')).toEqual({ private_key: 'ssh-rsa AAAA...' });
expect(provider.getSecretNames()).toHaveLength(3);
expect(provider.getSecretNames()).toEqual([
'Database Credentials.username',
'Database Credentials.password',
'API Key.key',
'SSH Key.private_key',
]);
});
it('should skip items without fields', async () => {
@ -342,5 +347,9 @@ describe('OnePasswordProvider', () => {
it('should return false for non-existent secrets', () => {
expect(provider.hasSecret('non-existent')).toBe(false);
});
it('should return no field names before secrets are loaded', () => {
expect(provider.getSecretNames()).toEqual([]);
});
});
});

View File

@ -193,8 +193,10 @@ export class OnePasswordProvider extends SecretsProvider {
return name in this.cachedSecrets;
}
getSecretNames() {
return Object.keys(this.cachedSecrets);
getSecretNames(): string[] {
return Object.entries(this.cachedSecrets).flatMap(([itemName, fields]) =>
Object.keys(fields).map((fieldName) => `${itemName}.${fieldName}`),
);
}
private async verifyConnection(): Promise<void> {

View File

@ -232,6 +232,26 @@ describe('externalSecretsStore', () => {
});
describe('secretsAsObject', () => {
it.each(['secrets', 'projectSecrets'] as const)(
'should expose masked 1Password fields from %s for preview and autocomplete',
(scope) => {
setModuleSettings({ forProjects: true });
const store = useExternalSecretsStore();
store.state[scope] = {
onePassword: ['testing.credential', 'testing.username'],
};
expect(store.secretsAsObject).toEqual({
onePassword: {
testing: {
credential: '*********',
username: '*********',
},
},
});
},
);
it('should only contain the global secrets if forProjects is disabled', () => {
setLegacyMode();
const store = useExternalSecretsStore();

View File

@ -54,18 +54,19 @@ describe('TelemetryRecorder', () => {
test('redacts secrets from failure evidence', () => {
vi.stubEnv('CONTAINER_TELEMETRY_VERBOSE', '1');
vi.stubEnv('GITHUB_HEAD_REF', 'fix-1password-preview');
const log = vi.spyOn(console, 'log').mockImplementation(() => {});
const telemetry = new TelemetryRecorder({});
telemetry.startStage('service:proxy');
telemetry.finishStage(
'failure',
new Error('https://user:password@example.test?token=secret-value'),
new Error('https://user:test-password-value@example.test?token=secret-value'),
);
telemetry.flush(false, 'Authorization: Bearer secret-token');
const output = String(log.mock.calls[0]?.[0] ?? '');
expect(output).not.toContain('password');
expect(output).not.toContain('test-password-value');
expect(output).not.toContain('secret-value');
expect(output).not.toContain('secret-token');
expect(output).toContain('[REDACTED]');