Phase 07 runtime migration. Post-Wave-1 Standard deployments that pre-dated
the edition gate may still carry enabled command-type hook rows in the DB;
those keep firing via the dispatcher after the UI stops letting users create
new ones. This helper flips them off at startup so live traffic never fires
a disabled-by-policy handler again.
- internal/hooks/migration_command_autodisable.go:
DisableLegacyCommandHooks(ctx, hookStore, edition). Standard only; Lite
returns early. Master-scope context + List(Enabled=true) → skip
non-command + source='builtin' rows → Update enabled=false. Per-row
WARN log with hook_id + tenant_id for audit; INFO summary when n>0.
Idempotent: second boot finds nothing.
- cmd/gateway_managed.go: invoke after builtin.Seed, BEFORE handler
registration so no HTTP/WS traffic races the migration.
- Tests (fake store, 5 cases):
* Standard with mixed rows → only command+source=ui gets disabled
* http + script/builtin + command/builtin rows untouched
* Idempotent second run → n=0
* Lite edition → n=0, nothing touched
* nil store → n=0, no error
* List error → propagated up
Note: Phase 04/05 never seed command-typed builtins, but the carve-out is
kept defensively so a future accidental builtin command row can't be
disabled by this migration.