Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
Agents
packstub/account-switcher
claude-code
cursor
impersonation
auth
audit-log
filament
linked-accounts
session-guard

Account Switcher for Laravel: user impersonation, linked sub-accounts (password-confirmed escalation), developer logins and an audit log of every switch, for any Laravel app with a session guard. Free, MIT. packstub/filament-account-switcher (the sibling repo, plugins/filament-account-switcher)...

Install
php artisan boost:add-skill packstub/account-switcher

Save this content to: AGENTS.md

# packstub/account-switcher

**Account Switcher for Laravel**: user impersonation, linked sub-accounts (password-confirmed escalation), developer logins and an audit log of every switch, for any Laravel app with a session guard. Free, MIT. `packstub/filament-account-switcher` (the sibling repo, `plugins/filament-account-switcher`) puts the same features into a Filament panel and requires this package; the two share the `Packstub\AccountSwitcher\` namespace (Composer merges the PSR-4 directories), so class names must not collide across them.

## Commands

```bash
composer test               # Pest suite (Testbench, in-memory SQLite, no Filament, no Livewire)
composer test:filter <name>
composer lint               # Pint
```

## Layout

- `src/AccountSwitcher.php` + `Facades\AccountSwitcher`: the session core. Every switch goes through `authenticateAs()` (re-login on the context's guard, session regeneration, the per-guard `password_hash_*` keys cleared). `routes()` registers the four routes. `resolveUsers()` turns a closure, an e-mail list or null into users. Macroable, so the Filament package can add `plugin()` and `accessiblePanel()`.
- `src/Contracts/SwitchContext.php`: what differs between a plain app and a panel (guard, scope stored in the log's `panel` column, user labels, `canAccess`, redirects and the landing-page fallback URL, feature toggles, extra rules, the developer login list with its runtime gate, labels, tags, search and own redirect, the switch-log context, the two form URLs). A method added to the contract in a minor gets a default in `AppContext`, which a custom context should extend. `src/AppContext.php` is the plain-Laravel implementation: config keys plus fluent closures. The provider binds it only when nothing else is bound, so the Filament package's `PanelContext` wins whatever the provider order.
- `src/Http/Controllers`: `ImpersonateController` (403 via `AccountSwitchDenied`, 404 for an unknown user), `SwitchBackController`, `SwitchAccountController` (a wrong password is a validation error on `password`, not a 403), `DeveloperLoginController` (404 outside the environments or the list).
- `src/Models`: `LinkedAccount` (pivot, both directions as two rows), `AccountSwitch` (the log); both on `AccountSwitcher::connectionName()`. `src/Concerns/HasLinkedAccounts`, `src/Events`, `src/Enums/SwitchReason`, `src/Exceptions/AccountSwitchDenied` (an `AuthorizationException`).
- `resources/views/components`: `banner` and `developer-logins`, anonymous Blade components (`<x-account-switcher::banner />`), inline styles only. `resources/lang/en/messages.php`: `account-switcher::messages.*` (banner, developer logins heading, reasons, errors).
- `config/packstub-account-switcher.php`: the key is shared with the Filament package (its users published it under that name before the split); `database/migrations/*.stub`.
- `docs/`: customer docs, synced into the store under `account-switcher/1.x` by `docs-sync.yml`.

## Conventions

- PHP 8.2+, Laravel 12 and 13. Every change needs a Pest test and a `CHANGELOG.md` line; headings are `## <version> — <date>`, the tag is `v<version>` on `main`. The section becomes the GitHub release and `github-release.yml` appends GitHub's list of merged pull requests under it, so keep it short and human: an optional lead sentence, then at most about six one-line bullets saying what a user gets, in plain words (class or method names only when a user needs the name, never lists of them). Always keep breaking changes with an `**Upgrading:**` line, security or privacy fixes, new minimum PHP/Laravel versions and migrations to run; leave out CI, tests and refactors.
- Nothing here may import from `Filament\` or `Livewire\`; what needs a panel belongs in `packstub/filament-account-switcher`.
- Config keys, migration file names, the `packstub_account_switcher` session key, route names, the `SwitchContext` methods and the translation keys are shared with the Filament package; they must not change inside a major. Schema changes follow the workspace rule (final shape in `create_*`, guarded `add_*`).
- Authorization stays in the service, never only in a controller or a view: `canImpersonate()` and `canSwitchToLinkedAccount()` are the single source, the routes call the same methods.
- After a change here run the Filament package's suite too (`plugins/filament-account-switcher`, `composer test`).

packstub/account-switcher

Account Switcher for Laravel: user impersonation, linked sub-accounts (password-confirmed escalation), developer logins and an audit log of every switch, for any Laravel app with a session guard. Free, MIT. packstub/filament-account-switcher (the sibling repo, plugins/filament-account-switcher) puts the same features into a Filament panel and requires this package; the two share the Packstub\AccountSwitcher\ namespace (Composer merges the PSR-4 directories), so class names must not collide across them.

Commands

composer test               # Pest suite (Testbench, in-memory SQLite, no Filament, no Livewire)
composer test:filter <name>
composer lint               # Pint

Layout

  • src/AccountSwitcher.php + Facades\AccountSwitcher: the session core. Every switch goes through authenticateAs() (re-login on the context's guard, session regeneration, the per-guard password_hash_* keys cleared). routes() registers the four routes. resolveUsers() turns a closure, an e-mail list or null into users. Macroable, so the Filament package can add plugin() and accessiblePanel().
  • src/Contracts/SwitchContext.php: what differs between a plain app and a panel (guard, scope stored in the log's panel column, user labels, canAccess, redirects and the landing-page fallback URL, feature toggles, extra rules, the developer login list with its runtime gate, labels, tags, search and own redirect, the switch-log context, the two form URLs). A method added to the contract in a minor gets a default in AppContext, which a custom context should extend. src/AppContext.php is the plain-Laravel implementation: config keys plus fluent closures. The provider binds it only when nothing else is bound, so the Filament package's PanelContext wins whatever the provider order.
  • src/Http/Controllers: ImpersonateController (403 via AccountSwitchDenied, 404 for an unknown user), SwitchBackController, SwitchAccountController (a wrong password is a validation error on password, not a 403), DeveloperLoginController (404 outside the environments or the list).
  • src/Models: LinkedAccount (pivot, both directions as two rows), AccountSwitch (the log); both on AccountSwitcher::connectionName(). src/Concerns/HasLinkedAccounts, src/Events, src/Enums/SwitchReason, src/Exceptions/AccountSwitchDenied (an AuthorizationException).
  • resources/views/components: banner and developer-logins, anonymous Blade components (<x-account-switcher::banner />), inline styles only. resources/lang/en/messages.php: account-switcher::messages.* (banner, developer logins heading, reasons, errors).
  • config/packstub-account-switcher.php: the key is shared with the Filament package (its users published it under that name before the split); database/migrations/*.stub.
  • docs/: customer docs, synced into the store under account-switcher/1.x by docs-sync.yml.

Conventions

  • PHP 8.2+, Laravel 12 and 13. Every change needs a Pest test and a CHANGELOG.md line; headings are ## <version> — <date>, the tag is v<version> on main. The section becomes the GitHub release and github-release.yml appends GitHub's list of merged pull requests under it, so keep it short and human: an optional lead sentence, then at most about six one-line bullets saying what a user gets, in plain words (class or method names only when a user needs the name, never lists of them). Always keep breaking changes with an **Upgrading:** line, security or privacy fixes, new minimum PHP/Laravel versions and migrations to run; leave out CI, tests and refactors.
  • Nothing here may import from Filament\ or Livewire\; what needs a panel belongs in packstub/filament-account-switcher.
  • Config keys, migration file names, the packstub_account_switcher session key, route names, the SwitchContext methods and the translation keys are shared with the Filament package; they must not change inside a major. Schema changes follow the workspace rule (final shape in create_*, guarded add_*).
  • Authorization stays in the service, never only in a controller or a view: canImpersonate() and canSwitchToLinkedAccount() are the single source, the routes call the same methods.
  • After a change here run the Filament package's suite too (plugins/filament-account-switcher, composer test).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core