Pre-EEP: BEAM-level in-app export visibility

I have opened a draft EEP for application-scoped function visibility in Erlang:

The proposal adds two module attributes:

-app(my_app).
-app_export([internal_helper/1]).

A function listed in -app_export/1 remains exported, but the BEAM only allows calls to it from modules declaring the same -app/1 value. Calls from modules in other app domains raise badappcall.

The motivation is to make internal APIs explicit and enforceable without adding new syntax or changing existing modules. This is related to EEP 5 and EEP 67, but differs by proposing runtime enforcement rather than only static or documentation-based visibility.

This is not intended as a security sandbox. A module can explicitly declare an app visibility domain, so the boundary is about encapsulation and accidental use, not preventing malicious code loaded into the node.

I am especially looking for feedback on:

  • whether -app/1 is the right attribute name, or whether it risks confusion with OTP application metadata;

  • whether explicit module metadata is preferable to deriving visibility from OTP application layout or code paths;

  • whether runtime enforcement is desirable for this boundary;

  • whether badappcall is the right error shape; and

  • whether the VM/JIT cost is acceptable if unrestricted exports keep the hot path to a predictable flag check.

A prototype exists, but I am preparing a clean public implementation fork separately. For now I would like feedback on the design and semantics.

2 Likes