diff --git a/server/src/__tests__/access-service.test.ts b/server/src/__tests__/access-service.test.ts index ab78f7a0b64..f1cbb2fb63d 100644 --- a/server/src/__tests__/access-service.test.ts +++ b/server/src/__tests__/access-service.test.ts @@ -275,6 +275,8 @@ describeEmbeddedPostgres("access service", () => { transport: "mcp_remote", authKind: "oauth", credentialPolicy: "per_user", + status: "active", + enabled: true, }).returning().then((rows) => rows[0]!); const definition = await db.insert(userSecretDefinitions).values({ companyId: company.id, @@ -329,9 +331,19 @@ describeEmbeddedPostgres("access service", () => { expect(await db.select().from(connectionGrants).where(eq(connectionGrants.id, grant.id))) .toEqual([expect.objectContaining({ status: "revoked", credentialSecretRefs: [] })]); expect(await db.select().from(connectionGrants).where(eq(connectionGrants.id, organizationGrant.id))) - .toEqual([expect.objectContaining({ credentialSecretRefs: [] })]); + .toEqual([expect.objectContaining({ + status: "needs_reauthorization", + isDefault: false, + credentialSecretRefs: [], + })]); expect(await db.select().from(toolConnections).where(eq(toolConnections.id, connection.id))) - .toEqual([expect.objectContaining({ credentialSecretRefs: [] })]); + .toEqual([expect.objectContaining({ + status: "draft", + enabled: false, + healthStatus: "missing_secret", + lastError: "oauth_reauthorization_required", + credentialSecretRefs: [], + })]); expect(await db.select().from(toolAccessAuditEvents).where(eq(toolAccessAuditEvents.reasonCode, "membership_removed"))) .toHaveLength(1); }); diff --git a/server/src/services/access.ts b/server/src/services/access.ts index 58e5265ead2..23472b3aeba 100644 --- a/server/src/services/access.ts +++ b/server/src/services/access.ts @@ -87,6 +87,7 @@ export function accessService(db: Db) { const [grantRefs, connectionRefs] = await Promise.all([ tx.select({ id: connectionGrants.id, + status: connectionGrants.status, credentialSecretRefs: connectionGrants.credentialSecretRefs, }).from(connectionGrants).where(eq(connectionGrants.companyId, companyId)), tx.select({ @@ -99,7 +100,14 @@ export function accessService(db: Db) { (ref) => !removedSecretIds.has(ref.secretId), ); if (credentialSecretRefs.length !== grant.credentialSecretRefs.length) { - await tx.update(connectionGrants).set({ credentialSecretRefs, updatedAt: now }) + await tx.update(connectionGrants).set({ + credentialSecretRefs, + ...(grant.status === "revoked" ? {} : { + status: "needs_reauthorization" as const, + isDefault: false, + }), + updatedAt: now, + }) .where(eq(connectionGrants.id, grant.id)); } } @@ -108,7 +116,15 @@ export function accessService(db: Db) { (ref) => !removedSecretIds.has(ref.secretId), ); if (credentialSecretRefs.length !== connection.credentialSecretRefs.length) { - await tx.update(toolConnections).set({ credentialSecretRefs, updatedAt: now }) + await tx.update(toolConnections).set({ + credentialSecretRefs, + status: "draft", + enabled: false, + healthStatus: "missing_secret", + healthMessage: "Personal credential owner no longer has company access. Reauthorize this connection.", + lastError: "oauth_reauthorization_required", + updatedAt: now, + }) .where(eq(toolConnections.id, connection.id)); } }