44 * @vitest -environment node
55 */
66import {
7+ dbChainMock ,
8+ dbChainMockFns ,
79 encryptionMock ,
810 encryptionMockFns ,
911 loggingSessionMock ,
@@ -34,6 +36,8 @@ const {
3436 flagState : { isBillingEnabled : false , isFreeApiDeploymentGateEnabled : true } ,
3537} ) )
3638
39+ vi . mock ( '@sim/db' , ( ) => dbChainMock )
40+
3741vi . mock ( '@/lib/billing/core/api-access' , ( ) => ( {
3842 isWorkspaceApiExecutionEntitled : mockIsWorkspaceApiExecutionEntitled ,
3943} ) )
@@ -480,6 +484,7 @@ describe('assertChatEmbedAllowed', () => {
480484 flagState . isBillingEnabled = true
481485 flagState . isFreeApiDeploymentGateEnabled = true
482486 mockIsWorkspaceApiExecutionEntitled . mockResolvedValue ( true )
487+ dbChainMockFns . limit . mockResolvedValue ( [ { workspaceId : 'ws-1' } ] )
483488 } )
484489
485490 it ( 'returns 403 for a cross-site origin when the owner is on the free plan' , async ( ) => {
@@ -501,6 +506,17 @@ describe('assertChatEmbedAllowed', () => {
501506 expect ( res ) . toBeNull ( )
502507 } )
503508
509+ it ( 'returns 403 for a cross-site origin when the workflow has no active workspace' , async ( ) => {
510+ dbChainMockFns . limit . mockResolvedValueOnce ( [ ] )
511+ const res = await assertChatEmbedAllowed (
512+ chatRequest ( 'https://evil.example.com' ) ,
513+ 'wf-1' ,
514+ 'req-1'
515+ )
516+ expect ( res ?. status ) . toBe ( 403 )
517+ expect ( mockIsWorkspaceApiExecutionEntitled ) . not . toHaveBeenCalled ( )
518+ } )
519+
504520 it ( 'allows a first-party *.sim.ai origin without gating' , async ( ) => {
505521 const res = await assertChatEmbedAllowed ( chatRequest ( 'https://chat.sim.ai' ) , 'wf-1' , 'req-1' )
506522 expect ( res ) . toBeNull ( )
0 commit comments