Skip to content

Commit 1a37ec6

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
refactor(oracle-epm): narrow shared infrastructure changes
1 parent 849968a commit 1a37ec6

4 files changed

Lines changed: 17 additions & 330 deletions

File tree

apps/sim/lib/credentials/orchestration/index.test.ts

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,6 @@ describe('performUpdateCredential — service-account secret rotation', () => {
286286
it('carries the stored dataCenter forward for a client-credential reconnect', async () => {
287287
mockCredential({ providerId: 'zoho-desk-service-account', displayName: 'Acme Desk' })
288288
mockIsClientCredentialAccountProviderId.mockReturnValue(true)
289-
mockGetClientCredentialAccountDescriptor.mockReturnValue({
290-
fields: [{ id: 'dataCenter' }],
291-
} as never)
292289
mockStoredBlob({ type: 'client_credential_account', dataCenter: 'eu' })
293290
mockVerifyAndBuildServiceAccountSecret.mockResolvedValue({
294291
providerId: 'zoho-desk-service-account',
@@ -334,7 +331,6 @@ describe('performUpdateCredential — service-account secret rotation', () => {
334331
mockIsClientCredentialAccountProviderId.mockReturnValue(true)
335332
mockGetClientCredentialAccountDescriptor.mockReturnValue({
336333
defaultAuthMethod: 'client_credentials',
337-
fields: [],
338334
} as never)
339335
mockStoredBlob({
340336
type: 'client_credential_account',
@@ -418,42 +414,6 @@ describe('performUpdateCredential — service-account secret rotation', () => {
418414
)
419415
})
420416

421-
it('threads Oracle EPM integration-user fields through reconnect without reading old secrets', async () => {
422-
mockCredential({
423-
providerId: 'oracle-epm-service-account',
424-
displayName: 'Production EPM',
425-
})
426-
mockIsClientCredentialAccountProviderId.mockReturnValue(true)
427-
mockGetClientCredentialAccountDescriptor.mockReturnValue({
428-
fields: [{ id: 'orgId' }, { id: 'clientId' }, { id: 'clientSecret' }],
429-
} as never)
430-
mockStoredBlob({ type: 'client_credential_account' })
431-
mockVerifyAndBuildServiceAccountSecret.mockResolvedValue({
432-
providerId: 'oracle-epm-service-account',
433-
encryptedServiceAccountKey: 'new-cipher',
434-
displayName: 'Production EPM',
435-
auditMetadata: {},
436-
})
437-
438-
await performUpdateCredential({
439-
credentialId: 'cred-1',
440-
userId: 'user-1',
441-
orgId: 'https://epm.example.com/gateway',
442-
clientId: 'integration.user@example.com',
443-
clientSecret: 'rotated-password',
444-
})
445-
446-
expect(mockDecryptSecret).not.toHaveBeenCalled()
447-
expect(mockVerifyAndBuildServiceAccountSecret).toHaveBeenCalledWith(
448-
'oracle-epm-service-account',
449-
expect.objectContaining({
450-
orgId: 'https://epm.example.com/gateway',
451-
clientId: 'integration.user@example.com',
452-
clientSecret: 'rotated-password',
453-
})
454-
)
455-
})
456-
457417
it('surfaces a rebuild failure as a validation error and writes nothing', async () => {
458418
mockCredential()
459419
mockStoredBlob({ type: 'service_account', client_email: OLD_EMAIL })

apps/sim/lib/credentials/orchestration/index.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,12 @@ export async function updateCredentialRecord(
292292
// credential back to the US accounts server. Carry the stored value forward
293293
// when the caller did not supply one.
294294
const isClientCredentialProvider = isClientCredentialAccountProviderId(providerId)
295-
const clientCredentialDescriptor = isClientCredentialProvider
296-
? getClientCredentialAccountDescriptor(providerId)
297-
: undefined
298-
const storesDataCenter = Boolean(
299-
clientCredentialDescriptor?.fields.some((field) => field.id === 'dataCenter')
300-
)
301-
const needsStoredDataCenter = params.dataCenter === undefined && storesDataCenter
295+
const needsStoredDataCenter = params.dataCenter === undefined && isClientCredentialProvider
302296
// Only a multi-grant provider stores these, so single-grant ones must not
303297
// pay for a row read + decrypt that can only ever return undefined.
304-
const isMultiGrantProvider = Boolean(clientCredentialDescriptor?.defaultAuthMethod)
298+
const isMultiGrantProvider = Boolean(
299+
getClientCredentialAccountDescriptor(providerId)?.defaultAuthMethod
300+
)
305301
const needsStoredAuthMethod = params.authMethod === undefined && isMultiGrantProvider
306302
const needsStoredUsername = params.username === undefined && isMultiGrantProvider
307303

apps/sim/lib/oauth/token-resolution.test.ts

Lines changed: 0 additions & 219 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ const {
88
mockCaptureServerEvent,
99
mockExecuteManagedToken,
1010
mockGetCredential,
11-
mockGetServiceConfigByProviderId,
1211
mockGetToolMetadata,
1312
mockRecordAudit,
1413
mockRefreshTokenIfNeeded,
@@ -19,7 +18,6 @@ const {
1918
mockCaptureServerEvent: vi.fn(),
2019
mockExecuteManagedToken: vi.fn(),
2120
mockGetCredential: vi.fn(),
22-
mockGetServiceConfigByProviderId: vi.fn(),
2321
mockGetToolMetadata: vi.fn(),
2422
mockRecordAudit: vi.fn(),
2523
mockRefreshTokenIfNeeded: vi.fn(),
@@ -80,14 +78,7 @@ vi.mock('@/tools/metadata', () => ({
8078
}))
8179

8280
vi.mock('@/lib/oauth/utils', () => ({
83-
credentialProviderMatchesService: (
84-
credentialProviderId: string,
85-
service: { providerId: string; serviceAccountProviderId?: string }
86-
) =>
87-
credentialProviderId === service.providerId ||
88-
credentialProviderId === service.serviceAccountProviderId,
8981
getCanonicalScopesForProvider: vi.fn().mockReturnValue([]),
90-
getServiceConfigByProviderId: mockGetServiceConfigByProviderId,
9182
}))
9283

9384
import { OrchestrationError } from '@/lib/core/orchestration/types'
@@ -360,10 +351,6 @@ describe('resolveCredentialAccessToken', () => {
360351
mockGetToolMetadata.mockReturnValue({
361352
oauth: { required: true, provider: 'google', requiredScopes: ['scope-a'] },
362353
})
363-
mockGetServiceConfigByProviderId.mockReturnValue({
364-
providerId: 'google',
365-
serviceAccountProviderId: 'google-service-account',
366-
})
367354
})
368355

369356
it('authenticates and delegates non-managed credentials without a second account lookup', async () => {
@@ -424,212 +411,6 @@ describe('resolveCredentialAccessToken', () => {
424411
})
425412
})
426413

427-
it('rejects a credential whose provider does not match the tool service', async () => {
428-
mockResolveOAuthAccountId.mockResolvedValue({
429-
accountId: 'account-1',
430-
credentialId: 'credential-1',
431-
credentialType: 'service_account',
432-
providerId: 'oracle-epm-service-account',
433-
usedCredentialTable: true,
434-
})
435-
mockAuthorizeCredentialUseForAuth.mockResolvedValue({
436-
ok: true,
437-
requesterUserId: 'user-1',
438-
credentialOwnerUserId: 'owner-1',
439-
workspaceId: 'ws-1',
440-
resolvedCredentialId: 'credential-1',
441-
})
442-
443-
const result = await resolveCredentialAccessToken({
444-
requestId: 'req-1',
445-
credentialId: 'credential-1',
446-
toolId: 'gmail_send',
447-
authenticate,
448-
})
449-
450-
expect(result).toEqual({
451-
ok: false,
452-
status: 403,
453-
code: 'CREDENTIAL_PROVIDER_MISMATCH',
454-
error: 'Credential does not match the tool service',
455-
})
456-
expect(mockGetServiceConfigByProviderId).toHaveBeenCalledWith('google')
457-
expect(authenticate).toHaveBeenCalledTimes(1)
458-
expect(mockResolveServiceAccountToken).not.toHaveBeenCalled()
459-
})
460-
461-
it('does not reveal provider mismatches before credential authorization succeeds', async () => {
462-
mockResolveOAuthAccountId.mockResolvedValue({
463-
accountId: 'credential-1',
464-
credentialId: 'credential-1',
465-
credentialType: 'service_account',
466-
providerId: 'oracle-epm-service-account',
467-
usedCredentialTable: true,
468-
})
469-
mockAuthorizeCredentialUseForAuth.mockResolvedValue({ ok: false, error: 'Unauthorized' })
470-
471-
await expect(
472-
resolveCredentialAccessToken({
473-
requestId: 'req-1',
474-
credentialId: 'credential-1',
475-
toolId: 'gmail_send',
476-
authenticate,
477-
})
478-
).resolves.toEqual({ ok: false, status: 403, error: 'Unauthorized' })
479-
expect(authenticate).toHaveBeenCalledTimes(1)
480-
expect(mockResolveServiceAccountToken).not.toHaveBeenCalled()
481-
})
482-
483-
it('accepts a shared service-account provider registered by the tool service', async () => {
484-
mockResolveOAuthAccountId.mockResolvedValue({
485-
accountId: 'credential-1',
486-
credentialId: 'credential-1',
487-
credentialType: 'service_account',
488-
providerId: 'oracle-epm-service-account',
489-
usedCredentialTable: true,
490-
})
491-
mockGetServiceConfigByProviderId.mockReturnValue({
492-
providerId: 'synthetic-oracle-child',
493-
serviceAccountProviderId: 'oracle-epm-service-account',
494-
})
495-
mockAuthorizeCredentialUseForAuth.mockResolvedValue({
496-
ok: true,
497-
requesterUserId: 'user-1',
498-
credentialOwnerUserId: 'owner-1',
499-
workspaceId: 'ws-1',
500-
resolvedCredentialId: 'credential-1',
501-
})
502-
mockResolveServiceAccountToken.mockResolvedValue({
503-
accessToken: 'basic-token',
504-
instanceUrl: 'https://epm.example.com',
505-
})
506-
507-
const result = await resolveCredentialAccessToken({
508-
requestId: 'req-1',
509-
credentialId: 'credential-1',
510-
toolId: 'synthetic_oracle_tool',
511-
authenticate,
512-
})
513-
514-
expect(result).toEqual({
515-
ok: true,
516-
token: {
517-
accessToken: 'basic-token',
518-
credentialType: 'service_account',
519-
instanceUrl: 'https://epm.example.com',
520-
},
521-
})
522-
})
523-
524-
it('preserves an existing service-account tool without OAuth service metadata', async () => {
525-
mockResolveOAuthAccountId.mockResolvedValue({
526-
accountId: 'credential-1',
527-
credentialId: 'credential-1',
528-
credentialType: 'service_account',
529-
providerId: 'claude-platform-service-account',
530-
usedCredentialTable: true,
531-
})
532-
mockGetToolMetadata.mockReturnValue({ oauth: undefined })
533-
mockAuthorizeCredentialUseForAuth.mockResolvedValue({
534-
ok: true,
535-
requesterUserId: 'user-1',
536-
credentialOwnerUserId: 'owner-1',
537-
workspaceId: 'ws-1',
538-
resolvedCredentialId: 'credential-1',
539-
})
540-
mockResolveServiceAccountToken.mockResolvedValue({ accessToken: 'workspace-api-key' })
541-
542-
await expect(
543-
resolveCredentialAccessToken({
544-
requestId: 'req-1',
545-
credentialId: 'credential-1',
546-
toolId: 'managed_agent_run_session',
547-
authenticate,
548-
})
549-
).resolves.toEqual({
550-
ok: true,
551-
token: {
552-
accessToken: 'workspace-api-key',
553-
credentialType: 'service_account',
554-
apiDomain: undefined,
555-
authStyle: undefined,
556-
cloudId: undefined,
557-
domain: undefined,
558-
instanceUrl: undefined,
559-
},
560-
})
561-
expect(mockGetServiceConfigByProviderId).not.toHaveBeenCalled()
562-
expect(mockResolveServiceAccountToken).toHaveBeenCalledWith(
563-
'credential-1',
564-
'claude-platform-service-account',
565-
[],
566-
undefined
567-
)
568-
})
569-
570-
it('fails closed when declared tool service metadata has no registered service', async () => {
571-
mockResolveOAuthAccountId.mockResolvedValue({
572-
accountId: 'credential-1',
573-
credentialId: 'credential-1',
574-
credentialType: 'service_account',
575-
providerId: 'oracle-epm-service-account',
576-
usedCredentialTable: true,
577-
})
578-
mockGetServiceConfigByProviderId.mockReturnValue(null)
579-
mockAuthorizeCredentialUseForAuth.mockResolvedValue({
580-
ok: true,
581-
requesterUserId: 'user-1',
582-
credentialOwnerUserId: 'owner-1',
583-
workspaceId: 'ws-1',
584-
resolvedCredentialId: 'credential-1',
585-
})
586-
587-
await expect(
588-
resolveCredentialAccessToken({
589-
requestId: 'req-1',
590-
credentialId: 'credential-1',
591-
toolId: 'synthetic_oracle_tool',
592-
authenticate,
593-
})
594-
).resolves.toEqual({
595-
ok: false,
596-
status: 403,
597-
code: 'CREDENTIAL_PROVIDER_MISMATCH',
598-
error: 'Credential does not match the tool service',
599-
})
600-
expect(authenticate).toHaveBeenCalledTimes(1)
601-
expect(mockResolveServiceAccountToken).not.toHaveBeenCalled()
602-
})
603-
604-
it('rejects a mismatched OAuth account after loading its authoritative provider', async () => {
605-
mockResolveOAuthAccountId.mockResolvedValue({
606-
accountId: 'account-1',
607-
usedCredentialTable: true,
608-
})
609-
mockAuthorizeCredentialUseForAuth.mockResolvedValue({
610-
ok: true,
611-
requesterUserId: 'user-1',
612-
credentialOwnerUserId: 'owner-1',
613-
resolvedCredentialId: 'account-1',
614-
})
615-
mockGetCredential.mockResolvedValue({ providerId: 'salesforce' })
616-
617-
const result = await resolveCredentialAccessToken({
618-
requestId: 'req-1',
619-
credentialId: 'credential-1',
620-
toolId: 'gmail_send',
621-
authenticate,
622-
})
623-
624-
expect(result).toEqual({
625-
ok: false,
626-
status: 403,
627-
code: 'CREDENTIAL_PROVIDER_MISMATCH',
628-
error: 'Credential does not match the tool service',
629-
})
630-
expect(mockRefreshTokenIfNeeded).not.toHaveBeenCalled()
631-
})
632-
633414
it('rejects a managed credential when no delegation resolver is wired', async () => {
634415
mockResolveOAuthAccountId.mockResolvedValue(MANAGED_RESOLVED)
635416

0 commit comments

Comments
 (0)