v2.9.3
License enforcement
Published builds now ignore EXECBRO_API_URL and config.json apiUrl. Both were supported configuration, which made them a bypass switch: pointing the client at a local server that answers {"tier":"pro"} lifted the free-tier cap permanently, and unlike a patched package it survived every update. Source checkouts and forks still honour the override, so building from source is unaffected.
Revocation. An installation flagged server-side now stops with a message naming the reason and a support contact, instead of a cap message reporting a limit it never hit. The state persists past the offline grace window, since a flag is not month-scoped the way the monthly cap is.
Fixes
get_license_statusno longer printsPlan expires: [object Object]. The API sent a raw Firestore Timestamp; it now sends an ISO string, and the client omits the line rather than rendering anything it cannot parse. The same guard prevents a null expiry showing as1/1/1970.- Dev hot-reload loop:
dev:mcpnowexecs the server so nodemon owns it directly. Previously nodemon killed the wrapping shell and the server survived as an orphan holding port 8600, so every rebuild died silently onEADDRINUSEwhile the orphan kept serving stale code. A failed bind now names the port conflict and exits non-zero, and the dev log moved out of/tmp, which macOS reaps after three days.
No tool signatures changed in this release.