Orchestrates the scan: invokes each enabled layer in turn,
collects LayerResults, and returns a Report.
Layers are run sequentially (not concurrently) so that terminal output stays readable in the streaming formatter and so that resource-heavy scanners like semgrep don't dogpile a laptop.
Layers never raise — failures land as %LayerResult{status: :error}.
The runner additionally guards every callback with a try, so a
bug in one layer can't take the whole scan down.
Summary
Functions
@spec run( [module()], keyword() ) :: MobDev.SecurityScan.Report.t()
Runs the listed layers in order. opts is forwarded to each
layer's run/1 callback. The optional :on_layer_start and
:on_layer_done callbacks let the formatter stream progress
to the terminal as layers complete.