CAP.PRESCAN.INDIRECT_CALL — Indirect call from a migration
- Category: safety
- Level: 0
- Stability: preview
- Suites: lint
This migration reaches its effect through your own code — (new Backfill)->run(), app(Importer::class)->handle() — the most common way around the side-effect catalog. The call resolves cleanly and appears in no framework catalog, so left alone it would be a silent pass while the effect happens one level below.
The pre-scan is pattern recognition, not taint analysis: it flags the call without following it into the class, because it cannot know whether run() sends a notification or formats a string. It flags conservatively because an undetermined costs you a shadow run while a silent pass could cost a sent message. A call on the migration's own method ($this->helper()), the framework, and pure value classes (Carbon, DateTime, Uuid) are not flagged. When you know a class is safe, add it to sqlens.capture.prescan.indirect_calls.allowlist — that is the intended way to state a known harmlessness.
Flagged
public function up(): void
{
Schema::table('users', fn (Blueprint $t) => $t->string('slug')->nullable());
// run() might send a notification or hit an API — pretend runs it
// for real and the capture cannot see what it does.
(new UserBackfill)->run();
}
Preferred
public function up(): void
{
Schema::table('users', fn (Blueprint $t) => $t->string('slug')->nullable());
}
// The backfill is a job the deploy dispatches after the migration, or
// a shadow run captures it against a throwaway database. If the class
// is known-safe, add it to
// sqlens.capture.prescan.indirect_calls.allowlist.