I would definitely approach this from what decompilation tools are available and how user friendly they are. With .NET (though this may not be true now), I could decompile a release into somewhat full featured source code files and their respective project containers. Like beam languages, the code is interpreted as MSIL but being able to read that bytecode or put it in my IDE of choice is no simple task.
If tools existed to only view MSIL I’d personally consider it a small threat because the average developer isn’t going to choose to work at that level. The same would be true for Erlang’s bytecode. If code can be decompiled to a relatively working project, that’s when I’d be concerned with obfuscation.
I suspect the average Elixir developer when confronted with a release and no source is likely not too concerned to reverse engineer intellectual property from bytecode. There will always be determined hackers. As an anecdote, JavaScript obfuscation absolutely does not stop me from changing Vue to developer mode so I can use Vue tools extensions to analyze the components of popular websites. JS can obfuscate function names but magic strings have to leak through.
Taking your API example, anyone using your library would have to be obfuscated with it. Otherwise they’d have to use function names like MyModule.c() or some random thing that would ideally change every obfuscation run. Obfuscation in JS works because the source is bundled together then minified. If I were a developer presented with a library that required I also obfuscate my application, I’d likely look for a new library. What about connecting with iex? Would I have to run MyModule.my_function() or MyModule.c()? I’d use .c() exactly once before I ripped it out. You could be in the enterprise space where I’d be forced to use your library but I wouldn’t willfully choose something that put those kind of stumbling blocks in my path. That’s only my 2 cents but those would be the things I wrestled with.
Having said all that, you may want to look at DockYard’s BeaconCMS (https://github.com/BeaconCMS/beacon/tree/main/lib/beacon/loader) as pages and components are generated with unique names. Its been a minute since I analyzed how the modules in that directory worked but in the console you can see your components have hashed names to prevent collisions. My guess is this is so one CMS can handle multi-tenancy or multiple sites without one page or component stepping on the other. This may be what you’re looking for but the word “obfuscate” obviously triggers some things with me.






















