ASM uses compile-time boundary checks to keep core runtime modules isolated from optional extension domains.
Compile-time Boundary rules are only one part of the contract. Runtime shape
ownership is now explicit too:
Zoiis the canonical boundary-schema layer for new dynamic ASM boundary work.ASM.Schema.ProviderOptions,ASM.Schema.Event, andASM.Schema.RemoteNodeown ASM-local runtime payloads.- provider-native CLI or protocol schemas stay in the provider repos instead of being copied into ASM.
NimbleOptionsremains at the public keyword ingress as a transitional adapter while schema equivalence is proven.
Compiler Setup
mix.exs enables the boundary compiler before the default Mix compilers:
compilers: [:boundary | Mix.compilers()]Boundary support is added as a compile-time dependency:
{:boundary, "~> 0.10.4", runtime: false}Declared Boundaries
Core boundary:
ASMwithdeps: []
Extension boundaries:
ASM.ExtensionsASM.Extensions.PersistenceASM.Extensions.RoutingASM.Extensions.PolicyASM.Extensions.RenderingASM.Extensions.WorkspaceASM.Extensions.PubSubASM.Extensions.ProviderASM.Extensions.ProviderSDK
Each extension boundary currently declares deps: [ASM].
Lifecycle Rule
Extension lifecycle ownership stays outside core application child specs:
- The core ASM OTP application starts core-only children.
- Host applications (or extension-owned supervisors) decide which extension processes to start.
This keeps both compile-time coupling and runtime ownership clean.
Enforcement Signal
Running compile with warnings-as-errors executes the boundary compiler:
mix compile --warnings-as-errors
Any core-to-extension dependency without a declared boundary dependency fails compilation.