The usual way I’d approach the problem would be to de-couple the two things in some way, so that Core does not send events to Web, but instead publishes the events to something it knows. Like a GenEvent that’s in Core and it’s subscribers hook in from Web, or a pub/sub system (such https://github.com/phoenixframework/phoenix_pubsub or https://github.com/ostinelli/syn).
In either way, I would go with architecture where you publish events in Core and other apps can have their services listen to those events.
Create a behavior that defines the interface your Phoenix app exposes to the core app. Let’s say it has a function publish_record.
In your Phoenix app, create a module that implements the behavior, for instance by calling the Phoenix broadcast function.
In your core app, create another implementation that just calls IO.inspect, or whatever you want.
In the app config, store the implementation to use (i.e. the module name). You can set core to use the simulated implementation by default, and override this in your phoenix app to use the real one.
In core application code, retrieve the implementation module and call the function from it (mod.broadcast(...) where mod is a variable).
An alternative might be to make the core app depend on phoenix_broadcast and call its functions directly if the endpoint is running. I didn’t go that way because it made the two apps quite coupled, but YMMV!