Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ded6367
feat(support): add Hypervel CarbonImmutable
binaryfire Jul 23, 2026
221fada
fix(facade-documenter): resolve owner docblock types
binaryfire Jul 23, 2026
e76cb8d
feat(support): make immutable dates the factory default
binaryfire Jul 23, 2026
4355112
feat(support): make DataObject date targets exact
binaryfire Jul 23, 2026
be9bd3b
feat(foundation): align the clock and Carbon cleanup
binaryfire Jul 23, 2026
774a4d1
feat(testing): route time travel through DateFactory
binaryfire Jul 23, 2026
d5d9639
fix(foundation): retain immutable lifecycle timestamps
binaryfire Jul 23, 2026
978a674
refactor(foundation): keep maintenance dates immutable
binaryfire Jul 23, 2026
e479c4b
fix(http): parse request dates through the configured factory
binaryfire Jul 23, 2026
9aef738
fix(console): make scheduling immutable-safe
binaryfire Jul 23, 2026
4989a4a
feat(database): make Eloquent dates immutable by default
binaryfire Jul 23, 2026
7181562
fix(validation): accept immutable parsed dates
binaryfire Jul 23, 2026
4bfb275
fix(queue): accept immutable mail and notification retries
binaryfire Jul 23, 2026
0313636
refactor(auth): use immutable authentication deadlines
binaryfire Jul 23, 2026
4aef2e2
refactor(cache): make expiry records immutable
binaryfire Jul 23, 2026
a1f6cac
refactor(bus): canonicalize immutable batch dates
binaryfire Jul 23, 2026
da0cc8c
refactor(queue): use immutable worker deadlines
binaryfire Jul 23, 2026
55b9192
refactor(horizon): use canonical immutable timestamps
binaryfire Jul 23, 2026
b072d83
refactor(session): make session expiry immutable
binaryfire Jul 23, 2026
1790514
fix(grpc): prewarm protobuf descriptors before workers
binaryfire Jul 23, 2026
5d86aa0
refactor(collections): use immutable lazy clocks
binaryfire Jul 23, 2026
832d25b
refactor(http): use immutable expiry and signing dates
binaryfire Jul 23, 2026
f3feffa
refactor(telescope): use immutable entry dates
binaryfire Jul 23, 2026
badb963
fix(models): type cast dates through CarbonInterface
binaryfire Jul 23, 2026
f64bb97
refactor(testing): compare cookie expiry immutably
binaryfire Jul 23, 2026
91c7856
feat(testbench): make immutable dates the test default
binaryfire Jul 23, 2026
609a6cd
test(jwt): use the immutable framework clock
binaryfire Jul 23, 2026
45a008c
test(support): assert immutable date consumers
binaryfire Jul 23, 2026
7308468
test: align framework date fixtures with immutability
binaryfire Jul 23, 2026
ba0ef2d
docs: document immutable date behavior
binaryfire Jul 23, 2026
91e7c2f
docs: add immutable date upgrade guidance
binaryfire Jul 23, 2026
ee11066
docs: establish immutable date framework policy
binaryfire Jul 23, 2026
9f86184
docs: preserve historical date plan context
binaryfire Jul 23, 2026
76e3ff5
build: raise the Carbon minimum to 3.13.1
binaryfire Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ Build complete, long-term solutions, not MVPs or local workarounds. A broad chan
- **Prefer `timestamp` over `timestampTz` in migrations** — store times in UTC with plain `timestamp` columns, matching the normal convention in Laravel and Hypervel first-party migrations. Reserve `timestampTz` for columns that genuinely need database-level timezone semantics, such as integrating with an existing timezone-aware schema or columns written by clients in different session timezones. The schema API supports both — this is a column-choice convention, not an API restriction.
- **Guard optional event dispatches with `hasListeners()`** — before constructing and dispatching framework events, guard them with `hasListeners()` so hot paths skip event overhead when nobody is listening. Do not guard dispatches where dispatching is the side effect, such as jobs, broadcasts, webhooks, or command bus calls.
- **Use `Sleep::usleep()` / `Sleep::sleep()` for delays in source code** — `Sleep` is fakeable in tests. Use raw `sleep()` / `usleep()` only where real time must pass, such as test harnesses and external-process polling.
- **Use immutable dates by default** — Hypervel defaults to `Hypervel\Support\CarbonImmutable`, including where Laravel uses mutable Carbon. Create public or application-configurable dates through the `Date` facade or date helpers, and use exact `CarbonImmutable` for framework-owned internal or held values. Type configurable Carbon boundaries as `CarbonInterface` and native or third-party boundaries as `DateTimeInterface`. Capture the return value of every date modifier whose result must persist. Use `Hypervel\Support\Carbon` only for explicit mutable opt-out or conversion behavior.
- **Use typed config getters, no call-site defaults** — prefer `$config->string()`, `$config->integer()`, `$config->float()`, `$config->boolean()`, `$config->array()` over `$config->get()` for any key that can't legitimately be null. Typed getters fail fast on misconfiguration — an `InvalidArgumentException` naming the key, instead of a wrong type propagating silently — and give phpstan the real type. Defaults live in config files: `LoadConfiguration` merges the framework base config, and package providers must merge their defaults through `mergeConfigFrom()`. A call-site default is then dead code that can drift from the real default. Declare every key in the package's config file and call the getter without a default — a missing key then fails loudly instead of being silently papered over. Exceptions: bootstrap code that runs before or without config merging (e.g. `LoadConfiguration` itself), and genuinely nullable keys, which keep `get()`.
- **Env var naming** — ported config keeps its upstream env var names. New Hypervel-specific keys start with the config file's domain prefix (`SERVER_`, `APP_`) with the clearest name for the rest, e.g. `SERVER_WORKERS` for the `Constant::OPTION_WORKER_NUM` server option. If a config value mirrors another config key, reuse that key's env var instead of defining a duplicate — e.g. the Slack log channel username falls back to `APP_NAME`.
- **Use `resolve...Using` for Hypervel-owned config resolvers** — prefer this naming for callbacks that resolve config-derived values, unless an established Laravel domain convention already exists, such as `redirectUsing()`.
Expand Down Expand Up @@ -672,6 +673,7 @@ Run `./vendor/bin/phpstan` and `./vendor/bin/php-cs-fixer fix` without flags —

When porting Laravel packages, whether first-party or third-party, keep them as close to 1:1 with upstream as possible so future changes are easy to merge. The exceptions are:
- Modernizing PHP types (PHP 8.4+ features, strict types, strict comparisons)
- Converting mutable Laravel date construction to Hypervel's immutable date conventions, typing configurable factory output as `CarbonInterface`, and capturing date-modifier return values
- Converting container array access (`$app['events']`) to `make()`, and untyped `$config->get()` calls to the typed getters where the key isn't nullable (see Container and the typed-getter rule under Development Conventions)
- Adding Laravel-style title docblocks to methods (not classes — see Development Conventions)
- For ported Laravel packages: making them coroutine-safe, adding Swoole performance enhancements (e.g., static property caching), making them pass PHPStan
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
"league/flysystem-read-only": "^3.25.1",
"league/uri": "^7.5.1",
"monolog/monolog": "^3.1",
"nesbot/carbon": "^3.8.4",
"nesbot/carbon": "^3.13.1",
"nikic/php-parser": "^5.7",
"nunomaduro/termwind": "^2.0",
"nyholm/psr7": "^1.0",
Expand Down
4 changes: 4 additions & 0 deletions docs/ai/differences-vs-laravel.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ Hypervel caches more aggressively than Laravel: any class resolved via `make()`

- Supported drivers exclude Memcached, DynamoDB, MongoDB.

## Dates

- Hypervel's `Date` facade, `now()` / `today()` helpers, and ordinary Eloquent date casts return `Hypervel\Support\CarbonImmutable` by default. Assign date-modifier results (`$date = $date->addDay()`) when retaining the changed value. Applications that deliberately need Laravel's mutable default may configure `Date::use(Hypervel\Support\Carbon::class)` during boot.

## Event Dispatch

- **`hasListeners()` guards skip event construction when no listeners exist.** Framework code checks `hasListeners()` before constructing event objects. If nothing is listening, the event is never created or dispatched. This is a Hypervel-specific performance optimization — Laravel always constructs and dispatches events regardless of listeners.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Array Cache Request-Local Store and Worker-Array Store

## Historical status

This plan predates Hypervel's immutable date default. Its Carbon examples are preserved as implementation history; current cache expiry records use `Hypervel\Support\CarbonImmutable`. See [Make CarbonImmutable the Framework Default](2026-07-22-carbon-immutable-default.md) for the current date architecture.

## Goal

Make Hypervel's `array` cache store behave like Laravel developers expect in a long-lived Swoole worker: data written to the `array` store must be isolated to the current request, job, scheduled task, or other unit of work.
Expand Down
2 changes: 2 additions & 0 deletions docs/plans/2026-07-01-fortify-passkeys-port.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

> Superseded note: the Fortify password broker inference described in this historical plan was later removed by `2026-07-06-auth-guard-declared-password-brokers.md`. Guards now declare password brokers with `auth.guards.{guard}.passwords`; `Fortify::passwordBrokerName()` no longer exists.

> Date note: this plan predates Hypervel's immutable date default. Its mutable Carbon guidance is preserved as implementation history; configurable Eloquent date casts now return `Hypervel\Support\CarbonImmutable` by default and should be typed as `CarbonInterface`. See [Make CarbonImmutable the Framework Default](2026-07-22-carbon-immutable-default.md) for the current date architecture.

## Scope

Port Laravel Fortify and Laravel Passkeys Server into the Hypervel components monorepo, with Swoole coroutine safety, worker-lifetime performance, clean Hypervel-native APIs, full tests, and updated Boost documentation.
Expand Down
Loading
Loading