created_at?->lt(CarbonImmutable::parse($startedAt))) { return self::LEGACY; } return self::bucket((string) $user->getKey()); } /** * Deterministic, evenly-split bucket for a post-start user. The 'price:' salt * decouples this split from every other crc32-based experiment on the same id * (e.g. SubscriptionExperiment), so the two arms are independent. Keep this the * single source of truth — the funnel report mirrors it to attribute users * without reading Pennant per row. */ public static function bucket(string $key): string { return crc32('price:'.$key) % 2 === 0 ? self::CONTROL : self::HIGH; } }