Skip to content

Correct Auth lifecycle, token, and cache behavior - #473

Merged
binaryfire merged 14 commits into
0.4from
audit/auth-correctness-lifecycle-parity
Aug 5, 2026
Merged

Correct Auth lifecycle, token, and cache behavior#473
binaryfire merged 14 commits into
0.4from
audit/auth-correctness-lifecycle-parity

Conversation

@binaryfire

@binaryfire binaryfire commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR corrects Auth token validation, callable handling, password-broker lifecycle behavior, and Eloquent user-cache ownership. It also brings the audited Auth API and integration surface up to date with current Laravel where those behaviors fit Hypervel's coroutine model.

The result keeps request state coroutine-local and worker-lifetime services reusable. It does not add locks, retries, network calls, serialization layers, or compatibility wrappers.

For the complete design and decision record, see docs/plans/2026-08-05-1615-auth-correctness-lifecycle-and-current-parity.md.

Token and authorization behavior

  • Read TokenGuard inputs in their documented order and accept only non-empty strings without losing the valid string zero.
  • Apply configured input keys, storage keys, and token hashing during explicit credential validation.
  • Reflect closures, invokable objects, callable strings, and array callables through one correct Gate boundary.
  • Weakly cache object-callable guest metadata and clear that cache through the framework state-reset path.
  • Skip constructing observational Gate events when the active dispatcher has no listener while preserving event fakes.

Password broker lifecycle

  • Refresh already-resolved concrete password brokers when the event dispatcher binding changes.
  • Keep Event::fake() and Event::fakeFor() restoration correct without resolving unused managers or replacing custom broker contracts.
  • Construct password reset-link events only when they are observed.
  • Accept unit and backed enums at broker and guard identifier boundaries, including integer-backed zero.
  • Preserve existing manager extension points, named arguments, facade forwarding, and default-broker behavior.

Eloquent provider correctness

  • Restore the caller model's timestamp setting after remember-token writes, including exceptional saves.
  • Use the configured model as the single cache-key authority.
  • Register invalidation descriptors when a cached provider changes model.
  • Keep old and new keyspaces invalidatable while retaining only immutable store and prefix data rather than provider instances or duplicate model strings.

Configuration, metadata, and diagnostics

  • Add canonical verification expiry and authentication timebox settings to the shipped Auth configuration.
  • Remove redundant consumer defaults while keeping the intentional nested verification fallback for replaced application configuration.
  • Update verification guidance to document the configured link lifetime.
  • Declare the split Auth package's direct dependencies and discoverable providers.
  • Regenerate and cover enum-aware Auth and Password facade metadata.
  • Mark credential arrays and key material as sensitive so exception traces redact them.

Compatibility and performance

Supported Laravel-facing Auth signatures, guard and broker APIs, protected resolution hooks, event behavior, and facade entry points remain intact. Enum support is additive. Hypervel-specific corrections reject malformed native token inputs or fix behavior that already contradicted configured cache and token contracts.

Hot paths gain only bounded local type checks or existing listener lookups. The event changes avoid unused allocations and dispatch. No request path gains additional I/O, locking, polling, container-resolution loops, or unbounded retained state.

Verification

  • Full formatting, static analysis, parallel test, Testbench package, and dogfood gates pass through composer fix.
  • Auth unit and integration coverage passes, including real password reset, dispatcher rebinding, logout-device rehashing, and Eloquent cache behavior.
  • Redis-backed Auth cache coverage exercises the available serializer modes.
  • Affected Fortify coverage, facade generation and linting, package metadata checks, and focused follow-up regressions pass.
  • The final diff passes whitespace checks and a fresh caller, lifecycle, cache-key, API, coroutine-safety, performance, and dead-code review.

Summary by CodeRabbit

  • New Features

    • Authentication now supports enum-based guard and password-broker identifiers.
    • Improved token validation handles hashing, empty values, and multiple request sources more reliably.
    • Password reset and authentication services now follow updated event dispatcher configuration.
    • Added configurable email verification expiry and authentication timebox settings.
  • Bug Fixes

    • Improved user-cache invalidation and remember-token timestamp restoration.
    • Sensitive credentials and token keys receive stronger protection.
  • Documentation

    • Documented the default 60-minute email verification link expiry and configuration option.

Record the approved Auth work unit before its implementation changes. The plan defines the validated TokenGuard, Gate, password-broker, Eloquent cache, configuration, metadata, and sensitive-parameter boundaries together with their focused regression coverage.

It also carries the audit anti-overengineering rules, Laravel API compatibility requirements, coroutine ownership model, performance constraints, rejected alternatives, verification gates, and final audit-record routing so the implementation can be reviewed against one authoritative design.
Read query, request-body, bearer, and basic-password token sources in their documented order while accepting only non-empty strings and preserving the valid string zero. Invalid values now fall through to later sources instead of shadowing them or leaking through a mixed boundary.

Make explicit credential validation honor the configured input key, storage key, and hashing mode. Add focused regressions for ordered lazy access, malformed values, zero tokens, custom keys, hashed storage, and sensitive credential metadata.
Normalize callable reflection through Closure::fromCallable so invokable objects and callable strings receive the same guest-access analysis as closures and array callables. Cache object-callable results by weak identity and restore the nullable lazy-cache sentinel during framework-state cleanup.

Avoid constructing and dispatching GateEvaluated when the active dispatcher has no listener, while preserving Event fakes through the repository hasListeners convention. Add regressions for every callable family, before and after callbacks, listener and fake paths, weak-cache release, and flushState cleanup.
Restore a user model timestamp setting in a finally block around remember-token writes so successful and exceptional saves cannot leak temporary state. Keep the original database failure unchanged and preserve models that began with timestamps disabled.

Use the configured model as the single cache-key authority, register each active model keyspace when setModel changes it, retain only the store and prefix needed by invalidation descriptors, and keep old keyspaces invalidatable until expiry. Add unit and real-cache regressions for timestamp restoration, model switching, descriptor deduplication, and both old and new keyspaces.
Give verification expiry, password confirmation timeout, authentication timebox duration, and password rehashing one shipped configuration owner. Remove redundant consumer defaults where the setting is required while retaining the intentional nested verification fallback for replaced application configuration.

Use typed configuration reads at each boundary, update the public verification guide, and add regressions for environment coercion, signed-link expiry, nested replacement behavior, missing canonical settings, and middleware construction from the shipped values.
Construct and dispatch PasswordResetLinkSent only when the active dispatcher observes that event, preserving Event fakes while avoiding unused observational work. Add a narrow dispatcher replacement method for the worker-lifetime broker so container event rebinding can update an already-resolved instance.

Cover no-listener, real-listener, and replacement behavior directly while leaving reset-link callback ordering and the public password-broker contract unchanged.
Refresh already-resolved concrete password brokers when the event dispatcher binding changes without resolving an unused manager or replacing custom broker contracts. This keeps worker-lifetime brokers aligned with Event::fake, fakeFor restoration, and ordinary container rebinding while preserving the protected custom resolution extension point.

Accept unit and backed enums across broker names, guard-to-broker lookup, default broker selection, and guard-owned cache clearing, including integer-backed zero without falsey fallback. Update contracts and generated facade metadata, consume canonical timebox settings, and cover broker cache identity, dispatcher restoration, unused-manager behavior, custom brokers, session guards, and real forgot-password wiring.
Mark SessionGuard credential arrays and hash keys as sensitive at every public and internal propagation boundary, and protect password-reset repository hash keys the same way. TokenGuard validation carries the corresponding attribute from its earlier correctness change.

Add reflection-based coverage for the complete eleven-parameter surface so future signature edits cannot silently expose credentials or application key material in stack traces.
Exercise static and invokable custom guard creators through AuthManager using Hypervel contracts and return types. These focused parity cases protect the existing Laravel-style extension API without changing production behavior or introducing additional runtime machinery.
Add an end-to-end Auth integration regression proving logoutOtherDevices rehashes the persisted password through the configured user provider and hashing service. The test exercises real request, session, guard, database, and hash wiring rather than replacing the behavior with mocks.
Declare the split Auth package direct runtime dependencies and both discoverable providers instead of relying on the monorepo root to mask missing package edges. Keep constraints aligned with the root replacement and dependency policy.

Add executable metadata coverage for dependencies, provider discovery, and the generated enum-aware Auth and Password facade signatures so package installs, IDE metadata, and static-analysis surfaces cannot drift independently of the concrete APIs.
Mark Auth complete in the core package checklist and route every carried or cross-package dependency through the audit index, including the Fortify consumer revalidated by canonical Auth configuration.

Record final findings, ownership, rejected concerns, coroutine and worker-lifecycle boundaries, Laravel-facing compatibility, performance characteristics, regression coverage, authoritative validation, independent review, and the absence of deferred Auth work or TODOs.
# Conflicts:
#	docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md
#	docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@binaryfire, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 00b25f9f-7a1b-4aa3-9b7a-ce01d8ebfb28

📥 Commits

Reviewing files that changed from the base of the PR and between 3e385a5 and c9665dd.

📒 Files selected for processing (2)
  • docs/plans/2026-08-05-1615-auth-correctness-lifecycle-and-current-parity.md
  • src/auth/src/Passwords/PasswordBrokerManager.php
📝 Walkthrough

Walkthrough

The Auth package now covers stricter token validation, generalized Gate callbacks, dispatcher rebinding, enum identifiers, model-cache consistency, configuration ownership, sensitive parameters, package dependencies, and expanded unit and integration tests.

Changes

Auth correctness and lifecycle

Layer / File(s) Summary
Contracts, configuration, and package wiring
src/auth/composer.json, src/contracts/..., src/foundation/config/auth.php, src/support/src/Facades/*, src/auth/src/AuthManager.php, src/auth/src/PasswordConfirmation.php, src/auth/src/Notifications/VerifyEmail.php, tests/Auth/*Config*, tests/Auth/PackageMetadataTest.php
Auth dependencies and owned configuration were added. Broker, guard, facade, and cache APIs now support enum identifiers where specified.
Guard validation and sensitive data handling
src/auth/src/Access/Gate.php, src/auth/src/TokenGuard.php, src/auth/src/SessionGuard.php, src/auth/src/Passwords/*TokenRepository.php, tests/Auth/AuthAccessGateTest.php, tests/Auth/AuthTokenGuardTest.php, tests/Auth/SensitiveParameterTest.php
Gate supports object and static guest callbacks with weak caching. Token lookup and hashing validation reject invalid values. Credential and hash-key parameters carry sensitive-parameter metadata.
Password broker lifecycle and event rebinding
src/auth/src/Passwords/PasswordBroker*.php, src/auth/src/Passwords/PasswordResetServiceProvider.php, tests/Auth/AuthPasswordBroker*Test.php, tests/Auth/AuthPasswordResetServiceProviderTest.php, tests/Integration/Auth/AuthenticationTest.php, tests/Integration/Auth/ForgotPasswordTest.php
Password brokers normalize enum names, suppress event dispatch without listeners, accept dispatcher replacement, and refresh resolved concrete brokers when the event binding changes.
Remember-token persistence and model cache invalidation
src/auth/src/EloquentUserProvider.php, tests/Auth/AuthEloquentUserProvider*.php, tests/Integration/Auth/EloquentUserProviderCacheTest.php
Remember-token updates restore timestamp state after success or failure. Cache descriptors and invalidation keys use the active model class, including after model changes.
Audit records and verification coverage
docs/plans/*auth*, docs/plans/*lifecycle-audit*, src/boost/docs/verification.md, tests/Integration/Auth/RehashOnLogoutOtherDevicesTest.php
The Auth audit records and implementation plan were added or completed. Verification-link expiration and password rehash behavior have documentation and regression coverage.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Application
  participant PasswordResetServiceProvider
  participant PasswordBrokerManager
  participant PasswordBroker
  participant EventDispatcher
  Application->>PasswordResetServiceProvider: Rebind events
  PasswordResetServiceProvider->>PasswordBrokerManager: Refresh resolved brokers
  PasswordBrokerManager->>PasswordBroker: Replace dispatcher
  PasswordBroker->>EventDispatcher: Check listeners before reset-link event
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the PR's primary Auth lifecycle, token validation, and cache behavior changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch audit/auth-correctness-lifecycle-parity

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR corrects authentication token handling, authorization callable reflection, password-broker event lifecycle, and Eloquent user-cache ownership while expanding Laravel-compatible enum and configuration support.

  • Validates TokenGuard inputs in source order and applies configured storage keys and hashing.
  • Refreshes resolved password brokers when the event dispatcher changes and avoids constructing unobserved Auth events.
  • Restores Eloquent timestamp state and keeps cache keys and invalidation descriptors aligned with the configured model.
  • Adds enum-aware Auth APIs, canonical configuration defaults, sensitive-parameter annotations, package metadata, documentation, and regression coverage.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/auth/src/TokenGuard.php Token extraction now accepts only non-empty strings in documented precedence order, while explicit validation honors configured keys and hashing.
src/auth/src/Access/Gate.php Gate normalizes callable reflection, weakly caches object-callable metadata, resets static state, and avoids unobserved evaluation events.
src/auth/src/EloquentUserProvider.php Remember-token writes restore timestamp settings and model-specific cache descriptors preserve coherent lookup and invalidation keyspaces.
src/auth/src/Passwords/PasswordBroker.php Reset-link events are constructed only when observed, and resolved brokers can receive dispatcher replacements.
src/auth/src/Passwords/PasswordBrokerManager.php Broker identifiers now support enums and resolved concrete brokers follow dispatcher rebinding.
src/auth/src/Passwords/PasswordResetServiceProvider.php Event rebinding refreshes already-resolved password managers without resolving otherwise-unused services.
src/auth/src/AuthManager.php Guard cache clearing accepts enum identifiers while preserving coroutine-local guard selection.
src/foundation/config/auth.php Foundation now owns canonical verification-expiry and authentication-timebox defaults.
src/contracts/src/Auth/PasswordBrokerFactory.php The password-broker contract exposes additive enum-aware identifier signatures.
src/auth/composer.json The split Auth package declares its direct runtime dependencies and provider discovery metadata.

Reviews (2): Last reviewed commit: "Clarify Auth validation and dispatcher l..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/plans/2026-08-05-1615-auth-correctness-lifecycle-and-current-parity.md`:
- Line 198: Update the hashing-cost statement in section 8 to acknowledge that
TokenGuard::user() also hashes request tokens when configured with $hash = true,
and state that explicit validate() uses the same configured hashing path as
normal request authentication.
- Around line 576-577: Update the final validation steps in the plan to use only
`composer fix` from the worktree root as the authoritative aggregate command.
Remove the separate PHPStan and PHP-CS-Fixer commands while preserving the
instruction not to weaken, skip, or rewrite tests.

In `@src/auth/src/Passwords/PasswordBroker.php`:
- Around line 200-209: Update the PHPDoc for PasswordBroker::setDispatcher() and
PasswordBrokerManager::refreshEventDispatcher() to state that request-time
mutation can replace the dispatcher seen by concurrent requests, causing events
to use an incorrect or fake dispatcher. Preserve the existing boot/tests-only
lifecycle guidance in both methods.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e493ac7e-78e4-4b19-87ac-77e3a34e2962

📥 Commits

Reviewing files that changed from the base of the PR and between ca4cffe and 3e385a5.

📒 Files selected for processing (42)
  • docs/plans/2026-07-12-0900-framework-coroutine-state-lifecycle-audit.md
  • docs/plans/2026-07-12-0915-framework-coroutine-state-lifecycle-audit-ledger.md
  • docs/plans/2026-08-05-1615-auth-correctness-lifecycle-and-current-parity.md
  • src/auth/composer.json
  • src/auth/src/Access/Gate.php
  • src/auth/src/AuthManager.php
  • src/auth/src/EloquentUserProvider.php
  • src/auth/src/Notifications/VerifyEmail.php
  • src/auth/src/PasswordConfirmation.php
  • src/auth/src/Passwords/CacheTokenRepository.php
  • src/auth/src/Passwords/DatabaseTokenRepository.php
  • src/auth/src/Passwords/PasswordBroker.php
  • src/auth/src/Passwords/PasswordBrokerManager.php
  • src/auth/src/Passwords/PasswordResetServiceProvider.php
  • src/auth/src/SessionGuard.php
  • src/auth/src/TokenGuard.php
  • src/boost/docs/verification.md
  • src/contracts/src/Auth/PasswordBrokerFactory.php
  • src/fortify/src/Actions/RedirectIfTwoFactorAuthenticatable.php
  • src/foundation/config/auth.php
  • src/support/src/Facades/Auth.php
  • src/support/src/Facades/Password.php
  • tests/Auth/AuthAccessGateTest.php
  • tests/Auth/AuthConfigTest.php
  • tests/Auth/AuthEloquentUserProviderCacheTest.php
  • tests/Auth/AuthEloquentUserProviderTest.php
  • tests/Auth/AuthManagerTest.php
  • tests/Auth/AuthPasswordBrokerManagerTest.php
  • tests/Auth/AuthPasswordBrokerTest.php
  • tests/Auth/AuthPasswordResetServiceProviderTest.php
  • tests/Auth/AuthTokenGuardTest.php
  • tests/Auth/AuthenticateMiddlewareTest.php
  • tests/Auth/PackageMetadataTest.php
  • tests/Auth/PasswordConfirmationTest.php
  • tests/Auth/RequirePasswordMiddlewareTest.php
  • tests/Auth/SensitiveParameterTest.php
  • tests/Auth/VerifyEmailNotificationTest.php
  • tests/Integration/Auth/AuthenticationTest.php
  • tests/Integration/Auth/EloquentUserProviderCacheTest.php
  • tests/Integration/Auth/Fixtures/AuthTestUser.php
  • tests/Integration/Auth/ForgotPasswordTest.php
  • tests/Integration/Auth/RehashOnLogoutOtherDevicesTest.php

Comment thread docs/plans/2026-08-05-1615-auth-correctness-lifecycle-and-current-parity.md Outdated
Comment thread docs/plans/2026-08-05-1615-auth-correctness-lifecycle-and-current-parity.md Outdated
Comment thread src/auth/src/Passwords/PasswordBroker.php
Correct the implementation plan to distinguish TokenGuard hashing already performed by normal request authentication from the hashing newly applied by explicit validation. Replace duplicated partial tool commands with composer fix as the single authoritative aggregate gate.

Document that refreshing every resolved password broker mutates worker-lifetime dispatcher state and races across coroutines when used per request. Keep the single-broker setter wording unchanged because it already states its worker-wide effect and matches established Auth mutators.
@binaryfire
binaryfire merged commit 126c0d8 into 0.4 Aug 5, 2026
37 of 38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant