Octane keeps the application in memory between requests, so a static property set during one request is visible to the next one — including one belonging to a different user.
final class CurrentTenant
{
private static ?Tenant $tenant = null;
public static function set(Tenant $t): void
{
self::$tenant = $t; // survives the request
}
}
// grep for the shape, before switching anything on:
// private static $
// public static function get
// a singleton holding a Request, User or Tenant
Every framework built on the shared-nothing model has code that relies on the process dying, and almost none of it is marked. Static caches are the visible half; the invisible half is a service registered as a singleton in the container that captured a request-scoped object in its constructor. Octane’s listeners reset the container between requests and cannot reset a static, which is why an audit has to happen before the switch rather than after the first incident.