3
0
mirror of https://github.com/snipe/snipe-it.git synced 2026-08-18 03:06:23 +00:00

Merge pull request #19431 from marcusmoore/boost

Installed Laravel Boost
This commit is contained in:
snipe
2026-08-07 17:10:52 +01:00
committed by GitHub
20 changed files with 591 additions and 135 deletions

View File

@ -0,0 +1,71 @@
# Snipe-IT Architecture
## Controllers
Two parallel controller trees:
- `app/Http/Controllers/` — web/UI controllers returning Blade views.
- `app/Http/Controllers/Api/` — REST API controllers returning JSON, consumed by datatables and select2.
Both trees use the same subdirectory groupings: `Assets/`, `Licenses/`, `Users/`, `Accessories/`, `Consumables/`, `Components/`, `Kits/`, `Account/`, `Auth/`.
## API Transformers
Every API controller returns data through a **Transformer** in `app/Http/Transformers/`. Never return raw model attributes from an API controller. `DatatablesTransformer` wraps paginated results.
```php
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
```
This supersedes the generic advice to reach for Eloquent API Resources — follow the existing transformer convention.
## Authorization
- All authorization goes through **Policies** in `app/Policies/`.
- `CheckoutablePermissionsPolicy` is the base for assets, licenses, accessories, and consumables.
- Its `checkout()` / `checkin()` methods accept `$item = null`, so `@can('checkout', \App\Models\Asset::class)` works without an instance.
## Routes
- UI routes live in `routes/web.php` **and** in the per-entity files under `routes/web/` (`hardware.php`, `users.php`, `licenses.php`, `accessories.php`, `components.php`, `consumables.php`, `kits.php`, `models.php`, `fields.php`, `locations.php`). Check both when adding or locating a UI route.
- API routes are in `routes/api.php`.
- Breadcrumbs are defined inline with `->breadcrumbs(fn (Trail $trail) => ...)` from `tabuna/breadcrumbs`. **Every UI route should have a breadcrumb.**
- Some route names contain slashes rather than dots. For example, use `route('reports/unaccepted_assets')`.
## Full Multiple Company Support (FMCS)
`Setting::getSettings()->full_multiple_companies_support == '1'` gates company-scoped filtering. The select2 endpoints (`selectlist()` methods) accept a `companyId` query param:
```php
if ((Setting::getSettings()->full_multiple_companies_support == '1') && ($request->filled('companyId'))) {
$query->where('table.company_id', $request->input('companyId'));
}
```
Wire it up from Blade with `data-company-id="{{ $user->company_id }}"`.
## Select2 AJAX Dropdowns
Use `class="js-data-ajax"` with `data-endpoint="hardware|licenses|consumables|..."`. `snipeit.js` auto-initializes these, forwarding `data-company-id` as `companyId` and `data-asset-status-type` as `statusType` to the API.
## Checkout Redirect Flow
After checkout, `Helper::getRedirectOption()` reads `$request->redirect_option`. To redirect back to the assigned user, the form must set:
- `redirect_option=target`
- `checkout_to_type=user`
- `assigned_user={{ $user->id }}`
## Translations
UI strings are translation keys in `resources/lang/en-US/general.php` and its sibling files. Always add a new key rather than hard-coding English in a view.
## Global View Variables
`$snipeSettings` is shared with every view by `SettingsServiceProvider`. Use it directly in Blade — do not pass `Setting::getSettings()` from the controller.
## Key Helper Methods (`app/Helpers/Helper.php`)
- `Helper::deployableStatusLabelList()` — status labels for checkout forms.
- `Helper::defaultChartColors(int $index = 0)` — 10-color chart palette.
- `Helper::getRedirectOption($request, $id, $table, $item_id = null)` — post-checkout redirect logic.

View File

@ -0,0 +1,32 @@
# Snipe-IT Stack & Tooling
## Frontend Is Laravel Mix, Not Vite
- Assets are built with **Laravel Mix (webpack)** via `webpack.mix.js`. This project has no `vite.config.js` and no Vite manifest.
- There is **no `npm run build` script**. Ignore any generic guidance that tells you to run it. Use:
- `npm run dev` — development build
- `npm run watch` — rebuild on change
- `npm run prod` — production build
- If the user doesn't see a frontend change, ask them to run `npm run dev` or `npm run watch`.
## UI Layer
- **AdminLTE 2 / Bootstrap 3** Blade views. There is no Inertia.
- **Livewire v4 is installed** and used for discrete widgets in `app/Livewire` (e.g. `Importer`, `CustomFieldEditor`, `LdapSettings`). It is not the primary UI layer.
- Default to a Blade view plus a standard controller. Only reach for Livewire when extending an existing Livewire component or when the user asks for it.
## Charts
- **Chart.js v2.9.4**, bundled at `public/js/dist/Chart.min.js`.
- Use the **v2 API**, not v3. For example, the chart type is `horizontalBar` (v3 removed it in favor of `indexAxis`).
- Use `Helper::defaultChartColors()` for the 10-color palette.
## Commands
```bash
# Clear caches after config/route changes
php artisan optimize:clear
# Coverage reports (served by Laravel Herd)
herd coverage
```

View File

@ -0,0 +1,12 @@
# Snipe-IT Testing
- Feature tests live in `tests/Feature/`, organized by entity (e.g. `tests/Feature/Assets/AssetsTest.php`). Unit tests live in `tests/Unit/`.
- Feature tests hit the database. The test environment uses `array` drivers for cache, session, and mail.
- Always build test data with model factories. Check for an existing custom state before setting attributes by hand.
- Test methods are named in snake_case: `test_page_renders()`, `test_requires_permission()`. Never camelCase.
- UI GET routes should have both a `test_page_renders` test and a `test_requires_permission` test.
```bash
php artisan test tests/Feature/Assets/AssetsTest.php # single file
php artisan test --filter test_some_method # single method
```

11
.ai/rules/actions.md Normal file
View File

@ -0,0 +1,11 @@
---
paths:
- 'app/Actions/**'
---
# Actions
## Actions expose a single static run() method
An Action is a class in `app/Actions/<Entity>/` named `<Verb><Entity>Action`, with one `public static function run(...)` and no constructor. Call it statically: `DestroySupplierAction::run(supplier: $supplier)`.
Do not use `handle()`, `execute()`, `__invoke()`, or instantiate the class.

18
.ai/rules/api.md Normal file
View File

@ -0,0 +1,18 @@
---
paths:
- 'app/Http/Controllers/Api/**'
---
# Api
## Wrap API responses in the standard envelope
Every API response goes through the shared envelope:
`return response()->json(Helper::formatStandardApiResponse('success', $payload, trans('...')));`
Use `'error'` with a `null` payload for failures, and a translation key for the message. There are no Eloquent API Resources in this project.
## Page API lists with offset and limit
API list endpoints page with `offset`/`limit` request params, resolved through the container as `app('api_offset_value')` and `app('api_limit_value')`, then applied with `->skip($offset)->take($limit)->get()`.
Do not use `paginate()`, `simplePaginate()`, or `cursorPaginate()` on API endpoints.

9
.ai/rules/app.md Normal file
View File

@ -0,0 +1,9 @@
---
paths:
- 'app/**'
---
# App
## Use trans(), never __()
Translate with `trans('admin/hardware/message.some_key')` using short dotted keys from `resources/lang/<locale>/`. Never use `__()` — it appears nowhere in this codebase. Add a new key rather than hard-coding English.

9
.ai/rules/controllers.md Normal file
View File

@ -0,0 +1,9 @@
---
paths:
- 'app/Http/Controllers/**'
---
# Controllers
## No DTOs or repository layer
Controllers build Eloquent queries inline and pass models, collections, and arrays around. There are no DTO or repository classes — do not introduce them. Extract to an Action or a Presenter when a controller method gets heavy.

18
.ai/rules/index.md Normal file
View File

@ -0,0 +1,18 @@
# Project Rules Index
Before planning or editing, find the row whose globs match the file's path and read that rule file.
| Applies to | Rule file |
| --- | --- |
| app/Actions/** | .ai/rules/actions.md |
| app/Http/Controllers/Api/** | .ai/rules/api.md |
| app/** | .ai/rules/app.md |
| app/Http/Controllers/** | .ai/rules/controllers.md |
| app/Livewire/** | .ai/rules/livewire.md |
| database/migrations/** | .ai/rules/migrations.md |
| app/Models/** | .ai/rules/models.md |
| app/Presenters/** | .ai/rules/presenters.md |
| app/Providers/** | .ai/rules/providers.md |
| app/Http/Requests/** | .ai/rules/requests.md |
| tests/** | .ai/rules/tests.md |
| resources/views/** | .ai/rules/views.md |

9
.ai/rules/livewire.md Normal file
View File

@ -0,0 +1,9 @@
---
paths:
- 'app/Livewire/**'
---
# Livewire
## Livewire components are class-based with a separate view
A Livewire component is a class in `app/Livewire` plus a kebab-case Blade view in `resources/views/livewire`. Livewire 4 is installed, but this project uses none of its single-file, multi-file, or Volt formats — match the class-plus-view shape.

9
.ai/rules/migrations.md Normal file
View File

@ -0,0 +1,9 @@
---
paths:
- 'database/migrations/**'
---
# Migrations
## No foreign-key constraints
Relationship columns are plain `integer('other_id')` columns (nullable and indexed as needed). Do not add `foreignId()`, `foreignIdFor()`, `constrained()`, or `->foreign()->references()` — this schema has no FK constraints and referential integrity is enforced in application code.

22
.ai/rules/models.md Normal file
View File

@ -0,0 +1,22 @@
---
paths:
- 'app/Models/**'
---
# Models
## Models validate themselves with watson/validating
Models carry their own validation: `use Watson\Validating\ValidatingTrait` plus a `protected $rules` array. `$model->save()` returns false when validation fails and `$model->getErrors()` holds the messages.
This is a second layer on top of the Form Request, not a replacement for it.
## Declare a presenter on the model
A model that renders in the UI sets `protected $presenter = \App\Presenters\<Entity>Presenter::class` and `use App\Presenters\Presentable`, exposing `$model->present()`.
## Share model behavior through opt-in traits
Cross-cutting model behavior comes from traits in `app/Models/Traits`, opted into per model: `CompanyableTrait` (FMCS scoping), `Loggable` (action log), `Searchable` (API/datatable search), `Requestable`, `Acceptable`, `HasUploads`.
Add behavior as a trait rather than pushing it into a base class.
## Casts go in the $casts property
Declare casts with `protected $casts = [...]`, not a `casts()` method, even though Laravel 12 supports the method form.

11
.ai/rules/presenters.md Normal file
View File

@ -0,0 +1,11 @@
---
paths:
- 'app/Presenters/**'
---
# Presenters
## Presenters own display and datatable config
Display formatting and Bootstrap-table column config belong in `app/Presenters/<Entity>Presenter.php`, reached from the model via `$model->present()`.
Keep this logic out of controllers, transformers, and Blade.

14
.ai/rules/providers.md Normal file
View File

@ -0,0 +1,14 @@
---
paths:
- 'app/Providers/**'
---
# Providers
## Named validation rules live in ValidationServiceProvider
Add a new named validation rule as a `Validator::extend()` (or `extendImplicit()`) closure in `app/Providers/ValidationServiceProvider.php`, then reference it by its string name in `$rules`.
`app/Rules` is reserved for the encrypted-custom-field rule objects — do not add general-purpose rules there.
## Register observers in AppServiceProvider
Wire an observer with `Model::observe(ModelObserver::class)` in `AppServiceProvider::boot()`. Do not use the `#[ObservedBy]` attribute on the model.

16
.ai/rules/requests.md Normal file
View File

@ -0,0 +1,16 @@
---
paths:
- 'app/Http/Requests/**'
---
# Requests
## Form Requests are the validation entry point
Validate HTTP input with a Form Request class, not inline `$request->validate()` or `Validator::make()`.
Extend `App\Http\Requests\Request` and declare rules in the `protected $rules` property — the base class returns it from `rules()`. When the request handles file uploads, extend `ImageUploadRequest` instead and call `$request->handleImages($model)` in the controller.
## Always call parent::prepareForValidation()
`ImageUploadRequest` inherits `prepareForValidation()` from the `ConvertsBase64ToFiles` trait, which turns base64 payloads into `UploadedFile` instances before rules run.
If a child request overrides `prepareForValidation()`, it MUST call `parent::prepareForValidation()` — usually first. Forgetting it silently breaks base64 image uploads with no validation error to point at. This has bitten us before.

15
.ai/rules/tests.md Normal file
View File

@ -0,0 +1,15 @@
---
paths:
- 'tests/**'
---
# Tests
## Database refresh comes from the base TestCase
`Tests\TestCase` already applies `LazilyRefreshDatabase` and seeds settings via `InitializesSettings`. Do not add `RefreshDatabase`, `DatabaseTransactions`, or `DatabaseMigrations` to an individual test.
## Test methods are snake_case
Name test methods in snake_case: `test_page_renders()`, `test_requires_permission()`. Never camelCase.
## Authenticate API tests with actingAsForApi()
Use `$this->actingAsForApi($user)` in API tests and `$this->actingAs($user)` in UI tests.

14
.ai/rules/views.md Normal file
View File

@ -0,0 +1,14 @@
---
paths:
- 'resources/views/**'
---
# Views
## Use trans(), never __()
Translate with `trans('general.some_key')` using short dotted keys from `resources/lang/<locale>/`. Never use `__()` — it appears nowhere in this codebase. Add a new key rather than hard-coding English.
## Blade composition: layouts plus anonymous components
Pages `@extends` a layout. Reusable markup is an anonymous Blade component: a file in `resources/views/components/` declaring `@props([...])`, used as `<x-name />`.
Do not create class-based components — there is no `app/View/Components` directory.

19
.gitignore vendored
View File

@ -76,4 +76,21 @@ storage/ldap_client_tls.key
/storage/framework/testing
/.phpunit.cache
/.claude/
/.mcp.json
/.agents
/.amp
/.claude
/.codex
/.cursor
/.factory
/.github/skills
/.grok
/.junie
/.kiro
/.pi
/.zed
AGENTS.md
boost.json
CLAUDE.md
opencode.json

133
CLAUDE.md
View File

@ -1,133 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Stack
- **PHP 8.2+** / **Laravel 12** (framework), **Laravel Mix** (webpack) for frontend assets
- **AdminLTE 2** / **Bootstrap 3** UI — Blade views. Mostly server-rendered; a handful of newer admin-settings screens use **Livewire** components (`app/Livewire/`, e.g. `LdapSettings`, `CustomFieldEditor`, `Importer`) — no Inertia.
- **Chart.js v2.9.4** — bundled at `public/js/dist/Chart.min.js`; use `horizontalBar` type (v2 API, not v3)
- Snipe-IT is a FOSS IT asset management system (assets, licenses, accessories, consumables, components, kits) — see README.md for product context.
## Common Commands
```bash
# Run all tests
php artisan test
# or
vendor/bin/phpunit
# Run a single test file
php artisan test tests/Feature/Assets/AssetsTest.php
# Run a specific test method
php artisan test --filter testSomeMethod
# Run/exclude tests by group (e.g. LDAP tests, which need the LDAP extension)
php artisan test --group=ldap
php artisan test --exclude-group=ldap
# Lint / static analysis
vendor/bin/pint # code style (Laravel preset, see pint.json)
vendor/bin/phpstan analyse # static analysis via Larastan, level 4 (phpstan.neon.dist)
# Build frontend assets (dev)
npm run dev
# Build for production
npm run prod
# Laravel Mix watch
npm run watch
# Tinker / REPL
php artisan tinker
# Clear caches after config/route changes
php artisan optimize:clear
```
Dev server is served via **Laravel Herd** (`herd coverage vendor/bin/phpunit --coverage-html tests/coverage/html` for coverage reports — see `composer.json` scripts).
Before running tests locally, copy `.env.testing.example` to `.env.testing`. Default test config uses in-memory SQLite (`DB_CONNECTION=sqlite_testing`); MySQL is also supported by setting the `DB_*` vars. See TESTING.md for details.
## Architecture
### Controllers
Two parallel controller trees:
- `app/Http/Controllers/` — web/UI controllers (Blade views)
- `app/Http/Controllers/Api/` — REST API controllers (JSON, used by datatables + select2)
Subdirectory groupings: `Assets/`, `Licenses/`, `Users/`, `Accessories/`, `Consumables/`, `Components/`, `Kits/`, `Account/`, `Auth/`
### API Pattern
Every API controller returns data via a **Transformer** (`app/Http/Transformers/`). Never return raw model attributes from API controllers — always pass through the transformer. `DatatablesTransformer` wraps paginated results.
```php
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
```
### Authorization
All authorization goes through **Policies** (`app/Policies/`). `CheckoutablePermissionsPolicy` is the base for assets/licenses/accessories/consumables — its `checkout()` / `checkin()` methods accept `$item = null` so you can use `@can('checkout', \App\Models\Asset::class)` without an instance.
### FMCS (Full Multiple Company Support)
`Setting::getSettings()->full_multiple_companies_support == '1'` gates company-scoped filtering. The select2 API endpoints (`selectlist()` methods) accept a `companyId` query param — apply it like this:
```php
if ((Setting::getSettings()->full_multiple_companies_support == '1') && ($request->filled('companyId'))) {
$query->where('table.company_id', $request->input('companyId'));
}
```
Pass `data-company-id="{{ $user->company_id }}"` in Blade to wire it to select2.
### Select2 AJAX Dropdowns
Use `class="js-data-ajax"` with `data-endpoint="hardware|licenses|consumables|..."`. `snipeit.js` auto-initializes these, forwarding `data-company-id` as `companyId` and `data-asset-status-type` as `statusType` to the API.
### Routes
All routes are in `routes/web.php` (UI) and `routes/api.php` (API). Breadcrumbs are defined inline using `->breadcrumbs(fn (Trail $trail) => ...)` from `tabuna/breadcrumbs`. Every UI route should have a breadcrumb.
Note: the `reports/unaccepted_assets` route is named with slashes, not dots — use `route('reports/unaccepted_assets')`.
### Translations
String keys live in `resources/lang/en-US/general.php` (and other files in that directory). Always add new UI strings as translation keys rather than hard-coding English.
### Checkout Redirect Flow
After checkout, `Helper::getRedirectOption()` reads `$request->redirect_option`. For redirecting back to the assigned user after checkout:
- Set `redirect_option=target` in the form
- Set `checkout_to_type=user` in the form
- Set `assigned_user={{ $user->id }}` in the form
### Key Helper Methods (`app/Helpers/Helper.php`)
- `Helper::deployableStatusLabelList()` — status labels for checkout forms
- `Helper::defaultChartColors()` — 10-color palette used in charts
- `Helper::getRedirectOption($request, $id, $table)` — post-checkout redirect logic
### Global View Variables
`$snipeSettings` is injected into all views via a service provider — no need to pass `Setting::getSettings()` from every controller. Use it directly in Blade.
### CSV Importing
`app/Importer/` holds per-entity importers (`AssetImporter`, `LicenseImporter`, `AccessoryImporter`, `ComponentImporter`, `ConsumableImporter`, `AssetModelImporter`, `CategoryImporter`, `UserImporter`, etc.), all extending `Importer.php`. The `Importer` Livewire component (`app/Livewire/Importer.php`) drives the UI for CSV import.
### Presenters
`app/Presenters/` (e.g. `AssetPresenter`, `AssetModelPresenter`, `AccessoryPresenter`) define the column/field configuration consumed by the Bootstrap Table datatables on index views — check these when adding or changing a column shown in a listing.
## Testing
Tests live in `tests/Feature/` (organized by entity) and `tests/Unit/`. Feature tests hit the database; the test environment uses `array` cache/session/mail drivers. Tests use factories for data setup. Use PHPUnit `#[Group('name')]` attributes to tag tests that need optional extensions/services (e.g. `LdapTest` is tagged `ldap`) so they can be excluded via `--exclude-group`.
## Contribution Policy
Per README.md / the project's AI Contribution Policy: PRs and issues generated by fully-automated tools without human review are not accepted upstream. If producing a PR for the upstream project (not an internal fork), treat Claude's output as a draft for human review, not a submission-ready artifact.

View File

@ -80,6 +80,7 @@
"require-dev": {
"fruitcake/laravel-debugbar": "^4.0",
"larastan/larastan": "^3.0",
"laravel/boost": "^2.5",
"laravel/pint": "^1.29",
"laravel/telescope": "^5.11",
"mockery/mockery": "^1.4",
@ -122,6 +123,9 @@
"@php artisan package:discover --ansi",
"@php artisan vendor:publish --force --tag=livewire:assets --ansi"
],
"post-update-cmd": [
"@php artisan boost:update --ansi"
],
"post-create-project-cmd": [
"php artisan key:generate"
],

280
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3c0126d219147bf831e2c034cee67319",
"content-hash": "d3d61d9b70fb976c46bafc7120c9f8e6",
"packages": [
{
"name": "alek13/slack",
@ -13149,6 +13149,146 @@
],
"time": "2026-04-16T10:02:43+00:00"
},
{
"name": "laravel/boost",
"version": "v2.5.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/boost.git",
"reference": "ae6ae78ecd053000d14204cef3c5c37aae6c97ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/boost/zipball/ae6ae78ecd053000d14204cef3c5c37aae6c97ed",
"reference": "ae6ae78ecd053000d14204cef3c5c37aae6c97ed",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^7.9",
"illuminate/console": "^11.45.3|^12.41.1|^13.0",
"illuminate/contracts": "^11.45.3|^12.41.1|^13.0",
"illuminate/routing": "^11.45.3|^12.41.1|^13.0",
"illuminate/support": "^11.45.3|^12.41.1|^13.0",
"laravel/mcp": "^0.7.1|^0.8.0|^0.9.0",
"laravel/prompts": "^0.3.10",
"laravel/roster": "^1.0.0",
"php": "^8.2"
},
"require-dev": {
"laravel/pint": "^1.27.0",
"mockery/mockery": "^1.6.12",
"orchestra/testbench": "^9.15.0|^10.6|^11.0",
"pestphp/pest": "^2.36.0|^3.8.4|^4.1.5",
"phpstan/phpstan": "^2.1.27",
"rector/rector": "^2.1"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Boost\\BoostServiceProvider"
]
},
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Boost\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.",
"homepage": "https://github.com/laravel/boost",
"keywords": [
"ai",
"dev",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/boost/issues",
"source": "https://github.com/laravel/boost"
},
"time": "2026-08-05T17:03:29+00:00"
},
{
"name": "laravel/mcp",
"version": "v0.9.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/mcp.git",
"reference": "a08884d79a95c5143498507aec5badf751cdbec4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/mcp/zipball/a08884d79a95c5143498507aec5badf751cdbec4",
"reference": "a08884d79a95c5143498507aec5badf751cdbec4",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"illuminate/console": "^11.45.3|^12.41.1|^13.0",
"illuminate/container": "^11.45.3|^12.41.1|^13.0",
"illuminate/contracts": "^11.45.3|^12.41.1|^13.0",
"illuminate/http": "^11.45.3|^12.41.1|^13.0",
"illuminate/json-schema": "^12.41.1|^13.0",
"illuminate/routing": "^11.45.3|^12.41.1|^13.0",
"illuminate/support": "^11.45.3|^12.41.1|^13.0",
"illuminate/validation": "^11.45.3|^12.41.1|^13.0",
"php": "^8.2",
"symfony/process": "^7.4.5|^8.0.5"
},
"require-dev": {
"laravel/pint": "^1.20",
"orchestra/testbench": "^9.15|^10.8|^11.0",
"pestphp/pest": "^3.8.5|^4.3.2",
"phpstan/phpstan": "^2.1.27",
"rector/rector": "^2.2.4"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Mcp": "Laravel\\Mcp\\Facades\\Mcp"
},
"providers": [
"Laravel\\Mcp\\Server\\McpServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Mcp\\": "src/",
"Laravel\\Mcp\\Server\\": "src/Server/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Rapidly build MCP servers for your Laravel applications.",
"homepage": "https://github.com/laravel/mcp",
"keywords": [
"laravel",
"mcp"
],
"support": {
"issues": "https://github.com/laravel/mcp/issues",
"source": "https://github.com/laravel/mcp"
},
"time": "2026-07-21T13:23:52+00:00"
},
{
"name": "laravel/pint",
"version": "v1.29.1",
@ -13217,6 +13357,68 @@
},
"time": "2026-04-20T15:26:14+00:00"
},
{
"name": "laravel/roster",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/roster.git",
"reference": "89e518bd88ae98ff50f6082f6b517c8d8e8245fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/roster/zipball/89e518bd88ae98ff50f6082f6b517c8d8e8245fa",
"reference": "89e518bd88ae98ff50f6082f6b517c8d8e8245fa",
"shasum": ""
},
"require": {
"composer/semver": "^3.0",
"illuminate/console": "^11.0|^12.0|^13.0",
"illuminate/contracts": "^11.0|^12.0|^13.0",
"illuminate/support": "^11.0|^12.0|^13.0",
"php": "^8.2",
"symfony/yaml": "^7.2|^8.0"
},
"require-dev": {
"laravel/pint": "^1.29",
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.0|^10.0|^11.0",
"pestphp/pest": "^3.0|^4.1",
"phpstan/phpstan": "^2.0",
"rector/rector": "^2.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Roster\\RosterServiceProvider"
]
},
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Roster\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Detect packages & approaches in use within a Laravel project",
"homepage": "https://github.com/laravel/roster",
"keywords": [
"dev",
"laravel"
],
"support": {
"issues": "https://github.com/laravel/roster/issues",
"source": "https://github.com/laravel/roster"
},
"time": "2026-07-18T17:53:15+00:00"
},
{
"name": "laravel/sentinel",
"version": "v1.1.0",
@ -17084,6 +17286,82 @@
],
"time": "2026-04-18T13:18:21+00:00"
},
{
"name": "symfony/yaml",
"version": "v7.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "e101850ded5d2c0d44bf32abb8996404afec2dec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/e101850ded5d2c0d44bf32abb8996404afec2dec",
"reference": "e101850ded5d2c0d44bf32abb8996404afec2dec",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"symfony/console": "<6.4"
},
"require-dev": {
"symfony/console": "^6.4|^7.0|^8.0"
},
"bin": [
"Resources/bin/yaml-lint"
],
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v7.4.15"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-07-21T15:13:06+00:00"
},
{
"name": "theseer/tokenizer",
"version": "1.3.1",