diff --git a/.env.docker.example b/.env.docker.example new file mode 100644 index 0000000..828c26d --- /dev/null +++ b/.env.docker.example @@ -0,0 +1,137 @@ +# ============================================================================== +# EZSCALE — Docker Compose dev environment +# Copy to .env.docker and fill in third-party credentials. +# This file is loaded by app, horizon, and scheduler containers. +# ============================================================================== + +APP_NAME="EZSCALE Billing" +APP_ENV=local +# APP_KEY is intentionally NOT set here. The entrypoint runs `php artisan key:generate` +# which writes the key to website/.env. If APP_KEY were defined here as empty, +# the empty env var would override the .env file value (env_file beats dotenv). +APP_DEBUG=true +APP_URL=http://ezscale.docker.localhost + +APP_LOCALE=en +APP_FALLBACK_LOCALE=en +APP_FAKER_LOCALE=en_US + +APP_MAINTENANCE_DRIVER=file + +BCRYPT_ROUNDS=10 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +# ============================================================================== +# Database — points at the `mariadb` compose service +# ============================================================================== +DB_CONNECTION=mysql +DB_HOST=mariadb +DB_PORT=3306 +DB_DATABASE=ezscale_billing +DB_USERNAME=ezscale +DB_PASSWORD=ezscale_local +DB_ROOT_PASSWORD=root + +# ============================================================================== +# Cache / sessions / queues — points at the `valkey` compose service +# ============================================================================== +SESSION_DRIVER=redis +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=.ezscale.docker.localhost + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=redis +CACHE_STORE=redis + +REDIS_CLIENT=phpredis +REDIS_HOST=valkey +REDIS_PASSWORD=null +REDIS_PORT=6379 + +# ============================================================================== +# Subdomain routing +# ============================================================================== +DOMAIN_MARKETING=ezscale.docker.localhost +DOMAIN_ACCOUNT=account.ezscale.docker.localhost +DOMAIN_ADMIN=admin.ezscale.docker.localhost + +# ============================================================================== +# Mail — points at the `mailpit` compose service +# ============================================================================== +MAIL_MAILER=smtp +MAIL_SCHEME=null +MAIL_HOST=mailpit +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_FROM_ADDRESS="noreply@ezscale.cloud" +MAIL_FROM_NAME="${APP_NAME}" + +# ============================================================================== +# Stripe — fill with your test-mode keys +# ============================================================================== +STRIPE_KEY= +STRIPE_SECRET= +STRIPE_WEBHOOK_SECRET= + +# ============================================================================== +# PayPal — sandbox credentials +# ============================================================================== +PAYPAL_MODE=sandbox +PAYPAL_SANDBOX_CLIENT_ID= +PAYPAL_SANDBOX_CLIENT_SECRET= + +# ============================================================================== +# Discord admin alerts (optional) +# ============================================================================== +DISCORD_WEBHOOK_URL= + +# ============================================================================== +# Provisioning APIs — external services, fill if you need to test provisioning +# ============================================================================== +VIRTFUSION_API_URL= +VIRTFUSION_API_KEY= +PTERODACTYL_API_URL= +PTERODACTYL_API_KEY= +SYNERGYCP_API_URL= +SYNERGYCP_API_KEY= +ENHANCE_API_URL= +ENHANCE_API_KEY= + +# ============================================================================== +# Screenshot Authentication (Dev/Local Only) +# ============================================================================== +SCREENSHOT_AUTH_ENABLED=false +SCREENSHOT_TOKEN= + +# ============================================================================== +# Support Ticket Email Integration (IMAP) — optional +# ============================================================================== +SUPPORT_EMAIL=support@ezscale.cloud +TICKET_EMAIL_POLLING=false +IMAP_HOST=outlook.office365.com +IMAP_PORT=993 +IMAP_ENCRYPTION=ssl +IMAP_USERNAME= +IMAP_PASSWORD= +IMAP_VALIDATE_CERT=true +IMAP_PROTOCOL=imap +IMAP_FOLDER=INBOX + +# ============================================================================== +# ServerHunter Integration (optional) +# ============================================================================== +SERVERHUNTER_API_KEY= + +# ============================================================================== +# Vite — Laravel Vite plugin reads this +# ============================================================================== +VITE_APP_NAME="${APP_NAME}" +VITE_DEV_SERVER_URL=http://vite.ezscale.docker.localhost diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1e9ddcb --- /dev/null +++ b/Makefile @@ -0,0 +1,135 @@ +# ============================================================================== +# EZSCALE — Makefile shortcuts for the docker compose dev stack +# ============================================================================== + +SHELL := /bin/bash +DC := docker compose +EXEC := $(DC) exec -T app +RUN := $(DC) run --rm app + +.DEFAULT_GOAL := help + +# -------------------------------------------------------------------- lifecycle +.PHONY: help +help: ## Show this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) + +.PHONY: init +init: ## First-time setup: copy .env.docker, build, install deps, migrate + @if [ ! -f .env.docker ]; then cp .env.docker.example .env.docker && echo "[init] created .env.docker"; fi + $(DC) build --pull + $(DC) up -d mariadb valkey + @echo "[init] waiting 10s for mariadb to settle..." + @sleep 10 + $(RUN) composer install + $(DC) run --rm vite npm install + $(DC) up -d + @echo "" + @echo "Stack is up. Open https://ezscale.docker.localhost" + +.PHONY: up +up: ## Start all services in the background + $(DC) up -d + +.PHONY: down +down: ## Stop all services (volumes preserved) + $(DC) down + +.PHONY: restart +restart: ## Restart all services + $(DC) restart + +.PHONY: build +build: ## Rebuild all images + $(DC) build --pull + +.PHONY: rebuild +rebuild: ## Rebuild from scratch (no cache) + $(DC) build --pull --no-cache + +.PHONY: destroy +destroy: ## Stop everything AND wipe data volumes (DB, mail, etc.) + $(DC) down -v + +.PHONY: ps +ps: ## Show service status + $(DC) ps + +# ------------------------------------------------------------------------ logs +.PHONY: logs +logs: ## Tail logs (use SVC=name to scope to one service) +ifdef SVC + $(DC) logs -f $(SVC) +else + $(DC) logs -f +endif + +# -------------------------------------------------------------------- shells +.PHONY: sh +sh: ## Bash inside the app container + $(DC) exec app bash + +.PHONY: web-sh +web-sh: ## Shell inside the nginx container + $(DC) exec web sh + +.PHONY: db-sh +db-sh: ## MariaDB CLI + $(DC) exec mariadb mariadb -uezscale -pezscale_local ezscale_billing + +.PHONY: redis-sh +redis-sh: ## Valkey CLI + $(DC) exec valkey valkey-cli + +# ----------------------------------------------------------- artisan / composer +.PHONY: artisan +artisan: ## Run an artisan command (use ARGS="migrate") + $(EXEC) php artisan $(ARGS) + +.PHONY: composer +composer: ## Run composer (use ARGS="require ...") + $(EXEC) composer $(ARGS) + +.PHONY: tinker +tinker: ## Open a tinker shell + $(DC) exec app php artisan tinker + +# ---------------------------------------------------------------------- frontend +.PHONY: npm +npm: ## Run npm in the vite container (use ARGS="install ...") + $(DC) exec vite npm $(ARGS) + +.PHONY: vite-build +vite-build: ## One-off production build + $(DC) run --rm vite npm run build + +# ----------------------------------------------------------------------- testing +.PHONY: test +test: ## Run the Pest suite + $(EXEC) php artisan test --compact $(ARGS) + +.PHONY: pint +pint: ## Format dirty PHP files + $(EXEC) vendor/bin/pint --dirty --format agent + +# -------------------------------------------------------------- DB convenience +.PHONY: migrate +migrate: ## Run pending migrations + $(EXEC) php artisan migrate + +.PHONY: fresh +fresh: ## Drop all tables, re-migrate, seed + $(EXEC) php artisan migrate:fresh --seed + +.PHONY: seed +seed: ## Run seeders + $(EXEC) php artisan db:seed + +# --------------------------------------------------------------- diagnostics +.PHONY: doctor +doctor: ## Print key compose info for debugging + $(DC) config --services + @echo "" + $(DC) ps + @echo "" + $(DC) exec app php -v 2>/dev/null || echo "app not running" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..4518435 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,220 @@ +# ============================================================================== +# EZSCALE — Docker Compose dev environment +# Spec: docs/superpowers/specs/2026-04-25-docker-compose-dev-environment-design.md +# +# Quick start: +# cp .env.docker.example .env.docker +# make up +# +# Hostnames (auto-resolve to 127.0.0.1): +# https://ezscale.docker.localhost — marketing +# https://account.ezscale.docker.localhost — customer dashboard +# https://admin.ezscale.docker.localhost — admin panel +# https://account.ezscale.docker.localhost/horizon — Horizon dashboard +# https://mail.ezscale.docker.localhost — Mailpit UI +# https://vite.ezscale.docker.localhost — Vite dev server +# http://localhost:8080 — Traefik dashboard (insecure) +# ============================================================================== + +name: ezscale + +x-app-base: &app-base + build: + context: ./docker/app + args: + UID: ${UID:-1000} + GID: ${GID:-1000} + image: ezscale/app:dev + env_file: + - .env.docker + volumes: + - ./website:/var/www/html + networks: + - ezscale + depends_on: + mariadb: + condition: service_healthy + valkey: + condition: service_healthy + mailpit: + condition: service_started + +services: + # --------------------------------------------------------------------------- + # Edge: Traefik (TLS + routing) + # --------------------------------------------------------------------------- + traefik: + image: traefik:v3.6 + restart: unless-stopped + command: [] + ports: + - "80:80" + - "443:443" + - "8080:8080" + volumes: + - ./docker/traefik/traefik.yml:/etc/traefik/traefik.yml:ro + - ./docker/traefik/dynamic.yml:/etc/traefik/dynamic.yml:ro + - traefik_certs:/etc/traefik/acme + - /var/run/docker.sock:/var/run/docker.sock:ro + networks: + - ezscale + labels: + - "traefik.enable=true" + + # --------------------------------------------------------------------------- + # PHP-FPM application container (php artisan serve replacement) + # --------------------------------------------------------------------------- + app: + <<: *app-base + container_name: ezscale-app + restart: unless-stopped + command: ["php-fpm"] + + # --------------------------------------------------------------------------- + # nginx — serves public/, proxies PHP to app:9000 + # --------------------------------------------------------------------------- + web: + build: + context: ./docker/nginx + image: ezscale/nginx:dev + restart: unless-stopped + volumes: + - ./website:/var/www/html:ro + - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro + networks: + - ezscale + depends_on: + - app + labels: + - "traefik.enable=true" + - "traefik.docker.network=ezscale" + - "traefik.http.services.ezscale-web.loadbalancer.server.port=80" + - "traefik.http.routers.ezscale-web.rule=Host(`ezscale.docker.localhost`) || Host(`account.ezscale.docker.localhost`) || Host(`admin.ezscale.docker.localhost`)" + - "traefik.http.routers.ezscale-web.entrypoints=web" + + # --------------------------------------------------------------------------- + # Vite dev server (HMR) + # --------------------------------------------------------------------------- + vite: + build: + context: ./docker/vite + args: + UID: ${UID:-1000} + GID: ${GID:-1000} + image: ezscale/vite:dev + restart: unless-stopped + working_dir: /var/www/html + environment: + VITE_HOST: "0.0.0.0" + VITE_ORIGIN: "http://vite.ezscale.docker.localhost" + VITE_HMR_HOST: "vite.ezscale.docker.localhost" + volumes: + - ./website:/var/www/html + networks: + - ezscale + labels: + - "traefik.enable=true" + - "traefik.docker.network=ezscale" + - "traefik.http.services.ezscale-vite.loadbalancer.server.port=5173" + - "traefik.http.routers.ezscale-vite.rule=Host(`vite.ezscale.docker.localhost`)" + - "traefik.http.routers.ezscale-vite.entrypoints=web" + + # --------------------------------------------------------------------------- + # Horizon — queue worker supervisor (Redis-only) + # --------------------------------------------------------------------------- + horizon: + <<: *app-base + container_name: ezscale-horizon + restart: unless-stopped + command: ["php", "artisan", "horizon"] + stop_signal: SIGTERM + stop_grace_period: 60s + + # --------------------------------------------------------------------------- + # Scheduler — runs `schedule:work` in a loop (cron replacement) + # --------------------------------------------------------------------------- + scheduler: + <<: *app-base + container_name: ezscale-scheduler + restart: unless-stopped + command: ["php", "artisan", "schedule:work"] + + # --------------------------------------------------------------------------- + # MariaDB — primary database + # --------------------------------------------------------------------------- + mariadb: + image: mariadb:12 + restart: unless-stopped + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --skip-character-set-client-handshake + environment: + MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-root} + MARIADB_DATABASE: ${DB_DATABASE:-ezscale_billing} + MARIADB_USER: ${DB_USERNAME:-ezscale} + MARIADB_PASSWORD: ${DB_PASSWORD:-ezscale_local} + volumes: + - mariadb_data:/var/lib/mysql + - ./docker/mariadb/init:/docker-entrypoint-initdb.d:ro + networks: + - ezscale + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 5s + timeout: 5s + retries: 20 + start_period: 30s + + # --------------------------------------------------------------------------- + # Valkey — sessions, cache, queues + # --------------------------------------------------------------------------- + valkey: + image: valkey/valkey:9-alpine + restart: unless-stopped + command: ["valkey-server", "--appendonly", "yes"] + volumes: + - valkey_data:/data + networks: + - ezscale + healthcheck: + test: ["CMD", "valkey-cli", "ping"] + interval: 5s + timeout: 3s + retries: 10 + + # --------------------------------------------------------------------------- + # Mailpit — SMTP catcher + web UI + # --------------------------------------------------------------------------- + mailpit: + image: axllent/mailpit:v1.29 + restart: unless-stopped + environment: + MP_SMTP_AUTH_ACCEPT_ANY: "1" + MP_SMTP_AUTH_ALLOW_INSECURE: "1" + MP_MAX_MESSAGES: "5000" + volumes: + - mailpit_data:/data + networks: + - ezscale + labels: + - "traefik.enable=true" + - "traefik.docker.network=ezscale" + - "traefik.http.services.ezscale-mail.loadbalancer.server.port=8025" + - "traefik.http.routers.ezscale-mail.rule=Host(`mail.ezscale.docker.localhost`)" + - "traefik.http.routers.ezscale-mail.entrypoints=web" + +# ============================================================================== +# Volumes & networks +# ============================================================================== + +volumes: + mariadb_data: + valkey_data: + mailpit_data: + traefik_certs: + +networks: + ezscale: + name: ezscale + driver: bridge diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..1844059 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,142 @@ +# EZSCALE — Docker Compose Dev Environment + +Multi-service development stack for the EZSCALE Laravel app. Replaces the bare-metal `composer run dev` workflow with a fully-containerized environment that mirrors the production topology (nginx + PHP-FPM + MariaDB + Valkey + Horizon). + +## Prerequisites + +- **Docker Engine 24+** with **Compose V2** (`docker compose`, not `docker-compose`) +- **WSL2 with files cloned under `/home/$USER/`** (NOT `/mnt/c/...` — bind-mount performance is unusable on the Windows-mounted filesystem) +- A modern browser (Chrome, Firefox, Safari) — `*.docker.localhost` resolution requires no `/etc/hosts` edits + +## First-time setup + +```bash +make init +``` + +That single command: +1. Copies `.env.docker.example` → `.env.docker` +2. Builds all custom images (PHP-FPM, nginx, vite) +3. Pulls third-party images (Traefik, MariaDB, Valkey, Mailpit) +4. Boots MariaDB and Valkey, waits for them to be healthy +5. Runs `composer install` and `npm install` +6. Brings up the rest of the stack + +When `make init` finishes, you should be able to open: + +- **https://ezscale.docker.localhost** — marketing site +- **https://account.ezscale.docker.localhost** — customer dashboard +- **https://admin.ezscale.docker.localhost** — admin panel +- **https://account.ezscale.docker.localhost/horizon** — Horizon dashboard +- **https://mail.ezscale.docker.localhost** — Mailpit UI (catches all outgoing email) +- **https://vite.ezscale.docker.localhost** — Vite dev server (for HMR) +- **http://localhost:8080** — Traefik dashboard (insecure, dev-only) + +The first time you visit any of these, your browser will warn about a self-signed cert. Accept once — Traefik issues a wildcard cert covering all subdomains. + +## Daily commands + +```bash +make up # bring stack up +make down # stop (volumes preserved) +make logs # tail all logs +make logs SVC=horizon # tail one service +make sh # bash inside app container +make artisan ARGS="migrate" # any artisan command +make composer ARGS="require foo/bar" +make npm ARGS="install foo" +make test # php artisan test --compact +make pint # format dirty PHP +make fresh # migrate:fresh --seed +make destroy # nuclear: stop + wipe volumes +``` + +`make help` prints the full list. + +## Architecture + +| Service | Image | Role | +|---------|-------|------| +| `traefik` | `traefik:v3.6` | Edge proxy + TLS termination + routing | +| `app` | custom (PHP 8.3-FPM Debian) | Application container | +| `web` | `nginx:1.30-alpine` | Serves `public/`, proxies PHP | +| `vite` | custom (Node 24 Alpine) | HMR dev server | +| `horizon` | same as `app` | Queue worker supervisor | +| `scheduler` | same as `app` | `schedule:work` runner | +| `mariadb` | `mariadb:12` | Primary database | +| `valkey` | `valkey/valkey:9-alpine` | Sessions/cache/queues | +| `mailpit` | `axllent/mailpit:v1.29` | SMTP catcher | + +Traefik routes the three Laravel subdomains (marketing/account/admin) to the same nginx container. Laravel's `Route::domain()` in `bootstrap/app.php` handles per-subdomain dispatch internally. + +## Environment + +The stack reads `.env.docker` at the repo root — separate from `website/.env`. This keeps the Docker workflow from fighting any bare-metal `composer run dev` setup you might still want to use. + +Critical Docker-specific values: + +``` +DB_HOST=mariadb +REDIS_HOST=valkey +MAIL_HOST=mailpit +APP_URL=https://ezscale.docker.localhost +``` + +Third-party API keys (Stripe, PayPal, VirtFusion, etc.) need to be added to your `.env.docker` if you want to test those integrations. + +## Volumes + +Persisted across `make down` (lost only on `make destroy`): + +- `mariadb_data` — MySQL data +- `valkey_data` — Valkey AOF persistence +- `mailpit_data` — captured email +- `traefik_certs` — self-signed cert cache + +The Laravel source (`./website`) is bind-mounted live — your edits show up immediately. `vendor/` and `node_modules/` are visible on the host for IDE autocomplete. + +## TLS + +Traefik auto-generates a single self-signed wildcard cert for `*.ezscale.docker.localhost` on first boot. The cert lives in the `traefik_certs` volume. + +If you want a green-padlock experience instead of accepting the warning once per browser: + +```bash +brew install mkcert # or apt/winget equivalent +mkcert -install +mkcert -cert-file docker/traefik/certs/cert.pem \ + -key-file docker/traefik/certs/key.pem \ + "ezscale.docker.localhost" "*.ezscale.docker.localhost" +``` + +Then update `docker/traefik/dynamic.yml` to point `certificates:` at those files. Currently configured for self-signed; mkcert is left as a future enhancement. + +## Common gotchas + +**Port 80 or 443 already in use.** +Edit `docker-compose.yml`'s `traefik` service and remap to e.g. `8000:80`, `8443:443`. Then access the stack at `https://ezscale.docker.localhost:8443`. + +**`make init` hangs on "waiting for mariadb".** +First MariaDB boot creates the system tablespace and can take 20-30s. The healthcheck has a 30s `start_period` to accommodate this. If it really stalls, `make logs SVC=mariadb` to see why. + +**Permission errors on `storage/logs/laravel.log`.** +The PHP container's UID matches your host UID (1000) by default. If your host UID differs, rebuild with `UID=$(id -u) GID=$(id -g) make build`. + +**Horizon dashboard 403s.** +Horizon's gate is in `App\Providers\HorizonServiceProvider::gate()`. In dev all admin users have access; you need to log in with an admin role first. + +**Vite assets don't load.** +Check `make logs SVC=vite`. The Laravel Vite plugin auto-injects the dev URL — if it can't reach `https://vite.ezscale.docker.localhost`, assets fall back to the manifest. Make sure that hostname is reachable in your browser. + +**Composer/npm install slow.** +First-time `composer install` takes 1-2 min. After that the `vendor/` dir is cached on disk. Same for `node_modules`. + +## Co-existing with bare-metal dev + +This stack does NOT delete or modify `website/.env`. If you previously used `cd website && composer run dev`, that still works — it reads `website/.env` and connects to whatever local PHP/MySQL/Redis you had. + +Pick one or the other for any given session. Don't run both simultaneously (they'd fight over ports and sessions). + +## Spec + +Full design rationale in [`docs/superpowers/specs/2026-04-25-docker-compose-dev-environment-design.md`](../docs/superpowers/specs/2026-04-25-docker-compose-dev-environment-design.md). diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile new file mode 100644 index 0000000..3629e6c --- /dev/null +++ b/docker/app/Dockerfile @@ -0,0 +1,64 @@ +FROM php:8.3-fpm-bookworm + +ARG UID=1000 +ARG GID=1000 + +ENV COMPOSER_ALLOW_SUPERUSER=1 \ + COMPOSER_NO_INTERACTION=1 \ + COMPOSER_MEMORY_LIMIT=-1 + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + git \ + unzip \ + curl \ + ca-certificates \ + libzip-dev \ + libpng-dev \ + libjpeg-dev \ + libfreetype6-dev \ + libwebp-dev \ + libicu-dev \ + libonig-dev \ + libxml2-dev \ + libcurl4-openssl-dev \ + libssl-dev \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \ + && docker-php-ext-install -j"$(nproc)" \ + pdo_mysql \ + intl \ + bcmath \ + gd \ + zip \ + pcntl \ + posix \ + exif \ + sockets \ + opcache + +RUN pecl install redis \ + && docker-php-ext-enable redis + +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +RUN groupmod -g ${GID} www-data \ + && usermod -u ${UID} -g ${GID} www-data \ + && mkdir -p /var/www/.composer \ + && chown -R www-data:www-data /var/www + +COPY php.ini /usr/local/etc/php/conf.d/zz-app.ini +COPY opcache.ini /usr/local/etc/php/conf.d/zz-opcache.ini +COPY php-fpm.conf /usr/local/etc/php-fpm.d/zz-app.conf +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +WORKDIR /var/www/html +USER www-data + +EXPOSE 9000 + +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +CMD ["php-fpm"] diff --git a/docker/app/entrypoint.sh b/docker/app/entrypoint.sh new file mode 100644 index 0000000..c0e1573 --- /dev/null +++ b/docker/app/entrypoint.sh @@ -0,0 +1,55 @@ +#!/bin/sh +set -e + +# ============================================================================== +# EZSCALE app container entrypoint +# Used by `app`, `horizon`, and `scheduler` services. Idempotent. +# ============================================================================== + +cd /var/www/html + +# Wait for MariaDB. depends_on: condition: service_healthy already gates this, +# but the belt-and-braces loop is cheap and survives healthcheck regressions. +if [ -n "${DB_HOST:-}" ]; then + echo "[entrypoint] waiting for ${DB_HOST}:${DB_PORT:-3306}..." + until php -r "new PDO('mysql:host=${DB_HOST};port=${DB_PORT:-3306}', '${DB_USERNAME}', '${DB_PASSWORD}');" 2>/dev/null; do + sleep 1 + done + echo "[entrypoint] mariadb is up." +fi + +# Bootstrap .env on first boot. We bind-mount the website/ source, so .env may +# already exist from a previous bare-metal `composer run dev` workflow. +if [ ! -f .env ]; then + if [ -f /var/www/html/.env.docker ]; then + echo "[entrypoint] copying .env.docker -> .env" + cp /var/www/html/.env.docker .env + elif [ -f .env.example ]; then + echo "[entrypoint] copying .env.example -> .env (fallback)" + cp .env.example .env + fi +fi + +# Vendor dir bootstrapping — first-clone convenience. Skipped if already present. +if [ ! -d vendor ] || [ ! -f vendor/autoload.php ]; then + echo "[entrypoint] vendor/ missing; running composer install" + composer install --no-interaction --prefer-dist --no-progress +fi + +# Generate APP_KEY if blank. `key:generate` writes to .env in place. +if ! grep -qE '^APP_KEY=base64:' .env; then + echo "[entrypoint] generating APP_KEY" + php artisan key:generate --force --no-interaction +fi + +# Run migrations only when this container is the `app` (php-fpm) role. +# Horizon and scheduler share this image but skip migrations to avoid races. +case "$1" in + php-fpm|php-fpm*) + echo "[entrypoint] running migrations" + php artisan migrate --force --no-interaction || true + php artisan storage:link || true + ;; +esac + +exec "$@" diff --git a/docker/app/opcache.ini b/docker/app/opcache.ini new file mode 100644 index 0000000..7594c49 --- /dev/null +++ b/docker/app/opcache.ini @@ -0,0 +1,18 @@ +; ============================================================================== +; OPcache — DEV configuration +; In prod, flip validate_timestamps to 0 and lock the cache. +; ============================================================================== + +opcache.enable = 1 +opcache.enable_cli = 1 +opcache.memory_consumption = 256 +opcache.interned_strings_buffer = 32 +opcache.max_accelerated_files = 20000 + +; Recheck files on every request — edits show up immediately +opcache.validate_timestamps = 1 +opcache.revalidate_freq = 0 + +opcache.fast_shutdown = 1 +opcache.jit = tracing +opcache.jit_buffer_size = 100M diff --git a/docker/app/php-fpm.conf b/docker/app/php-fpm.conf new file mode 100644 index 0000000..d014d8f --- /dev/null +++ b/docker/app/php-fpm.conf @@ -0,0 +1,23 @@ +; ============================================================================== +; PHP-FPM pool — DEV configuration +; ============================================================================== + +[www] +user = www-data +group = www-data + +listen = 9000 +listen.backlog = 511 + +pm = dynamic +pm.max_children = 25 +pm.start_servers = 4 +pm.min_spare_servers = 2 +pm.max_spare_servers = 8 +pm.max_requests = 1000 + +; Surface FPM logs to stdout/stderr so `docker compose logs app` shows them +access.log = /proc/self/fd/2 +catch_workers_output = yes +decorate_workers_output = no +clear_env = no diff --git a/docker/app/php.ini b/docker/app/php.ini new file mode 100644 index 0000000..2ebf56c --- /dev/null +++ b/docker/app/php.ini @@ -0,0 +1,24 @@ +; ============================================================================== +; EZSCALE dev overrides — applied AFTER php.ini-development +; ============================================================================== + +memory_limit = 512M +max_execution_time = 120 +post_max_size = 50M +upload_max_filesize = 50M +max_input_vars = 5000 + +display_errors = On +display_startup_errors = On +error_reporting = E_ALL +log_errors = On + +date.timezone = UTC + +; Session handling delegated to Laravel; keep PHP-side defaults sane +session.cookie_httponly = 1 +session.cookie_samesite = "Lax" + +; Realpath cache helps Composer/Laravel reload cycles +realpath_cache_size = 4096K +realpath_cache_ttl = 600 diff --git a/docker/mariadb/init/01-create-test-db.sql b/docker/mariadb/init/01-create-test-db.sql new file mode 100644 index 0000000..93250b0 --- /dev/null +++ b/docker/mariadb/init/01-create-test-db.sql @@ -0,0 +1,9 @@ +-- Runs once on first MariaDB volume bootstrap. +-- Creates the testing database used by `php artisan test`. + +CREATE DATABASE IF NOT EXISTS ezscale_billing_testing + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +GRANT ALL PRIVILEGES ON ezscale_billing_testing.* TO 'ezscale'@'%'; +FLUSH PRIVILEGES; diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 0000000..1da4e38 --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,8 @@ +FROM nginx:1.30-alpine + +RUN rm -f /etc/nginx/conf.d/default.conf + +COPY nginx.conf /etc/nginx/nginx.conf +COPY conf.d/ /etc/nginx/conf.d/ + +EXPOSE 80 diff --git a/docker/nginx/conf.d/ezscale.conf b/docker/nginx/conf.d/ezscale.conf new file mode 100644 index 0000000..179befb --- /dev/null +++ b/docker/nginx/conf.d/ezscale.conf @@ -0,0 +1,54 @@ +# ============================================================================== +# EZSCALE catch-all server block +# Traefik routes all 3 subdomains (marketing/account/admin) here. Laravel's +# Route::domain() in bootstrap/app.php handles per-subdomain dispatch. +# ============================================================================== + +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + root /var/www/html/public; + index index.php index.html; + + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options "nosniff"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + + charset utf-8; + + location = /favicon.ico { access_log off; log_not_found off; } + location = /robots.txt { access_log off; log_not_found off; } + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass php-upstream; + fastcgi_index index.php; + + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + fastcgi_param HTTP_PROXY ""; + + # Match Traefik forwarded headers + fastcgi_param HTTPS $http_x_forwarded_proto; + fastcgi_param REMOTE_ADDR $http_x_forwarded_for; + + fastcgi_buffers 16 16k; + fastcgi_buffer_size 32k; + fastcgi_read_timeout 300; + } + + # Deny dotfiles except .well-known (LE/CSP) + location ~ /\.(?!well-known).* { + deny all; + access_log off; + log_not_found off; + } +} diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 0000000..d1cac6e --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,40 @@ +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent" "$host"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + server_tokens off; + + # Traefik handles compression at the edge — leave it off here. + gzip off; + + # 50M for file uploads (matches php upload_max_filesize) + client_max_body_size 50M; + + # Upstream PHP-FPM + upstream php-upstream { + server app:9000; + } + + include /etc/nginx/conf.d/*.conf; +} diff --git a/docker/traefik/dynamic.yml b/docker/traefik/dynamic.yml new file mode 100644 index 0000000..74cd509 --- /dev/null +++ b/docker/traefik/dynamic.yml @@ -0,0 +1,17 @@ +# ============================================================================== +# Traefik dynamic config — TLS options + self-signed wildcard cert +# ============================================================================== + +tls: + options: + default: + minVersion: VersionTLS12 + sniStrict: false + stores: + default: + defaultGeneratedCert: + resolver: "" + domain: + main: "ezscale.docker.localhost" + sans: + - "*.ezscale.docker.localhost" diff --git a/docker/traefik/traefik.yml b/docker/traefik/traefik.yml new file mode 100644 index 0000000..4462850 --- /dev/null +++ b/docker/traefik/traefik.yml @@ -0,0 +1,33 @@ +# ============================================================================== +# Traefik static config — DEV +# ============================================================================== + +global: + checkNewVersion: false + sendAnonymousUsage: false + +api: + dashboard: true + insecure: true # Dev-only: dashboard at :8080 with no auth + +log: + level: INFO + +accessLog: {} + +entryPoints: + web: + address: ":80" + websecure: + address: ":443" + traefik: + address: ":8080" + +providers: + docker: + exposedByDefault: false + network: ezscale + watch: true + file: + filename: /etc/traefik/dynamic.yml + watch: true diff --git a/docker/vite/Dockerfile b/docker/vite/Dockerfile new file mode 100644 index 0000000..cc6283d --- /dev/null +++ b/docker/vite/Dockerfile @@ -0,0 +1,16 @@ +FROM node:24-alpine + +ARG UID=1000 +ARG GID=1000 + +RUN apk add --no-cache git \ + && deluser --remove-home node 2>/dev/null || true \ + && addgroup -g ${GID} node \ + && adduser -D -u ${UID} -G node node + +WORKDIR /var/www/html +USER node + +EXPOSE 5173 + +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173"] diff --git a/docs/superpowers/specs/2026-04-25-docker-compose-dev-environment-design.md b/docs/superpowers/specs/2026-04-25-docker-compose-dev-environment-design.md new file mode 100644 index 0000000..383f34e --- /dev/null +++ b/docs/superpowers/specs/2026-04-25-docker-compose-dev-environment-design.md @@ -0,0 +1,226 @@ +# Docker Compose Dev Environment — Design Spec + +## Overview + +Replace the bare-metal `composer run dev` workflow (which assumes host-installed PHP 8.3, Node 24, MariaDB, Valkey/Redis, and Mailpit) with a fully-containerized multi-service stack orchestrated by `docker compose`. Removes the `laravel/sail` dev dependency. The stack runs the existing single Laravel application — including its three subdomains (`marketing`, `account`, `admin`) — across 9 purpose-built services on a single Compose project. + +## Goals + +- Single command (`docker compose up -d` or `make up`) brings up the entire dev environment from a fresh clone +- All three subdomains reachable in the browser with TLS +- Hot-reloading frontend assets via Vite, Horizon dashboard, scheduled jobs, queue workers, and trapped outgoing mail +- Dev/prod parity: nginx + PHP-FPM (matches likely Kubernetes target), official MariaDB & Valkey images +- No `/etc/hosts` edits, no host-side Node/PHP installs required +- Existing `composer run dev` flow stays usable for anyone who prefers bare-metal — Docker stack reads its own `.env.docker`, doesn't fight `website/.env` + +## Non-Goals + +- Production Dockerfiles / Helm charts (separate workstream; this Dockerfile is dev-tuned) +- Mocking external provisioning APIs (VirtFusion, SynergyCP, Pterodactyl, Enhance) — those stay external, configured via env +- HTTPS with locally-trusted CA (mkcert) — using Traefik self-signed; revisit if cert warnings become annoying + +## Architecture + +### Service map (9 services) + +| # | Service | Image | Role | Exposed via | +|---|---------|-------|------|-------------| +| 1 | `traefik` | `traefik:v3.6` | Edge proxy + TLS termination + routing | Host ports 80, 443, 8080 | +| 2 | `app` | custom (`docker/app/Dockerfile`) | PHP 8.3-FPM | Internal only | +| 3 | `web` | `nginx:1.30-alpine` | Serves `public/`, proxies PHP to `app:9000` | Traefik → 3 vhosts | +| 4 | `vite` | custom (`docker/vite/Dockerfile`) | `npm run dev` for HMR | Traefik → `vite.ezscale.docker.localhost` | +| 5 | `horizon` | same image as `app` | `php artisan horizon` | Internal | +| 6 | `scheduler` | same image as `app` | `php artisan schedule:work` | Internal | +| 7 | `mariadb` | `mariadb:12` | Primary database (utf8mb4 + utf8mb4_unicode_ci pinned) | Internal | +| 8 | `valkey` | `valkey/valkey:9-alpine` | Sessions, cache, queues | Internal | +| 9 | `mailpit` | `axllent/mailpit:v1.29` | SMTP catcher + UI | Traefik → `mail.ezscale.docker.localhost` | + +### Image base decisions + +- **PHP container**: `php:8.3-fpm-bookworm` (Debian) — chosen over Alpine because (a) `musl` DNS edge cases are a real risk for an app calling many external APIs (Stripe, PayPal, VirtFusion, SynergyCP, Pterodactyl, MaxMind, Outlook IMAP), (b) extension-install Dockerfile is half as complex on Debian, (c) Forge/Vapor and most public Laravel images on Kubernetes use Debian, (d) the 245MB image-size delta is paid once per node per image SHA. Easy to swap later — Dockerfile is structured so `FROM` swap is the only mechanical change. +- **Other Linux services**: Alpine where official Alpine variants exist (nginx, vite, valkey). +- **MariaDB & Mailpit**: no official Alpine; MariaDB stays Debian, Mailpit is already FROM-scratch single-binary. +- **Traefik**: scratch-based; smaller than Alpine. + +### Hostnames (browser-facing) + +- `https://ezscale.docker.localhost` — marketing site +- `https://account.ezscale.docker.localhost` — customer dashboard +- `https://admin.ezscale.docker.localhost` — admin panel +- `https://account.ezscale.docker.localhost/horizon` — Horizon dashboard +- `https://mail.ezscale.docker.localhost` — Mailpit UI +- `https://vite.ezscale.docker.localhost` — Vite dev server +- `http://localhost:8080` — Traefik dashboard (insecure, dev-only) + +`*.docker.localhost` resolves to `127.0.0.1` natively in modern browsers — no `/etc/hosts` edits. + +### TLS strategy + +Traefik auto-generates a single wildcard self-signed cert covering `ezscale.docker.localhost` and `*.ezscale.docker.localhost`. Browser shows a warning on first visit; after accepting, all subdomains share the trust decision. Configured in `docker/traefik/dynamic.yml` via `tls.stores.default.defaultGeneratedCert`. + +### Subdomain routing + +Traefik routes the three Laravel subdomains (marketing/account/admin) to the same `web` (nginx) container. Nginx uses a single catch-all `server_name _;` block. Laravel's existing `Route::domain(config('app.domains.*'))` in `bootstrap/app.php` handles the per-subdomain dispatch internally — no per-subdomain nginx vhost needed. + +Vite (port 5173) and Mailpit (port 8025) are routed to their own containers via separate Traefik label rules. + +### Service dependency graph + +``` +mariadb (healthcheck: mariadb-admin ping) ─┐ +valkey (healthcheck: valkey-cli ping) ─┼──► app ──► web ──► traefik + │ │ + │ ├──► horizon + │ └──► scheduler +mailpit (no healthcheck needed) ─┘ +vite ──► traefik (independent of app) +``` + +`app`, `horizon`, and `scheduler` use `depends_on` with `condition: service_healthy` for `mariadb` and `valkey`. They share the same image and bind-mount the same `website/` source — they differ only in `command:`. + +## Directory layout + +All Docker artifacts under a new `docker/` sibling of `website/`. Nothing inside `website/` is restructured. + +``` +/home/andrew/local_projects/website/ +├── docker-compose.yml ← NEW +├── .env.docker.example ← NEW (committed template) +├── .env.docker ← NEW (gitignored, copied from example) +├── Makefile ← NEW (ergonomic shortcuts) +├── docker/ +│ ├── README.md +│ ├── app/ +│ │ ├── Dockerfile +│ │ ├── php.ini +│ │ ├── opcache.ini +│ │ ├── php-fpm.conf +│ │ └── entrypoint.sh +│ ├── nginx/ +│ │ ├── Dockerfile +│ │ ├── nginx.conf +│ │ └── conf.d/ezscale.conf +│ ├── traefik/ +│ │ ├── traefik.yml +│ │ └── dynamic.yml +│ ├── vite/ +│ │ └── Dockerfile +│ └── mariadb/ +│ └── init/01-create-test-db.sql +└── website/ ← unchanged +``` + +## App container — extensions and config + +PHP extensions baked in: `pdo_mysql intl bcmath gd zip pcntl posix exif sockets opcache redis`. That covers Cashier, Horizon (pcntl/posix for signal handling), Inertia, dompdf, webklex/php-imap (which is pure-PHP, doesn't need ext-imap), and phpredis (`REDIS_CLIENT=phpredis`). + +Build args: `UID=1000 GID=1000` so the in-container user matches the host user. Files written by `composer install`, `artisan migrate`, etc. land as the host user — no chmod dance. + +`opcache.validate_timestamps=1` and `revalidate_freq=0` so file edits show up immediately. Inverse of prod settings. + +`entrypoint.sh` waits for MariaDB, copies `.env.docker` → `.env` if `.env` is missing, runs `key:generate` and `migrate --force` (both idempotent), creates the storage symlink, then execs the container's CMD. Same image is used for `app` (CMD `php-fpm`), `horizon` (CMD `php artisan horizon`), and `scheduler` (CMD `php artisan schedule:work`). + +## Volumes & persistence + +Named volumes (Docker-managed, persist across `docker compose down`): + +- `mariadb_data` — `/var/lib/mysql` +- `valkey_data` — `/data` (Valkey AOF/RDB persistence) +- `traefik_certs` — `/etc/traefik/acme` (self-signed cert cache) +- `mailpit_data` — `/data` (mailpit message store) + +Bind mounts: + +- `./website` → `/var/www/html` in `app`, `horizon`, `scheduler`, `web`, `vite`. Includes `vendor/` and `node_modules/` (visible on host for IDE). +- `./docker/nginx/conf.d` → `/etc/nginx/conf.d` (read-only) +- `./docker/traefik/*.yml` → `/etc/traefik/` (read-only) +- `./docker/mariadb/init` → `/docker-entrypoint-initdb.d` (read-only) + +WSL2-native filesystem (`/home/andrew/...` is ext4) makes bind-mounted `vendor/` and `node_modules/` performant. The named-volume overlay trick used on macOS isn't necessary here. + +## Environment handling + +Two env files coexist: + +- **`website/.env`** — used by bare-metal `composer run dev` (untouched by Docker workflow) +- **`.env.docker`** — used by Docker stack via Compose `env_file:`. Gitignored. Created by `cp .env.docker.example .env.docker`. + +Docker-specific env values: + +``` +APP_URL=https://ezscale.docker.localhost +DOMAIN_MARKETING=ezscale.docker.localhost +DOMAIN_ACCOUNT=account.ezscale.docker.localhost +DOMAIN_ADMIN=admin.ezscale.docker.localhost +SESSION_DOMAIN=.ezscale.docker.localhost + +DB_HOST=mariadb +DB_PORT=3306 +DB_DATABASE=ezscale_billing +DB_USERNAME=ezscale +DB_PASSWORD=ezscale_local + +REDIS_HOST=valkey +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailpit +MAIL_PORT=1025 + +QUEUE_CONNECTION=redis +SESSION_DRIVER=redis +CACHE_STORE=redis +``` + +External API keys (Stripe test, PayPal sandbox, VirtFusion, etc.) are placeholders in `.env.docker.example`; developers fill them in their local `.env.docker`. + +## Dev workflow (Makefile shortcuts) + +``` +make up # docker compose up -d +make down # docker compose down +make build # docker compose build --pull +make logs # docker compose logs -f +make logs SVC=horizon # tails one service +make sh # shell into app container +make artisan ARGS="..." # runs artisan inside app +make composer ARGS="..." # runs composer inside app +make npm ARGS="..." # runs npm inside vite +make test # php artisan test --compact +make pint # vendor/bin/pint --dirty --format agent +make fresh # migrate:fresh --seed inside app +make destroy # docker compose down -v (wipes volumes) +``` + +## Removals + +- **`laravel/sail` removed from `website/composer.json` require-dev**. +- `website/composer.lock` regenerated. +- The Sail binary (`website/vendor/bin/sail`) disappears on next `composer install`. +- No `docker-compose.yml` or `Dockerfile` from Sail to remove — Sail was installed but never published. + +## Modifications to existing files + +- `website/composer.json` — drop `laravel/sail` line +- `website/composer.lock` — regenerated +- Repo-root `.gitignore` — add `.env.docker` + +## Out of scope + +- Production Dockerfile (multi-stage, smaller, opcache locked) +- Kubernetes manifests / Helm chart +- mkcert / locally-trusted TLS +- Mocking provisioning APIs +- xdebug (can be added later via build arg) +- Containerized `composer install` / `npm install` orchestration on first boot — user runs these manually once per fresh clone via `make composer ARGS="install"` and `make npm ARGS="install"` + +## Risks & mitigations + +| Risk | Mitigation | +|------|-----------| +| Self-signed cert warnings annoying users with multiple browsers | Document mkcert as future upgrade path | +| Bind-mounted `vendor/` slow on WSL2 if user clones to `/mnt/c/...` | README explicitly tells users to clone under `/home/$USER/` | +| Horizon dashboard route at `/horizon` requires auth in prod — what about dev? | `App\Providers\HorizonServiceProvider::gate()` controls this; in dev, all admin users have access | +| `entrypoint.sh` auto-migrate could mask broken migrations | Idempotent; failure aborts startup, errors visible in `docker compose logs app` | +| Port 80/443 already used on host (e.g. another nginx) | README documents how to remap Traefik to 8000/8443 if needed | +| MariaDB 12 vs MySQL 8 collation drift on real prod migration | Compose pins `--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci`; same flags applied in prod prevents drift | diff --git a/website/bootstrap/app.php b/website/bootstrap/app.php index 81e61ba..88fae95 100644 --- a/website/bootstrap/app.php +++ b/website/bootstrap/app.php @@ -51,7 +51,7 @@ return Application::configure(basePath: dirname(__DIR__)) \App\Http\Middleware\ScreenshotAuthMiddleware::class, ); - $middleware->redirectGuestsTo(fn () => 'https://'.config('app.domains.account').'/login'); + $middleware->redirectGuestsTo(fn () => request()->getScheme().'://'.config('app.domains.account').'/login'); $middleware->redirectUsersTo('/dashboard'); $middleware->alias([ diff --git a/website/composer.json b/website/composer.json index 9098a27..8c7db68 100644 --- a/website/composer.json +++ b/website/composer.json @@ -29,7 +29,6 @@ "laravel/boost": "^2.1", "laravel/pail": "^1.2.2", "laravel/pint": "^1.24", - "laravel/sail": "^1.41", "mockery/mockery": "^1.6", "nunomaduro/collision": "^8.6", "pestphp/pest": "^4.3", diff --git a/website/composer.lock b/website/composer.lock index aee9e2b..c18b790 100644 --- a/website/composer.lock +++ b/website/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "58faeefce96f5a565ceecd0869605b38", + "content-hash": "477f77d2df504d36496e949d4979cbf5", "packages": [ { "name": "bacon/bacon-qr-code", - "version": "v3.0.3", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/Bacon/BaconQrCode.git", - "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563" + "reference": "4da2233e72eeecd9be3b62e0dc2cc9ed8e2e31c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/36a1cb2b81493fa5b82e50bf8068bf84d1542563", - "reference": "36a1cb2b81493fa5b82e50bf8068bf84d1542563", + "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/4da2233e72eeecd9be3b62e0dc2cc9ed8e2e31c2", + "reference": "4da2233e72eeecd9be3b62e0dc2cc9ed8e2e31c2", "shasum": "" }, "require": { @@ -57,32 +57,32 @@ "homepage": "https://github.com/Bacon/BaconQrCode", "support": { "issues": "https://github.com/Bacon/BaconQrCode/issues", - "source": "https://github.com/Bacon/BaconQrCode/tree/v3.0.3" + "source": "https://github.com/Bacon/BaconQrCode/tree/v3.1.1" }, - "time": "2025-11-19T17:15:36+00:00" + "time": "2026-04-05T21:06:35+00:00" }, { "name": "barryvdh/laravel-dompdf", - "version": "v3.1.1", + "version": "v3.1.2", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + "reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", - "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/ee3b72b19ccdf57d0243116ecb2b90261344dedc", + "reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc", "shasum": "" }, "require": { "dompdf/dompdf": "^3.0", - "illuminate/support": "^9|^10|^11|^12", + "illuminate/support": "^9|^10|^11|^12|^13.0", "php": "^8.1" }, "require-dev": { "larastan/larastan": "^2.7|^3.0", - "orchestra/testbench": "^7|^8|^9|^10", + "orchestra/testbench": "^7|^8|^9.16|^10|^11.0", "phpro/grumphp": "^2.5", "squizlabs/php_codesniffer": "^3.5" }, @@ -124,7 +124,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.2" }, "funding": [ { @@ -136,20 +136,20 @@ "type": "github" } ], - "time": "2025-02-13T15:07:54+00:00" + "time": "2026-02-21T08:51:10+00:00" }, { "name": "brick/math", - "version": "0.14.7", + "version": "0.14.8", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "07ff363b16ef8aca9692bba3be9e73fe63f34e50" + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/07ff363b16ef8aca9692bba3be9e73fe63f34e50", - "reference": "07ff363b16ef8aca9692bba3be9e73fe63f34e50", + "url": "https://api.github.com/repos/brick/math/zipball/63422359a44b7f06cae63c3b429b59e8efcc0629", + "reference": "63422359a44b7f06cae63c3b429b59e8efcc0629", "shasum": "" }, "require": { @@ -188,7 +188,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.14.7" + "source": "https://github.com/brick/math/tree/0.14.8" }, "funding": [ { @@ -196,7 +196,7 @@ "type": "github" } ], - "time": "2026-02-07T10:57:35+00:00" + "time": "2026-02-10T14:33:43+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -269,16 +269,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.10", + "version": "1.5.11", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63" + "reference": "68ff39175e8e94a4bb1d259407ce51a6a60f09e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/961a5e4056dd2e4a2eedcac7576075947c28bf63", - "reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/68ff39175e8e94a4bb1d259407ce51a6a60f09e6", + "reference": "68ff39175e8e94a4bb1d259407ce51a6a60f09e6", "shasum": "" }, "require": { @@ -325,7 +325,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.10" + "source": "https://github.com/composer/ca-bundle/tree/1.5.11" }, "funding": [ { @@ -337,7 +337,7 @@ "type": "github" } ], - "time": "2025-12-08T15:06:51+00:00" + "time": "2026-03-30T09:16:10+00:00" }, { "name": "dasprid/enum", @@ -700,16 +700,16 @@ }, { "name": "dompdf/dompdf", - "version": "v3.1.4", + "version": "v3.1.5", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "db712c90c5b9868df3600e64e68da62e78a34623" + "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623", - "reference": "db712c90c5b9868df3600e64e68da62e78a34623", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", + "reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496", "shasum": "" }, "require": { @@ -758,9 +758,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v3.1.4" + "source": "https://github.com/dompdf/dompdf/tree/v3.1.5" }, - "time": "2025-10-29T12:43:30+00:00" + "time": "2026-03-03T13:54:37+00:00" }, { "name": "dompdf/php-font-lib", @@ -986,16 +986,16 @@ }, { "name": "firebase/php-jwt", - "version": "v7.0.2", + "version": "v7.0.5", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "5645b43af647b6947daac1d0f659dd1fbe8d3b65" + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5645b43af647b6947daac1d0f659dd1fbe8d3b65", - "reference": "5645b43af647b6947daac1d0f659dd1fbe8d3b65", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", "shasum": "" }, "require": { @@ -1003,6 +1003,7 @@ }, "require-dev": { "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -1042,10 +1043,10 @@ "php" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.2" + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" }, - "time": "2025-12-16T22:17:28+00:00" + "time": "2026-04-01T20:38:03+00:00" }, { "name": "fruitcake/php-cors", @@ -1449,16 +1450,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884", "shasum": "" }, "require": { @@ -1474,6 +1475,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", + "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { @@ -1545,7 +1547,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" + "source": "https://github.com/guzzle/psr7/tree/2.9.0" }, "funding": [ { @@ -1561,7 +1563,7 @@ "type": "tidelift" } ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2026-03-10T16:41:02+00:00" }, { "name": "guzzlehttp/uri-template", @@ -1651,31 +1653,34 @@ }, { "name": "inertiajs/inertia-laravel", - "version": "v2.0.19", + "version": "v2.0.24", "source": { "type": "git", "url": "https://github.com/inertiajs/inertia-laravel.git", - "reference": "732a991342a0f82653a935440e2f3b9be1eb6f6e" + "reference": "ea345adad12f110edbbc4bef03b69c2374a535d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/732a991342a0f82653a935440e2f3b9be1eb6f6e", - "reference": "732a991342a0f82653a935440e2f3b9be1eb6f6e", + "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/ea345adad12f110edbbc4bef03b69c2374a535d4", + "reference": "ea345adad12f110edbbc4bef03b69c2374a535d4", "shasum": "" }, "require": { "ext-json": "*", - "laravel/framework": "^10.0|^11.0|^12.0", + "laravel/framework": "^10.0|^11.0|^12.0|^13.0", "php": "^8.1.0", - "symfony/console": "^6.2|^7.0" + "symfony/console": "^6.2|^7.0|^8.0" + }, + "conflict": { + "laravel/boost": "<2.2.0" }, "require-dev": { "guzzlehttp/guzzle": "^7.2", "larastan/larastan": "^3.0", "laravel/pint": "^1.16", "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^8.0|^9.2|^10.0", - "phpunit/phpunit": "^10.4|^11.5", + "orchestra/testbench": "^8.0|^9.2|^10.0|^11.0", + "phpunit/phpunit": "^10.4|^11.5|^12.0", "roave/security-advisories": "dev-master" }, "suggest": { @@ -1715,29 +1720,29 @@ ], "support": { "issues": "https://github.com/inertiajs/inertia-laravel/issues", - "source": "https://github.com/inertiajs/inertia-laravel/tree/v2.0.19" + "source": "https://github.com/inertiajs/inertia-laravel/tree/v2.0.24" }, - "time": "2026-01-13T15:29:20+00:00" + "time": "2026-04-10T14:36:44+00:00" }, { "name": "jaybizzle/crawler-detect", - "version": "v1.3.7", + "version": "v1.3.9", "source": { "type": "git", "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "7f7a45b5d5df9c95ba6b2008544e6cf8e66de6f5" + "reference": "5edf2e43d9f42e5baa6f844826213257c247b309" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/7f7a45b5d5df9c95ba6b2008544e6cf8e66de6f5", - "reference": "7f7a45b5d5df9c95ba6b2008544e6cf8e66de6f5", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/5edf2e43d9f42e5baa6f844826213257c247b309", + "reference": "5edf2e43d9f42e5baa6f844826213257c247b309", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.5|^6.5|^7.5|^8.5|^9.4" + "phpunit/phpunit": "^4.8|^5.5|^6.5|^7.5|^8.5.52|^9.4" }, "type": "library", "autoload": { @@ -1767,9 +1772,9 @@ ], "support": { "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", - "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.3.7" + "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.3.9" }, - "time": "2026-02-02T19:15:54+00:00" + "time": "2026-04-14T19:32:41+00:00" }, { "name": "jenssegers/agent", @@ -1856,48 +1861,49 @@ }, { "name": "laravel/cashier", - "version": "v16.2.0", + "version": "v16.5.1", "source": { "type": "git", "url": "https://github.com/laravel/cashier-stripe.git", - "reference": "9634b60c196ef1a512aa4f9543b6c2a1d64dff85" + "reference": "49a581bccb5e56a45e1c8ee94587ce3420203a7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/cashier-stripe/zipball/9634b60c196ef1a512aa4f9543b6c2a1d64dff85", - "reference": "9634b60c196ef1a512aa4f9543b6c2a1d64dff85", + "url": "https://api.github.com/repos/laravel/cashier-stripe/zipball/49a581bccb5e56a45e1c8ee94587ce3420203a7a", + "reference": "49a581bccb5e56a45e1c8ee94587ce3420203a7a", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/console": "^10.0|^11.0|^12.0", - "illuminate/contracts": "^10.0|^11.0|^12.0", - "illuminate/database": "^10.0|^11.0|^12.0", - "illuminate/http": "^10.0|^11.0|^12.0", - "illuminate/log": "^10.0|^11.0|^12.0", - "illuminate/notifications": "^10.0|^11.0|^12.0", - "illuminate/pagination": "^10.0|^11.0|^12.0", - "illuminate/routing": "^10.0|^11.0|^12.0", - "illuminate/support": "^10.0|^11.0|^12.0", - "illuminate/view": "^10.0|^11.0|^12.0", + "illuminate/console": "^10.0|^11.0|^12.0|^13.0", + "illuminate/contracts": "^10.0|^11.0|^12.0|^13.0", + "illuminate/database": "^10.0|^11.0|^12.0|^13.0", + "illuminate/http": "^10.0|^11.0|^12.0|^13.0", + "illuminate/log": "^10.0|^11.0|^12.0|^13.0", + "illuminate/notifications": "^10.0|^11.0|^12.0|^13.0", + "illuminate/pagination": "^10.0|^11.0|^12.0|^13.0", + "illuminate/routing": "^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^10.0|^11.0|^12.0|^13.0", + "illuminate/view": "^10.0|^11.0|^12.0|^13.0", "moneyphp/money": "^4.0", "nesbot/carbon": "^2.0|^3.0", "php": "^8.1", "stripe/stripe-php": "^17.3.0", - "symfony/console": "^6.0|^7.0", - "symfony/http-kernel": "^6.0|^7.0", + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/http-kernel": "^6.0|^7.0|^8.0", "symfony/polyfill-intl-icu": "^1.22.1", "symfony/polyfill-php84": "^1.32" }, "require-dev": { "dompdf/dompdf": "^2.0|^3.0", - "orchestra/testbench": "^8.36|^9.15|^10.8", + "orchestra/testbench": "^8.36|^9.15|^10.8|^11.0", "phpstan/phpstan": "^1.10", "spatie/laravel-ray": "^1.40" }, "suggest": { "dompdf/dompdf": "Required when generating and downloading invoice PDF's using Dompdf (^2.0|^3.0).", - "ext-intl": "Allows for more locales besides the default \"en\" when formatting money values." + "ext-intl": "Allows for more locales besides the default \"en\" when formatting money values.", + "spatie/laravel-pdf": "Required when generating and downloading invoice PDF's using Cashier's LaravelPdfInvoiceRenderer." }, "type": "library", "extra": { @@ -1940,20 +1946,20 @@ "issues": "https://github.com/laravel/cashier/issues", "source": "https://github.com/laravel/cashier" }, - "time": "2026-01-06T16:30:29+00:00" + "time": "2026-04-01T15:57:36+00:00" }, { "name": "laravel/fortify", - "version": "v1.34.1", + "version": "v1.36.2", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "412575e9c0cb21d49a30b7045ad4902019f538c2" + "reference": "b36e0782e6f5f6cfbab34327895a63b7c4c031f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/412575e9c0cb21d49a30b7045ad4902019f538c2", - "reference": "412575e9c0cb21d49a30b7045ad4902019f538c2", + "url": "https://api.github.com/repos/laravel/fortify/zipball/b36e0782e6f5f6cfbab34327895a63b7c4c031f9", + "reference": "b36e0782e6f5f6cfbab34327895a63b7c4c031f9", "shasum": "" }, "require": { @@ -2003,20 +2009,20 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2026-02-03T06:55:55+00:00" + "time": "2026-03-20T20:13:51+00:00" }, { "name": "laravel/framework", - "version": "v12.50.0", + "version": "v12.57.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "174ffed91d794a35a541a5eb7c3785a02a34aaba" + "reference": "63a6ced3db46582b3276e2d03770a6317a94d6e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/174ffed91d794a35a541a5eb7c3785a02a34aaba", - "reference": "174ffed91d794a35a541a5eb7c3785a02a34aaba", + "url": "https://api.github.com/repos/laravel/framework/zipball/63a6ced3db46582b3276e2d03770a6317a94d6e2", + "reference": "63a6ced3db46582b3276e2d03770a6317a94d6e2", "shasum": "" }, "require": { @@ -2037,7 +2043,7 @@ "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.3.0", "laravel/serializable-closure": "^1.3|^2.0", - "league/commonmark": "^2.7", + "league/commonmark": "^2.8.1", "league/flysystem": "^3.25.1", "league/flysystem-local": "^3.25.1", "league/uri": "^7.5.1", @@ -2057,8 +2063,8 @@ "symfony/mailer": "^7.2.0", "symfony/mime": "^7.2.0", "symfony/polyfill-php83": "^1.33", - "symfony/polyfill-php84": "^1.33", - "symfony/polyfill-php85": "^1.33", + "symfony/polyfill-php84": "^1.34", + "symfony/polyfill-php85": "^1.34", "symfony/process": "^7.2.0", "symfony/routing": "^7.2.0", "symfony/uid": "^7.2.0", @@ -2132,7 +2138,7 @@ "orchestra/testbench-core": "^10.9.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", - "phpstan/phpstan": "^2.0", + "phpstan/phpstan": "^2.1.41", "phpunit/phpunit": "^10.5.35|^11.5.3|^12.0.1", "predis/predis": "^2.3|^3.0", "resend/resend-php": "^0.10.0|^1.0", @@ -2225,40 +2231,41 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2026-02-04T18:34:13+00:00" + "time": "2026-04-22T13:21:29+00:00" }, { "name": "laravel/horizon", - "version": "v5.43.0", + "version": "v5.46.0", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "2a04285ba83915511afbe987cbfedafdc27fd2de" + "reference": "bfea968e8aa674fb649d02e55ea0d38bdf5137d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/2a04285ba83915511afbe987cbfedafdc27fd2de", - "reference": "2a04285ba83915511afbe987cbfedafdc27fd2de", + "url": "https://api.github.com/repos/laravel/horizon/zipball/bfea968e8aa674fb649d02e55ea0d38bdf5137d5", + "reference": "bfea968e8aa674fb649d02e55ea0d38bdf5137d5", "shasum": "" }, "require": { "ext-json": "*", "ext-pcntl": "*", "ext-posix": "*", - "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0", - "illuminate/queue": "^9.21|^10.0|^11.0|^12.0", - "illuminate/support": "^9.21|^10.0|^11.0|^12.0", + "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/queue": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0|^13.0", + "laravel/sentinel": "^1.0", "nesbot/carbon": "^2.17|^3.0", "php": "^8.0", "ramsey/uuid": "^4.0", - "symfony/console": "^6.0|^7.0", - "symfony/error-handler": "^6.0|^7.0", + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/error-handler": "^6.0|^7.0|^8.0", "symfony/polyfill-php83": "^1.28", - "symfony/process": "^6.0|^7.0" + "symfony/process": "^6.0|^7.0|^8.0" }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.55|^8.36|^9.15|^10.8", + "orchestra/testbench": "^7.56|^8.37|^9.16|^10.9|^11.0", "phpstan/phpstan": "^1.10|^2.0", "predis/predis": "^1.1|^2.0|^3.0" }, @@ -2302,47 +2309,47 @@ ], "support": { "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.43.0" + "source": "https://github.com/laravel/horizon/tree/v5.46.0" }, - "time": "2026-01-15T15:10:56+00:00" + "time": "2026-04-20T18:08:11+00:00" }, { "name": "laravel/passport", - "version": "v13.4.3", + "version": "v13.7.5", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "b3c549d519dbf50be4eae563a267dd1553736041" + "reference": "90053dc4ba681c076855779250109bb624f961f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/b3c549d519dbf50be4eae563a267dd1553736041", - "reference": "b3c549d519dbf50be4eae563a267dd1553736041", + "url": "https://api.github.com/repos/laravel/passport/zipball/90053dc4ba681c076855779250109bb624f961f6", + "reference": "90053dc4ba681c076855779250109bb624f961f6", "shasum": "" }, "require": { "ext-json": "*", "ext-openssl": "*", "firebase/php-jwt": "^6.4|^7.0", - "illuminate/auth": "^11.35|^12.0", - "illuminate/console": "^11.35|^12.0", - "illuminate/container": "^11.35|^12.0", - "illuminate/contracts": "^11.35|^12.0", - "illuminate/cookie": "^11.35|^12.0", - "illuminate/database": "^11.35|^12.0", - "illuminate/encryption": "^11.35|^12.0", - "illuminate/http": "^11.35|^12.0", - "illuminate/support": "^11.35|^12.0", + "illuminate/auth": "^11.35|^12.0|^13.0", + "illuminate/console": "^11.35|^12.0|^13.0", + "illuminate/container": "^11.35|^12.0|^13.0", + "illuminate/contracts": "^11.35|^12.0|^13.0", + "illuminate/cookie": "^11.35|^12.0|^13.0", + "illuminate/database": "^11.35|^12.0|^13.0", + "illuminate/encryption": "^11.35|^12.0|^13.0", + "illuminate/http": "^11.35|^12.0|^13.0", + "illuminate/support": "^11.35|^12.0|^13.0", "league/oauth2-server": "^9.2", "php": "^8.2", "php-http/discovery": "^1.20", "phpseclib/phpseclib": "^3.0", "psr/http-factory-implementation": "*", - "symfony/console": "^7.1", - "symfony/psr-http-message-bridge": "^7.1" + "symfony/console": "^7.1|^8.0", + "symfony/psr-http-message-bridge": "^7.1|^8.0" }, "require-dev": { - "orchestra/testbench": "^9.15|^10.8", + "orchestra/testbench": "^9.15|^10.8|^11.0", "phpstan/phpstan": "^2.0" }, "type": "library", @@ -2379,20 +2386,20 @@ "issues": "https://github.com/laravel/passport/issues", "source": "https://github.com/laravel/passport" }, - "time": "2025-12-22T14:58:04+00:00" + "time": "2026-04-16T14:00:29+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.12", + "version": "v0.3.17", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "4861ded9003b7f8a158176a0b7666f74ee761be8" + "reference": "6a82ac19a28b916ae0885828795dbd4c59d9a818" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/4861ded9003b7f8a158176a0b7666f74ee761be8", - "reference": "4861ded9003b7f8a158176a0b7666f74ee761be8", + "url": "https://api.github.com/repos/laravel/prompts/zipball/6a82ac19a28b916ae0885828795dbd4c59d9a818", + "reference": "6a82ac19a28b916ae0885828795dbd4c59d9a818", "shasum": "" }, "require": { @@ -2436,22 +2443,78 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.12" + "source": "https://github.com/laravel/prompts/tree/v0.3.17" }, - "time": "2026-02-03T06:57:26+00:00" + "time": "2026-04-20T16:07:33+00:00" }, { - "name": "laravel/serializable-closure", - "version": "v2.0.9", + "name": "laravel/sentinel", + "version": "v1.1.0", "source": { "type": "git", - "url": "https://github.com/laravel/serializable-closure.git", - "reference": "8f631589ab07b7b52fead814965f5a800459cb3e" + "url": "https://github.com/laravel/sentinel.git", + "reference": "972d9885d9d14312a118e9565c4e6ecc5e751ea1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/8f631589ab07b7b52fead814965f5a800459cb3e", - "reference": "8f631589ab07b7b52fead814965f5a800459cb3e", + "url": "https://api.github.com/repos/laravel/sentinel/zipball/972d9885d9d14312a118e9565c4e6ecc5e751ea1", + "reference": "972d9885d9d14312a118e9565c4e6ecc5e751ea1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/container": "^8.37|^9.0|^10.0|^11.0|^12.0|^13.0", + "php": "^8.0" + }, + "require-dev": { + "laravel/pint": "^1.27", + "orchestra/testbench": "^6.47.1|^7.56|^8.37|^9.16|^10.9|^11.0", + "phpstan/phpstan": "^2.1.33" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sentinel\\SentinelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sentinel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "mior@laravel.com" + } + ], + "support": { + "source": "https://github.com/laravel/sentinel/tree/v1.1.0" + }, + "time": "2026-03-24T14:03:38+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.12", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "a6abb4e54f6fcd3138120b9ad497f0bd146f9919" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/a6abb4e54f6fcd3138120b9ad497f0bd146f9919", + "reference": "a6abb4e54f6fcd3138120b9ad497f0bd146f9919", "shasum": "" }, "require": { @@ -2499,20 +2562,20 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2026-02-03T06:55:34+00:00" + "time": "2026-04-14T13:33:34+00:00" }, { "name": "laravel/tinker", - "version": "v2.11.0", + "version": "v2.11.1", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "3d34b97c9a1747a81a3fde90482c092bd8b66468" + "reference": "c9f80cc835649b5c1842898fb043f8cc098dd741" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/3d34b97c9a1747a81a3fde90482c092bd8b66468", - "reference": "3d34b97c9a1747a81a3fde90482c092bd8b66468", + "url": "https://api.github.com/repos/laravel/tinker/zipball/c9f80cc835649b5c1842898fb043f8cc098dd741", + "reference": "c9f80cc835649b5c1842898fb043f8cc098dd741", "shasum": "" }, "require": { @@ -2563,9 +2626,9 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.11.0" + "source": "https://github.com/laravel/tinker/tree/v2.11.1" }, - "time": "2025-12-19T19:16:45+00:00" + "time": "2026-02-06T14:12:35+00:00" }, { "name": "lcobucci/clock", @@ -2706,16 +2769,16 @@ }, { "name": "league/commonmark", - "version": "2.8.0", + "version": "2.8.2", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" + "reference": "59fb075d2101740c337c7216e3f32b36c204218b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", - "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/59fb075d2101740c337c7216e3f32b36c204218b", + "reference": "59fb075d2101740c337c7216e3f32b36c204218b", "shasum": "" }, "require": { @@ -2740,9 +2803,9 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 | ^7.0", - "symfony/process": "^5.4 | ^6.0 | ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" }, @@ -2809,7 +2872,7 @@ "type": "tidelift" } ], - "time": "2025-11-26T21:48:24+00:00" + "time": "2026-03-19T13:16:38+00:00" }, { "name": "league/config", @@ -2954,16 +3017,16 @@ }, { "name": "league/flysystem", - "version": "3.31.0", + "version": "3.33.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "1717e0b3642b0df65ecb0cc89cdd99fa840672ff" + "reference": "570b8871e0ce693764434b29154c54b434905350" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/1717e0b3642b0df65ecb0cc89cdd99fa840672ff", - "reference": "1717e0b3642b0df65ecb0cc89cdd99fa840672ff", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/570b8871e0ce693764434b29154c54b434905350", + "reference": "570b8871e0ce693764434b29154c54b434905350", "shasum": "" }, "require": { @@ -3031,9 +3094,9 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.31.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.33.0" }, - "time": "2026-01-23T15:38:47+00:00" + "time": "2026-03-25T07:59:30+00:00" }, { "name": "league/flysystem-local", @@ -3238,20 +3301,20 @@ }, { "name": "league/uri", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76" + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", - "reference": "4436c6ec8d458e4244448b069cc572d088230b76", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4", + "reference": "08cf38e3924d4f56238125547b5720496fac8fd4", "shasum": "" }, "require": { - "league/uri-interfaces": "^7.8", + "league/uri-interfaces": "^7.8.1", "php": "^8.1", "psr/http-factory": "^1" }, @@ -3324,7 +3387,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri/tree/7.8.0" + "source": "https://github.com/thephpleague/uri/tree/7.8.1" }, "funding": [ { @@ -3332,20 +3395,20 @@ "type": "github" } ], - "time": "2026-01-14T17:24:56+00:00" + "time": "2026-03-15T20:22:25+00:00" }, { "name": "league/uri-interfaces", - "version": "7.8.0", + "version": "7.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", - "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928", + "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928", "shasum": "" }, "require": { @@ -3408,7 +3471,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri-src/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0" + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1" }, "funding": [ { @@ -3416,7 +3479,7 @@ "type": "github" } ], - "time": "2026-01-15T06:54:53+00:00" + "time": "2026-03-08T20:05:35+00:00" }, { "name": "masterminds/html5", @@ -3602,16 +3665,16 @@ }, { "name": "mobiledetect/mobiledetectlib", - "version": "2.8.45", + "version": "2.8.47", "source": { "type": "git", "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266" + "reference": "28e9045958dcaf771f9b56564549d5b174e38b0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/96aaebcf4f50d3d2692ab81d2c5132e425bca266", - "reference": "96aaebcf4f50d3d2692ab81d2c5132e425bca266", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/28e9045958dcaf771f9b56564549d5b174e38b0e", + "reference": "28e9045958dcaf771f9b56564549d5b174e38b0e", "shasum": "" }, "require": { @@ -3652,7 +3715,7 @@ ], "support": { "issues": "https://github.com/serbanghita/Mobile-Detect/issues", - "source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.45" + "source": "https://github.com/serbanghita/Mobile-Detect/tree/2.8.47" }, "funding": [ { @@ -3660,7 +3723,7 @@ "type": "github" } ], - "time": "2023-11-07T21:57:25+00:00" + "time": "2026-04-14T12:32:34+00:00" }, { "name": "moneyphp/money", @@ -3857,16 +3920,16 @@ }, { "name": "nesbot/carbon", - "version": "3.11.1", + "version": "3.11.4", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "f438fcc98f92babee98381d399c65336f3a3827f" + "reference": "e890471a3494740f7d9326d72ce6a8c559ffee60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/f438fcc98f92babee98381d399c65336f3a3827f", - "reference": "f438fcc98f92babee98381d399c65336f3a3827f", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/e890471a3494740f7d9326d72ce6a8c559ffee60", + "reference": "e890471a3494740f7d9326d72ce6a8c559ffee60", "shasum": "" }, "require": { @@ -3958,20 +4021,20 @@ "type": "tidelift" } ], - "time": "2026-01-29T09:26:29+00:00" + "time": "2026-04-07T09:57:54+00:00" }, { "name": "nette/schema", - "version": "v1.3.4", + "version": "v1.3.5", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "086497a2f34b82fede9b5a41cc8e131d087cd8f7" + "reference": "f0ab1a3cda782dbc5da270d28545236aa80c4002" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/086497a2f34b82fede9b5a41cc8e131d087cd8f7", - "reference": "086497a2f34b82fede9b5a41cc8e131d087cd8f7", + "url": "https://api.github.com/repos/nette/schema/zipball/f0ab1a3cda782dbc5da270d28545236aa80c4002", + "reference": "f0ab1a3cda782dbc5da270d28545236aa80c4002", "shasum": "" }, "require": { @@ -3979,8 +4042,10 @@ "php": "8.1 - 8.5" }, "require-dev": { + "nette/phpstan-rules": "^1.0", "nette/tester": "^2.6", - "phpstan/phpstan": "^2.0@stable", + "phpstan/extension-installer": "^1.4@stable", + "phpstan/phpstan": "^2.1.39@stable", "tracy/tracy": "^2.8" }, "type": "library", @@ -4021,22 +4086,22 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.4" + "source": "https://github.com/nette/schema/tree/v1.3.5" }, - "time": "2026-02-08T02:54:00+00:00" + "time": "2026-02-23T03:47:12+00:00" }, { "name": "nette/utils", - "version": "v4.1.2", + "version": "v4.1.3", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "f76b5dc3d6c6d3043c8d937df2698515b99cbaf5" + "reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/f76b5dc3d6c6d3043c8d937df2698515b99cbaf5", - "reference": "f76b5dc3d6c6d3043c8d937df2698515b99cbaf5", + "url": "https://api.github.com/repos/nette/utils/zipball/bb3ea637e3d131d72acc033cfc2746ee893349fe", + "reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe", "shasum": "" }, "require": { @@ -4048,8 +4113,10 @@ }, "require-dev": { "jetbrains/phpstorm-attributes": "^1.2", + "nette/phpstan-rules": "^1.0", "nette/tester": "^2.5", - "phpstan/phpstan": "^2.0@stable", + "phpstan/extension-installer": "^1.4@stable", + "phpstan/phpstan": "^2.1@stable", "tracy/tracy": "^2.9" }, "suggest": { @@ -4110,9 +4177,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.2" + "source": "https://github.com/nette/utils/tree/v4.1.3" }, - "time": "2026-02-03T17:21:09+00:00" + "time": "2026-02-13T03:05:33+00:00" }, { "name": "nikic/php-parser", @@ -4174,31 +4241,31 @@ }, { "name": "nunomaduro/termwind", - "version": "v2.3.3", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017" + "reference": "712a31b768f5daea284c2169a7d227031001b9a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/6fb2a640ff502caace8e05fd7be3b503a7e1c017", - "reference": "6fb2a640ff502caace8e05fd7be3b503a7e1c017", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/712a31b768f5daea284c2169a7d227031001b9a8", + "reference": "712a31b768f5daea284c2169a7d227031001b9a8", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.3.6" + "symfony/console": "^7.4.4 || ^8.0.4" }, "require-dev": { - "illuminate/console": "^11.46.1", - "laravel/pint": "^1.25.1", + "illuminate/console": "^11.47.0", + "laravel/pint": "^1.27.1", "mockery/mockery": "^1.6.12", - "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.1.3", + "pestphp/pest": "^2.36.0 || ^3.8.4 || ^4.3.2", "phpstan/phpstan": "^1.12.32", "phpstan/phpstan-strict-rules": "^1.6.2", - "symfony/var-dumper": "^7.3.5", + "symfony/var-dumper": "^7.3.5 || ^8.0.4", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -4230,7 +4297,7 @@ "email": "enunomaduro@gmail.com" } ], - "description": "Its like Tailwind CSS, but for the console.", + "description": "It's like Tailwind CSS, but for the console.", "keywords": [ "cli", "console", @@ -4241,7 +4308,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.3.3" + "source": "https://github.com/nunomaduro/termwind/tree/v2.4.0" }, "funding": [ { @@ -4257,7 +4324,7 @@ "type": "github" } ], - "time": "2025-11-20T02:34:59+00:00" + "time": "2026-02-16T23:10:27+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -4534,16 +4601,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.49", + "version": "3.0.51", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9" + "reference": "d59c94077f9c9915abb51ddb52ce85188ece1748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/6233a1e12584754e6b5daa69fe1289b47775c1b9", - "reference": "6233a1e12584754e6b5daa69fe1289b47775c1b9", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d59c94077f9c9915abb51ddb52ce85188ece1748", + "reference": "d59c94077f9c9915abb51ddb52ce85188ece1748", "shasum": "" }, "require": { @@ -4624,7 +4691,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.49" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.51" }, "funding": [ { @@ -4640,7 +4707,7 @@ "type": "tidelift" } ], - "time": "2026-01-27T09:17:28+00:00" + "time": "2026-04-10T01:33:53+00:00" }, { "name": "pragmarx/google2fa", @@ -5221,16 +5288,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.19", + "version": "v0.12.22", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "a4f766e5c5b6773d8399711019bb7d90875a50ee" + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/a4f766e5c5b6773d8399711019bb7d90875a50ee", - "reference": "a4f766e5c5b6773d8399711019bb7d90875a50ee", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3be75d5b9244936dd4ac62ade2bfb004d13acf0f", + "reference": "3be75d5b9244936dd4ac62ade2bfb004d13acf0f", "shasum": "" }, "require": { @@ -5294,9 +5361,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.19" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.22" }, - "time": "2026-01-30T17:33:13+00:00" + "time": "2026-03-22T23:03:24+00:00" }, { "name": "ralouphie/getallheaders", @@ -5498,33 +5565,35 @@ }, { "name": "sabberworm/php-css-parser", - "version": "v9.1.0", + "version": "v9.3.0", "source": { "type": "git", "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", - "reference": "1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb" + "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb", - "reference": "1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", + "reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949", "shasum": "" }, "require": { "ext-iconv": "*", "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "thecodingmachine/safe": "^1.3 || ^2.5 || ^3.3" + "thecodingmachine/safe": "^1.3 || ^2.5 || ^3.4" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "1.4.0", "phpstan/extension-installer": "1.4.3", - "phpstan/phpstan": "1.12.28 || 2.1.25", - "phpstan/phpstan-phpunit": "1.4.2 || 2.0.7", - "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.6", - "phpunit/phpunit": "8.5.46", + "phpstan/phpstan": "1.12.32 || 2.1.32", + "phpstan/phpstan-phpunit": "1.4.2 || 2.0.8", + "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.7", + "phpunit/phpunit": "8.5.52", "rawr/phpunit-data-provider": "3.3.1", - "rector/rector": "1.2.10 || 2.1.7", - "rector/type-perfect": "1.0.0 || 2.1.0" + "rector/rector": "1.2.10 || 2.2.8", + "rector/type-perfect": "1.0.0 || 2.1.0", + "squizlabs/php_codesniffer": "4.0.1", + "thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.1" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" @@ -5532,10 +5601,14 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-main": "9.4.x-dev" } }, "autoload": { + "files": [ + "src/Rule/Rule.php", + "src/RuleSet/RuleContainer.php" + ], "psr-4": { "Sabberworm\\CSS\\": "src/" } @@ -5566,36 +5639,37 @@ ], "support": { "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", - "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.1.0" + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.3.0" }, - "time": "2025-09-14T07:37:21+00:00" + "time": "2026-03-03T17:31:43+00:00" }, { "name": "spatie/laravel-permission", - "version": "6.24.0", + "version": "6.25.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-permission.git", - "reference": "76adb1fc8d07c16a0721c35c4cc330b7a12598d7" + "reference": "d7d4cb0d58616722f1afc90e0484e4825155b9b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/76adb1fc8d07c16a0721c35c4cc330b7a12598d7", - "reference": "76adb1fc8d07c16a0721c35c4cc330b7a12598d7", + "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/d7d4cb0d58616722f1afc90e0484e4825155b9b3", + "reference": "d7d4cb0d58616722f1afc90e0484e4825155b9b3", "shasum": "" }, "require": { - "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0", - "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0", - "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0", - "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0|^13.0", "php": "^8.0" }, "require-dev": { - "laravel/passport": "^11.0|^12.0", + "laravel/passport": "^11.0|^12.0|^13.0", "laravel/pint": "^1.0", - "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", - "phpunit/phpunit": "^9.4|^10.1|^11.5" + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0|^11.0", + "pestphp/pest": "^2.0|^3.0|^4.0", + "pestphp/pest-plugin-laravel": "^2.0|^3.0|^4.0" }, "type": "library", "extra": { @@ -5643,7 +5717,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-permission/issues", - "source": "https://github.com/spatie/laravel-permission/tree/6.24.0" + "source": "https://github.com/spatie/laravel-permission/tree/6.25.0" }, "funding": [ { @@ -5651,33 +5725,38 @@ "type": "github" } ], - "time": "2025-12-13T21:45:21+00:00" + "time": "2026-03-17T22:46:46+00:00" }, { "name": "srmklive/paypal", - "version": "3.0.40", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/srmklive/laravel-paypal.git", - "reference": "1ddc49fd836a4785933ab953452152f3fedbac63" + "url": "https://github.com/blendbyte/laravel-paypal.git", + "reference": "522834a22fbd10e8fa1be21cb7c84d3d45c3a763" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/srmklive/laravel-paypal/zipball/1ddc49fd836a4785933ab953452152f3fedbac63", - "reference": "1ddc49fd836a4785933ab953452152f3fedbac63", + "url": "https://api.github.com/repos/blendbyte/laravel-paypal/zipball/522834a22fbd10e8fa1be21cb7c84d3d45c3a763", + "reference": "522834a22fbd10e8fa1be21cb7c84d3d45c3a763", "shasum": "" }, "require": { - "ext-curl": "*", - "guzzlehttp/guzzle": "~7.0", - "illuminate/support": "~6.0|~7.0|~8.0|~9.0|^10.0|^11.0|^12.0", - "nesbot/carbon": "~2.0|^3.0", - "php": ">=7.2|^8.0" + "guzzlehttp/guzzle": "^7.9", + "guzzlehttp/psr7": "^2.0", + "illuminate/support": "^12.0|^13.0", + "nesbot/carbon": "^3.0", + "php": "^8.2", + "psr/http-client": "^1.0" }, "require-dev": { - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^8.0|^9.0|^10.0|^11.0", - "symfony/var-dumper": "~5.0|^6.0|^7.0" + "larastan/larastan": "^3.0", + "laravel/framework": "^12.0|^13.0", + "laravel/pint": "^1.29", + "orchestra/testbench": "^10.0|^11.0", + "pestphp/pest": "^3.0|^4.0", + "phpunit/phpunit": "^11.0|^12.0", + "symfony/var-dumper": "^7.0" }, "type": "library", "extra": { @@ -5699,38 +5778,31 @@ "license": [ "MIT" ], - "authors": [ - { - "name": "Raza Mehdi", - "email": "srmk@outlook.com" - } - ], - "description": "Laravel plugin For Processing Payments Through Paypal Express Checkout. Can Be Used Independently With Other Applications.", + "description": "PayPal REST API client for Laravel and standalone PHP.", "keywords": [ - "http", - "laravel paypal", - "paypal", - "rest", - "web service" + "REST API", + "laravel", + "payments", + "paypal" ], "support": { - "issues": "https://github.com/srmklive/laravel-paypal/issues", - "source": "https://github.com/srmklive/laravel-paypal/tree/3.0.40" + "issues": "https://github.com/blendbyte/laravel-paypal/issues", + "source": "https://github.com/blendbyte/laravel-paypal/tree/3.1.1" }, - "time": "2025-02-25T21:38:18+00:00" + "time": "2026-04-18T05:16:56+00:00" }, { "name": "stevebauman/location", - "version": "v7.6.2", + "version": "v7.6.3", "source": { "type": "git", "url": "https://github.com/stevebauman/location.git", - "reference": "2f7686b685b924f193d6a6b82074861b8cc5aa3a" + "reference": "ed76d047c40dc13646438e486a8981102476adbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stevebauman/location/zipball/2f7686b685b924f193d6a6b82074861b8cc5aa3a", - "reference": "2f7686b685b924f193d6a6b82074861b8cc5aa3a", + "url": "https://api.github.com/repos/stevebauman/location/zipball/ed76d047c40dc13646438e486a8981102476adbe", + "reference": "ed76d047c40dc13646438e486a8981102476adbe", "shasum": "" }, "require": { @@ -5738,12 +5810,12 @@ "ext-json": "*", "geoip2/geoip2": "^2.0|^3.0", "guzzlehttp/guzzle": "^7.0", - "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", "php": ">=8.1" }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0", + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "pestphp/pest": "^1.0|^2.0|^3.7" }, "type": "library", @@ -5784,9 +5856,9 @@ ], "support": { "issues": "https://github.com/stevebauman/location/issues", - "source": "https://github.com/stevebauman/location/tree/v7.6.2" + "source": "https://github.com/stevebauman/location/tree/v7.6.3" }, - "time": "2026-02-11T16:06:17+00:00" + "time": "2026-03-18T16:51:48+00:00" }, { "name": "stripe/stripe-php", @@ -5849,16 +5921,16 @@ }, { "name": "symfony/clock", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110" + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/9169f24776edde469914c1e7a1442a50f7a4e110", - "reference": "9169f24776edde469914c1e7a1442a50f7a4e110", + "url": "https://api.github.com/repos/symfony/clock/zipball/674fa3b98e21531dd040e613479f5f6fa8f32111", + "reference": "674fa3b98e21531dd040e613479f5f6fa8f32111", "shasum": "" }, "require": { @@ -5903,7 +5975,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.4.0" + "source": "https://github.com/symfony/clock/tree/v7.4.8" }, "funding": [ { @@ -5923,20 +5995,20 @@ "type": "tidelift" } ], - "time": "2025-11-12T15:39:26+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/console", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894" + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/41e38717ac1dd7a46b6bda7d6a82af2d98a78894", - "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894", + "url": "https://api.github.com/repos/symfony/console/zipball/1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", + "reference": "1e92e39c51f95b88e3d66fa2d9f06d1fb45dd707", "shasum": "" }, "require": { @@ -6001,7 +6073,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.4" + "source": "https://github.com/symfony/console/tree/v7.4.8" }, "funding": [ { @@ -6021,20 +6093,20 @@ "type": "tidelift" } ], - "time": "2026-01-13T11:36:38+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/css-selector", - "version": "v7.4.0", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135" + "reference": "b055f228a4178a1d6774909903905e3475f3eac8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab862f478513e7ca2fe9ec117a6f01a8da6e1135", - "reference": "ab862f478513e7ca2fe9ec117a6f01a8da6e1135", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/b055f228a4178a1d6774909903905e3475f3eac8", + "reference": "b055f228a4178a1d6774909903905e3475f3eac8", "shasum": "" }, "require": { @@ -6070,7 +6142,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.4.0" + "source": "https://github.com/symfony/css-selector/tree/v7.4.8" }, "funding": [ { @@ -6090,7 +6162,7 @@ "type": "tidelift" } ], - "time": "2025-10-30T13:39:42+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6161,16 +6233,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8" + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8da531f364ddfee53e36092a7eebbbd0b775f6b8", - "reference": "8da531f364ddfee53e36092a7eebbbd0b775f6b8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", "shasum": "" }, "require": { @@ -6219,7 +6291,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.4.4" + "source": "https://github.com/symfony/error-handler/tree/v7.4.8" }, "funding": [ { @@ -6239,20 +6311,20 @@ "type": "tidelift" } ], - "time": "2026-01-20T16:42:42+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746" + "reference": "f57b899fa736fd71121168ef268f23c206083f0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/dc2c0eba1af673e736bb851d747d266108aea746", - "reference": "dc2c0eba1af673e736bb851d747d266108aea746", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f57b899fa736fd71121168ef268f23c206083f0a", + "reference": "f57b899fa736fd71121168ef268f23c206083f0a", "shasum": "" }, "require": { @@ -6304,7 +6376,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.4" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.8" }, "funding": [ { @@ -6324,7 +6396,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T11:45:34+00:00" + "time": "2026-03-30T13:54:39+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6404,16 +6476,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ad4daa7c38668dcb031e63bc99ea9bd42196a2cb" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ad4daa7c38668dcb031e63bc99ea9bd42196a2cb", - "reference": "ad4daa7c38668dcb031e63bc99ea9bd42196a2cb", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { @@ -6448,7 +6520,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.5" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -6468,20 +6540,20 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "446d0db2b1f21575f1284b74533e425096abdfb6" + "reference": "9381209597ec66c25be154cbf2289076e64d1eab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/446d0db2b1f21575f1284b74533e425096abdfb6", - "reference": "446d0db2b1f21575f1284b74533e425096abdfb6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab", + "reference": "9381209597ec66c25be154cbf2289076e64d1eab", "shasum": "" }, "require": { @@ -6530,7 +6602,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.8" }, "funding": [ { @@ -6550,20 +6622,20 @@ "type": "tidelift" } ], - "time": "2026-01-27T16:16:02+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "229eda477017f92bd2ce7615d06222ec0c19e82a" + "reference": "017e76ad089bac281553389269e259e155935e1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/229eda477017f92bd2ce7615d06222ec0c19e82a", - "reference": "229eda477017f92bd2ce7615d06222ec0c19e82a", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/017e76ad089bac281553389269e259e155935e1a", + "reference": "017e76ad089bac281553389269e259e155935e1a", "shasum": "" }, "require": { @@ -6605,7 +6677,7 @@ "symfony/config": "^6.4|^7.0|^8.0", "symfony/console": "^6.4|^7.0|^8.0", "symfony/css-selector": "^6.4|^7.0|^8.0", - "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4.1|^7.0.1|^8.0", "symfony/dom-crawler": "^6.4|^7.0|^8.0", "symfony/expression-language": "^6.4|^7.0|^8.0", "symfony/finder": "^6.4|^7.0|^8.0", @@ -6649,7 +6721,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.4.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.8" }, "funding": [ { @@ -6669,20 +6741,20 @@ "type": "tidelift" } ], - "time": "2026-01-28T10:33:42+00:00" + "time": "2026-03-31T20:57:01+00:00" }, { "name": "symfony/mailer", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "7b750074c40c694ceb34cb926d6dffee231c5cd6" + "reference": "f6ea532250b476bfc1b56699b388a1bdbf168f62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/7b750074c40c694ceb34cb926d6dffee231c5cd6", - "reference": "7b750074c40c694ceb34cb926d6dffee231c5cd6", + "url": "https://api.github.com/repos/symfony/mailer/zipball/f6ea532250b476bfc1b56699b388a1bdbf168f62", + "reference": "f6ea532250b476bfc1b56699b388a1bdbf168f62", "shasum": "" }, "require": { @@ -6733,7 +6805,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.4.4" + "source": "https://github.com/symfony/mailer/tree/v7.4.8" }, "funding": [ { @@ -6753,20 +6825,20 @@ "type": "tidelift" } ], - "time": "2026-01-08T08:25:11+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/mime", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "b18c7e6e9eee1e19958138df10412f3c4c316148" + "reference": "6df02f99998081032da3407a8d6c4e1dcb5d4379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/b18c7e6e9eee1e19958138df10412f3c4c316148", - "reference": "b18c7e6e9eee1e19958138df10412f3c4c316148", + "url": "https://api.github.com/repos/symfony/mime/zipball/6df02f99998081032da3407a8d6c4e1dcb5d4379", + "reference": "6df02f99998081032da3407a8d6c4e1dcb5d4379", "shasum": "" }, "require": { @@ -6777,7 +6849,7 @@ }, "conflict": { "egulias/email-validator": "~3.0.0", - "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/reflection-docblock": "<5.2|>=7", "phpdocumentor/type-resolver": "<1.5.1", "symfony/mailer": "<6.4", "symfony/serializer": "<6.4.3|>7.0,<7.0.3" @@ -6785,7 +6857,7 @@ "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", - "phpdocumentor/reflection-docblock": "^5.2", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", "symfony/dependency-injection": "^6.4|^7.0|^8.0", "symfony/process": "^6.4|^7.0|^8.0", "symfony/property-access": "^6.4|^7.0|^8.0", @@ -6822,7 +6894,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.4.5" + "source": "https://github.com/symfony/mime/tree/v7.4.8" }, "funding": [ { @@ -6842,20 +6914,20 @@ "type": "tidelift" } ], - "time": "2026-01-27T08:59:58+00:00" + "time": "2026-03-30T14:11:46+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -6905,7 +6977,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.36.0" }, "funding": [ { @@ -6925,20 +6997,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/ad1b7b9092976d6c948b8a187cec9faaea9ec1df", + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df", "shasum": "" }, "require": { @@ -6987,7 +7059,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.36.0" }, "funding": [ { @@ -7007,20 +7079,20 @@ "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c" + "reference": "3510b63d07376b04e57e27e82607d468bb134f78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", - "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/3510b63d07376b04e57e27e82607d468bb134f78", + "reference": "3510b63d07376b04e57e27e82607d468bb134f78", "shasum": "" }, "require": { @@ -7075,7 +7147,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.36.0" }, "funding": [ { @@ -7095,11 +7167,11 @@ "type": "tidelift" } ], - "time": "2025-06-20T22:24:30+00:00" + "time": "2026-04-10T16:50:15+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -7162,7 +7234,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0" }, "funding": [ { @@ -7186,7 +7258,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -7247,7 +7319,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0" }, "funding": [ { @@ -7271,16 +7343,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { @@ -7332,7 +7404,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0" }, "funding": [ { @@ -7352,20 +7424,20 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", "shasum": "" }, "require": { @@ -7416,7 +7488,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.36.0" }, "funding": [ { @@ -7436,20 +7508,20 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149", + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149", "shasum": "" }, "require": { @@ -7496,7 +7568,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0" }, "funding": [ { @@ -7516,20 +7588,20 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php84", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06", + "reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06", "shasum": "" }, "require": { @@ -7576,7 +7648,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.36.0" }, "funding": [ { @@ -7596,20 +7668,20 @@ "type": "tidelift" } ], - "time": "2025-06-24T13:30:11+00:00" + "time": "2026-04-10T18:47:49+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" + "reference": "2c408a6bb0313e6001a83628dc5506100474254e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", - "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/2c408a6bb0313e6001a83628dc5506100474254e", + "reference": "2c408a6bb0313e6001a83628dc5506100474254e", "shasum": "" }, "require": { @@ -7656,7 +7728,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.36.0" }, "funding": [ { @@ -7676,20 +7748,20 @@ "type": "tidelift" } ], - "time": "2025-06-23T16:12:55+00:00" + "time": "2026-04-10T16:50:15+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", "shasum": "" }, "require": { @@ -7739,7 +7811,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.36.0" }, "funding": [ { @@ -7759,20 +7831,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/process", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "608476f4604102976d687c483ac63a79ba18cc97" + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/608476f4604102976d687c483ac63a79ba18cc97", - "reference": "608476f4604102976d687c483ac63a79ba18cc97", + "url": "https://api.github.com/repos/symfony/process/zipball/60f19cd3badc8de688421e21e4305eba50f8089a", + "reference": "60f19cd3badc8de688421e21e4305eba50f8089a", "shasum": "" }, "require": { @@ -7804,7 +7876,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.5" + "source": "https://github.com/symfony/process/tree/v7.4.8" }, "funding": [ { @@ -7824,20 +7896,20 @@ "type": "tidelift" } ], - "time": "2026-01-26T15:07:59+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "929ffe10bbfbb92e711ac3818d416f9daffee067" + "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/929ffe10bbfbb92e711ac3818d416f9daffee067", - "reference": "929ffe10bbfbb92e711ac3818d416f9daffee067", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/76f1a57719a4a04c0ea18678a6c9305b5dcb9da8", + "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8", "shasum": "" }, "require": { @@ -7892,7 +7964,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.4" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.8" }, "funding": [ { @@ -7912,20 +7984,20 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:30:35+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/routing", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147" + "reference": "9608de9873ec86e754fb6c0a0fa7e5f1a960eb6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0798827fe2c79caeed41d70b680c2c3507d10147", - "reference": "0798827fe2c79caeed41d70b680c2c3507d10147", + "url": "https://api.github.com/repos/symfony/routing/zipball/9608de9873ec86e754fb6c0a0fa7e5f1a960eb6b", + "reference": "9608de9873ec86e754fb6c0a0fa7e5f1a960eb6b", "shasum": "" }, "require": { @@ -7977,7 +8049,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.4.4" + "source": "https://github.com/symfony/routing/tree/v7.4.8" }, "funding": [ { @@ -7997,7 +8069,7 @@ "type": "tidelift" } ], - "time": "2026-01-12T12:19:02+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/service-contracts", @@ -8088,16 +8160,16 @@ }, { "name": "symfony/string", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f" + "reference": "114ac57257d75df748eda23dd003878080b8e688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/1c4b10461bf2ec27537b5f36105337262f5f5d6f", - "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f", + "url": "https://api.github.com/repos/symfony/string/zipball/114ac57257d75df748eda23dd003878080b8e688", + "reference": "114ac57257d75df748eda23dd003878080b8e688", "shasum": "" }, "require": { @@ -8155,7 +8227,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.4" + "source": "https://github.com/symfony/string/tree/v7.4.8" }, "funding": [ { @@ -8175,20 +8247,20 @@ "type": "tidelift" } ], - "time": "2026-01-12T10:54:30+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/translation", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "bfde13711f53f549e73b06d27b35a55207528877" + "reference": "33600f8489485425bfcddd0d983391038d3422e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/bfde13711f53f549e73b06d27b35a55207528877", - "reference": "bfde13711f53f549e73b06d27b35a55207528877", + "url": "https://api.github.com/repos/symfony/translation/zipball/33600f8489485425bfcddd0d983391038d3422e7", + "reference": "33600f8489485425bfcddd0d983391038d3422e7", "shasum": "" }, "require": { @@ -8255,7 +8327,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.4.4" + "source": "https://github.com/symfony/translation/tree/v7.4.8" }, "funding": [ { @@ -8275,7 +8347,7 @@ "type": "tidelift" } ], - "time": "2026-01-13T10:40:19+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/translation-contracts", @@ -8361,16 +8433,16 @@ }, { "name": "symfony/uid", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36" + "reference": "6883ebdf7bf6a12b37519dbc0df62b0222401b56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/7719ce8aba76be93dfe249192f1fbfa52c588e36", - "reference": "7719ce8aba76be93dfe249192f1fbfa52c588e36", + "url": "https://api.github.com/repos/symfony/uid/zipball/6883ebdf7bf6a12b37519dbc0df62b0222401b56", + "reference": "6883ebdf7bf6a12b37519dbc0df62b0222401b56", "shasum": "" }, "require": { @@ -8415,7 +8487,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.4.4" + "source": "https://github.com/symfony/uid/tree/v7.4.8" }, "funding": [ { @@ -8435,20 +8507,20 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:30:35+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "0e4769b46a0c3c62390d124635ce59f66874b282" + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0e4769b46a0c3c62390d124635ce59f66874b282", - "reference": "0e4769b46a0c3c62390d124635ce59f66874b282", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd", + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd", "shasum": "" }, "require": { @@ -8502,7 +8574,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.4.4" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.8" }, "funding": [ { @@ -8522,20 +8594,20 @@ "type": "tidelift" } ], - "time": "2026-01-01T22:13:48+00:00" + "time": "2026-03-30T13:44:50+00:00" }, { "name": "thecodingmachine/safe", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/thecodingmachine/safe.git", - "reference": "2cdd579eeaa2e78e51c7509b50cc9fb89a956236" + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/2cdd579eeaa2e78e51c7509b50cc9fb89a956236", - "reference": "2cdd579eeaa2e78e51c7509b50cc9fb89a956236", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19", "shasum": "" }, "require": { @@ -8645,7 +8717,7 @@ "description": "PHP core functions that throw exceptions instead of returning FALSE on error", "support": { "issues": "https://github.com/thecodingmachine/safe/issues", - "source": "https://github.com/thecodingmachine/safe/tree/v3.3.0" + "source": "https://github.com/thecodingmachine/safe/tree/v3.4.0" }, "funding": [ { @@ -8656,12 +8728,16 @@ "url": "https://github.com/shish", "type": "github" }, + { + "url": "https://github.com/silasjoisten", + "type": "github" + }, { "url": "https://github.com/staabm", "type": "github" } ], - "time": "2025-05-14T06:15:44+00:00" + "time": "2026-02-04T18:08:13+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -8804,23 +8880,23 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.3", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "reference": "d870a33f0f79d2b4579740b0620200221ee44aeb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/d870a33f0f79d2b4579740b0620200221ee44aeb", + "reference": "d870a33f0f79d2b4579740b0620200221ee44aeb", "shasum": "" }, "require": { - "php": ">=7.0.0" + "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5" }, "suggest": { "ext-intl": "Use Intl for transliterator_transliterate() support" @@ -8850,7 +8926,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "source": "https://github.com/voku/portable-ascii/tree/2.1.0" }, "funding": [ { @@ -8874,7 +8950,7 @@ "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" + "time": "2026-04-16T23:10:39+00:00" }, { "name": "webklex/php-imap", @@ -8961,16 +9037,16 @@ "packages-dev": [ { "name": "brianium/paratest", - "version": "v7.17.0", + "version": "v7.20.0", "source": { "type": "git", "url": "https://github.com/paratestphp/paratest.git", - "reference": "53cb90a6aa3ef3840458781600628ade058a18b9" + "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/53cb90a6aa3ef3840458781600628ade058a18b9", - "reference": "53cb90a6aa3ef3840458781600628ade058a18b9", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/81c80677c9ec0ed4ef16b246167f11dec81a6e3d", + "reference": "81c80677c9ec0ed4ef16b246167f11dec81a6e3d", "shasum": "" }, "require": { @@ -8981,24 +9057,24 @@ "fidry/cpu-core-counter": "^1.3.0", "jean85/pretty-package-versions": "^2.1.1", "php": "~8.3.0 || ~8.4.0 || ~8.5.0", - "phpunit/php-code-coverage": "^12.5.2", - "phpunit/php-file-iterator": "^6", - "phpunit/php-timer": "^8", - "phpunit/phpunit": "^12.5.8", - "sebastian/environment": "^8.0.3", - "symfony/console": "^7.3.4 || ^8.0.0", - "symfony/process": "^7.3.4 || ^8.0.0" + "phpunit/php-code-coverage": "^12.5.3 || ^13.0.1", + "phpunit/php-file-iterator": "^6.0.1 || ^7", + "phpunit/php-timer": "^8 || ^9", + "phpunit/phpunit": "^12.5.14 || ^13.0.5", + "sebastian/environment": "^8.0.3 || ^9", + "symfony/console": "^7.4.7 || ^8.0.7", + "symfony/process": "^7.4.5 || ^8.0.5" }, "require-dev": { "doctrine/coding-standard": "^14.0.0", "ext-pcntl": "*", "ext-pcov": "*", "ext-posix": "*", - "phpstan/phpstan": "^2.1.38", - "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.12", - "phpstan/phpstan-strict-rules": "^2.0.8", - "symfony/filesystem": "^7.3.2 || ^8.0.0" + "phpstan/phpstan": "^2.1.44", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.16", + "phpstan/phpstan-strict-rules": "^2.0.10", + "symfony/filesystem": "^7.4.6 || ^8.0.6" }, "bin": [ "bin/paratest", @@ -9038,7 +9114,7 @@ ], "support": { "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.17.0" + "source": "https://github.com/paratestphp/paratest/tree/v7.20.0" }, "funding": [ { @@ -9050,7 +9126,7 @@ "type": "paypal" } ], - "time": "2026-02-05T09:14:44+00:00" + "time": "2026-03-29T15:46:14+00:00" }, { "name": "doctrine/deprecations", @@ -9408,33 +9484,33 @@ }, { "name": "laravel/boost", - "version": "v2.1.1", + "version": "v2.4.5", "source": { "type": "git", "url": "https://github.com/laravel/boost.git", - "reference": "1c7d6f44c96937a961056778b9143218b1183302" + "reference": "60386c7723ff7cb388b62b6c137597244a9cf2f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/boost/zipball/1c7d6f44c96937a961056778b9143218b1183302", - "reference": "1c7d6f44c96937a961056778b9143218b1183302", + "url": "https://api.github.com/repos/laravel/boost/zipball/60386c7723ff7cb388b62b6c137597244a9cf2f2", + "reference": "60386c7723ff7cb388b62b6c137597244a9cf2f2", "shasum": "" }, "require": { "guzzlehttp/guzzle": "^7.9", - "illuminate/console": "^11.45.3|^12.41.1", - "illuminate/contracts": "^11.45.3|^12.41.1", - "illuminate/routing": "^11.45.3|^12.41.1", - "illuminate/support": "^11.45.3|^12.41.1", - "laravel/mcp": "^0.5.1", + "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.5.1|^0.6.0|^0.7.0", "laravel/prompts": "^0.3.10", - "laravel/roster": "^0.2.9", + "laravel/roster": "^0.5.0", "php": "^8.2" }, "require-dev": { "laravel/pint": "^1.27.0", "mockery/mockery": "^1.6.12", - "orchestra/testbench": "^9.15.0|^10.6", + "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" @@ -9470,20 +9546,20 @@ "issues": "https://github.com/laravel/boost/issues", "source": "https://github.com/laravel/boost" }, - "time": "2026-02-06T10:41:29+00:00" + "time": "2026-04-22T13:29:20+00:00" }, { "name": "laravel/mcp", - "version": "v0.5.5", + "version": "v0.7.0", "source": { "type": "git", "url": "https://github.com/laravel/mcp.git", - "reference": "b3327bb75fd2327577281e507e2dbc51649513d6" + "reference": "3513b4feca5f1678be4d2261dcfa8e456436d02a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/mcp/zipball/b3327bb75fd2327577281e507e2dbc51649513d6", - "reference": "b3327bb75fd2327577281e507e2dbc51649513d6", + "url": "https://api.github.com/repos/laravel/mcp/zipball/3513b4feca5f1678be4d2261dcfa8e456436d02a", + "reference": "3513b4feca5f1678be4d2261dcfa8e456436d02a", "shasum": "" }, "require": { @@ -9543,20 +9619,20 @@ "issues": "https://github.com/laravel/mcp/issues", "source": "https://github.com/laravel/mcp" }, - "time": "2026-02-05T14:05:18+00:00" + "time": "2026-04-21T10:23:03+00:00" }, { "name": "laravel/pail", - "version": "v1.2.5", + "version": "v1.2.6", "source": { "type": "git", "url": "https://github.com/laravel/pail.git", - "reference": "fdb73f5eacf03db576c710d5a00101ba185f2254" + "reference": "aa71a01c309e7f66bc2ec4fb1a59291b82eb4abf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pail/zipball/fdb73f5eacf03db576c710d5a00101ba185f2254", - "reference": "fdb73f5eacf03db576c710d5a00101ba185f2254", + "url": "https://api.github.com/repos/laravel/pail/zipball/aa71a01c309e7f66bc2ec4fb1a59291b82eb4abf", + "reference": "aa71a01c309e7f66bc2ec4fb1a59291b82eb4abf", "shasum": "" }, "require": { @@ -9623,20 +9699,20 @@ "issues": "https://github.com/laravel/pail/issues", "source": "https://github.com/laravel/pail" }, - "time": "2026-02-04T15:10:32+00:00" + "time": "2026-02-09T13:44:54+00:00" }, { "name": "laravel/pint", - "version": "v1.27.0", + "version": "v1.29.1", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90" + "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/c67b4195b75491e4dfc6b00b1c78b68d86f54c90", - "reference": "c67b4195b75491e4dfc6b00b1c78b68d86f54c90", + "url": "https://api.github.com/repos/laravel/pint/zipball/0770e9b7fafd50d4586881d456d6eb41c9247a80", + "reference": "0770e9b7fafd50d4586881d456d6eb41c9247a80", "shasum": "" }, "require": { @@ -9647,13 +9723,14 @@ "php": "^8.2.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.92.4", - "illuminate/view": "^12.44.0", - "larastan/larastan": "^3.8.1", - "laravel-zero/framework": "^12.0.4", + "friendsofphp/php-cs-fixer": "^3.95.1", + "illuminate/view": "^12.56.0", + "larastan/larastan": "^3.9.6", + "laravel-zero/framework": "^12.1.0", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^2.3.3", - "pestphp/pest": "^3.8.4" + "nunomaduro/termwind": "^2.4.0", + "pestphp/pest": "^3.8.6", + "shipfastlabs/agent-detector": "^1.1.3" }, "bin": [ "builds/pint" @@ -9690,35 +9767,35 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2026-01-05T16:49:17+00:00" + "time": "2026-04-20T15:26:14+00:00" }, { "name": "laravel/roster", - "version": "v0.2.9", + "version": "v0.5.1", "source": { "type": "git", "url": "https://github.com/laravel/roster.git", - "reference": "82bbd0e2de614906811aebdf16b4305956816fa6" + "reference": "5089de7615f72f78e831590ff9d0435fed0102bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/roster/zipball/82bbd0e2de614906811aebdf16b4305956816fa6", - "reference": "82bbd0e2de614906811aebdf16b4305956816fa6", + "url": "https://api.github.com/repos/laravel/roster/zipball/5089de7615f72f78e831590ff9d0435fed0102bb", + "reference": "5089de7615f72f78e831590ff9d0435fed0102bb", "shasum": "" }, "require": { - "illuminate/console": "^10.0|^11.0|^12.0", - "illuminate/contracts": "^10.0|^11.0|^12.0", - "illuminate/routing": "^10.0|^11.0|^12.0", - "illuminate/support": "^10.0|^11.0|^12.0", - "php": "^8.1|^8.2", - "symfony/yaml": "^6.4|^7.2" + "illuminate/console": "^11.0|^12.0|^13.0", + "illuminate/contracts": "^11.0|^12.0|^13.0", + "illuminate/routing": "^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.14", "mockery/mockery": "^1.6", - "orchestra/testbench": "^8.22.0|^9.0|^10.0", - "pestphp/pest": "^2.0|^3.0", + "orchestra/testbench": "^9.0|^10.0|^11.0", + "pestphp/pest": "^3.0|^4.1", "phpstan/phpstan": "^2.0" }, "type": "library", @@ -9751,70 +9828,7 @@ "issues": "https://github.com/laravel/roster/issues", "source": "https://github.com/laravel/roster" }, - "time": "2025-10-20T09:56:46+00:00" - }, - { - "name": "laravel/sail", - "version": "v1.52.0", - "source": { - "type": "git", - "url": "https://github.com/laravel/sail.git", - "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/64ac7d8abb2dbcf2b76e61289451bae79066b0b3", - "reference": "64ac7d8abb2dbcf2b76e61289451bae79066b0b3", - "shasum": "" - }, - "require": { - "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", - "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", - "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", - "php": "^8.0", - "symfony/console": "^6.0|^7.0", - "symfony/yaml": "^6.0|^7.0" - }, - "require-dev": { - "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", - "phpstan/phpstan": "^2.0" - }, - "bin": [ - "bin/sail" - ], - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Sail\\SailServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Sail\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Docker files for running a basic Laravel application.", - "keywords": [ - "docker", - "laravel" - ], - "support": { - "issues": "https://github.com/laravel/sail/issues", - "source": "https://github.com/laravel/sail" - }, - "time": "2026-01-01T02:46:03+00:00" + "time": "2026-03-05T07:58:43+00:00" }, { "name": "mockery/mockery", @@ -9961,39 +9975,36 @@ }, { "name": "nunomaduro/collision", - "version": "v8.8.3", + "version": "v8.9.4", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4" + "reference": "716af8f95a470e9094cfca09ed897b023be191a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/1dc9e88d105699d0fee8bb18890f41b274f6b4c4", - "reference": "1dc9e88d105699d0fee8bb18890f41b274f6b4c4", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/716af8f95a470e9094cfca09ed897b023be191a5", + "reference": "716af8f95a470e9094cfca09ed897b023be191a5", "shasum": "" }, "require": { - "filp/whoops": "^2.18.1", - "nunomaduro/termwind": "^2.3.1", + "filp/whoops": "^2.18.4", + "nunomaduro/termwind": "^2.4.0", "php": "^8.2.0", - "symfony/console": "^7.3.0" + "symfony/console": "^7.4.8 || ^8.0.8" }, "conflict": { - "laravel/framework": "<11.44.2 || >=13.0.0", - "phpunit/phpunit": "<11.5.15 || >=13.0.0" + "laravel/framework": "<11.48.0 || >=14.0.0", + "phpunit/phpunit": "<11.5.50 || >=14.0.0" }, "require-dev": { - "brianium/paratest": "^7.8.3", - "larastan/larastan": "^3.4.2", - "laravel/framework": "^11.44.2 || ^12.18", - "laravel/pint": "^1.22.1", - "laravel/sail": "^1.43.1", - "laravel/sanctum": "^4.1.1", - "laravel/tinker": "^2.10.1", - "orchestra/testbench-core": "^9.12.0 || ^10.4", - "pestphp/pest": "^3.8.2 || ^4.0.0", - "sebastian/environment": "^7.2.1 || ^8.0" + "brianium/paratest": "^7.8.5", + "larastan/larastan": "^3.9.6", + "laravel/framework": "^11.48.0 || ^12.56.0 || ^13.5.0", + "laravel/pint": "^1.29.1", + "orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.2.1", + "pestphp/pest": "^3.8.5 || ^4.4.3 || ^5.0.0", + "sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.3.0" }, "type": "library", "extra": { @@ -10056,45 +10067,46 @@ "type": "patreon" } ], - "time": "2025-11-20T02:55:25+00:00" + "time": "2026-04-21T14:04:20+00:00" }, { "name": "pestphp/pest", - "version": "v4.3.2", + "version": "v4.6.3", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "3a4329ddc7a2b67c19fca8342a668b39be3ae398" + "reference": "bff44562a99d30aa37573995566051b0344f9f8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/3a4329ddc7a2b67c19fca8342a668b39be3ae398", - "reference": "3a4329ddc7a2b67c19fca8342a668b39be3ae398", + "url": "https://api.github.com/repos/pestphp/pest/zipball/bff44562a99d30aa37573995566051b0344f9f8e", + "reference": "bff44562a99d30aa37573995566051b0344f9f8e", "shasum": "" }, "require": { - "brianium/paratest": "^7.16.1", - "nunomaduro/collision": "^8.8.3", - "nunomaduro/termwind": "^2.3.3", + "brianium/paratest": "^7.20.0", + "nunomaduro/collision": "^8.9.3", + "nunomaduro/termwind": "^2.4.0", "pestphp/pest-plugin": "^4.0.0", - "pestphp/pest-plugin-arch": "^4.0.0", + "pestphp/pest-plugin-arch": "^4.0.2", "pestphp/pest-plugin-mutate": "^4.0.1", "pestphp/pest-plugin-profanity": "^4.2.1", "php": "^8.3.0", - "phpunit/phpunit": "^12.5.8", - "symfony/process": "^7.4.4|^8.0.0" + "phpunit/phpunit": "^12.5.23", + "symfony/process": "^7.4.8|^8.0.8" }, "conflict": { "filp/whoops": "<2.18.3", - "phpunit/phpunit": ">12.5.8", + "phpunit/phpunit": ">12.5.23", "sebastian/exporter": "<7.0.0", "webmozart/assert": "<1.11.0" }, "require-dev": { - "pestphp/pest-dev-tools": "^4.0.0", - "pestphp/pest-plugin-browser": "^4.2.1", - "pestphp/pest-plugin-type-coverage": "^4.0.3", - "psy/psysh": "^0.12.18" + "mrpunyapal/peststan": "^0.2.5", + "pestphp/pest-dev-tools": "^4.1.0", + "pestphp/pest-plugin-browser": "^4.3.1", + "pestphp/pest-plugin-type-coverage": "^4.0.4", + "psy/psysh": "^0.12.22" }, "bin": [ "bin/pest" @@ -10160,7 +10172,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v4.3.2" + "source": "https://github.com/pestphp/pest/tree/v4.6.3" }, "funding": [ { @@ -10172,7 +10184,7 @@ "type": "github" } ], - "time": "2026-01-28T01:01:19+00:00" + "time": "2026-04-18T13:51:25+00:00" }, { "name": "pestphp/pest-plugin", @@ -10246,26 +10258,26 @@ }, { "name": "pestphp/pest-plugin-arch", - "version": "v4.0.0", + "version": "v4.0.2", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-arch.git", - "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d" + "reference": "3fb0d02a91b9da504b139dc7ab2a31efb7c3215c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/25bb17e37920ccc35cbbcda3b00d596aadf3e58d", - "reference": "25bb17e37920ccc35cbbcda3b00d596aadf3e58d", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/3fb0d02a91b9da504b139dc7ab2a31efb7c3215c", + "reference": "3fb0d02a91b9da504b139dc7ab2a31efb7c3215c", "shasum": "" }, "require": { "pestphp/pest-plugin": "^4.0.0", "php": "^8.3", - "ta-tikoma/phpunit-architecture-test": "^0.8.5" + "ta-tikoma/phpunit-architecture-test": "^0.8.7" }, "require-dev": { - "pestphp/pest": "^4.0.0", - "pestphp/pest-dev-tools": "^4.0.0" + "pestphp/pest": "^4.4.6", + "pestphp/pest-dev-tools": "^4.1.0" }, "type": "library", "extra": { @@ -10300,7 +10312,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v4.0.2" }, "funding": [ { @@ -10312,31 +10324,31 @@ "type": "github" } ], - "time": "2025-08-20T13:10:51+00:00" + "time": "2026-04-10T17:20:19+00:00" }, { "name": "pestphp/pest-plugin-laravel", - "version": "v4.0.0", + "version": "v4.1.0", "source": { "type": "git", "url": "https://github.com/pestphp/pest-plugin-laravel.git", - "reference": "e12a07046b826a40b1c8632fd7b80d6b8d7b628e" + "reference": "3057a36669ff11416cc0dc2b521b3aec58c488d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/e12a07046b826a40b1c8632fd7b80d6b8d7b628e", - "reference": "e12a07046b826a40b1c8632fd7b80d6b8d7b628e", + "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/3057a36669ff11416cc0dc2b521b3aec58c488d0", + "reference": "3057a36669ff11416cc0dc2b521b3aec58c488d0", "shasum": "" }, "require": { - "laravel/framework": "^11.45.2|^12.25.0", - "pestphp/pest": "^4.0.0", + "laravel/framework": "^11.45.2|^12.52.0|^13.0", + "pestphp/pest": "^4.4.1", "php": "^8.3.0" }, "require-dev": { - "laravel/dusk": "^8.3.3", - "orchestra/testbench": "^9.13.0|^10.5.0", - "pestphp/pest-dev-tools": "^4.0.0" + "laravel/dusk": "^8.3.6", + "orchestra/testbench": "^9.13.0|^10.9.0|^11.0", + "pestphp/pest-dev-tools": "^4.1.0" }, "type": "library", "extra": { @@ -10374,7 +10386,7 @@ "unit" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v4.0.0" + "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v4.1.0" }, "funding": [ { @@ -10386,7 +10398,7 @@ "type": "github" } ], - "time": "2025-08-20T12:46:37+00:00" + "time": "2026-02-21T00:29:45+00:00" }, { "name": "pestphp/pest-plugin-mutate", @@ -10693,16 +10705,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.6", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", - "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582", + "reference": "7bae67520aa9f5ecc506d646810bd40d9da54582", "shasum": "" }, "require": { @@ -10710,8 +10722,8 @@ "ext-filter": "*", "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7|^2.0", + "phpdocumentor/type-resolver": "^2.0", + "phpstan/phpdoc-parser": "^2.0", "webmozart/assert": "^1.9.1 || ^2" }, "require-dev": { @@ -10721,7 +10733,8 @@ "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^9.5", - "psalm/phar": "^5.26" + "psalm/phar": "^5.26", + "shipmonk/dead-code-detector": "^0.5.1" }, "type": "library", "extra": { @@ -10751,44 +10764,44 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.3" }, - "time": "2025-12-22T21:13:58+00:00" + "time": "2026-03-18T20:49:53+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.12.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18|^2.0" + "phpstan/phpdoc-parser": "^2.0" }, "require-dev": { "ext-tokenizer": "*", "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" + "psalm/phar": "^4" }, "type": "library", "extra": { "branch-alias": { - "dev-1.x": "1.x-dev" + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -10809,9 +10822,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/2.0.0" }, - "time": "2025-11-21T15:09:14+00:00" + "time": "2026-01-06T21:53:42+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -10862,16 +10875,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "12.5.3", + "version": "12.5.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d" + "reference": "876099a072646c7745f673d7aeab5382c4439691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b015312f28dd75b75d3422ca37dff2cd1a565e8d", - "reference": "b015312f28dd75b75d3422ca37dff2cd1a565e8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/876099a072646c7745f673d7aeab5382c4439691", + "reference": "876099a072646c7745f673d7aeab5382c4439691", "shasum": "" }, "require": { @@ -10880,7 +10893,6 @@ "ext-xmlwriter": "*", "nikic/php-parser": "^5.7.0", "php": ">=8.3", - "phpunit/php-file-iterator": "^6.0", "phpunit/php-text-template": "^5.0", "sebastian/complexity": "^5.0", "sebastian/environment": "^8.0.3", @@ -10927,7 +10939,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.6" }, "funding": [ { @@ -10947,7 +10959,7 @@ "type": "tidelift" } ], - "time": "2026-02-06T06:01:44+00:00" + "time": "2026-04-15T08:23:17+00:00" }, { "name": "phpunit/php-file-iterator", @@ -11208,16 +11220,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.8", + "version": "12.5.23", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "37ddb96c14bfee10304825edbb7e66d341ec6889" + "reference": "c54fcf3d6bcb6e96ac2f7e40097dc37b5f139969" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/37ddb96c14bfee10304825edbb7e66d341ec6889", - "reference": "37ddb96c14bfee10304825edbb7e66d341ec6889", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c54fcf3d6bcb6e96ac2f7e40097dc37b5f139969", + "reference": "c54fcf3d6bcb6e96ac2f7e40097dc37b5f139969", "shasum": "" }, "require": { @@ -11231,18 +11243,19 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.2", - "phpunit/php-file-iterator": "^6.0.0", + "phpunit/php-code-coverage": "^12.5.6", + "phpunit/php-file-iterator": "^6.0.1", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", "phpunit/php-timer": "^8.0.0", "sebastian/cli-parser": "^4.2.0", - "sebastian/comparator": "^7.1.4", + "sebastian/comparator": "^7.1.6", "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.3", + "sebastian/environment": "^8.1.0", "sebastian/exporter": "^7.0.2", "sebastian/global-state": "^8.0.2", "sebastian/object-enumerator": "^7.0.0", + "sebastian/recursion-context": "^7.0.1", "sebastian/type": "^6.0.3", "sebastian/version": "^6.0.0", "staabm/side-effects-detector": "^1.0.5" @@ -11285,31 +11298,15 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.8" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.23" }, "funding": [ { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" + "url": "https://phpunit.de/sponsoring.html", + "type": "other" } ], - "time": "2026-01-27T06:12:29+00:00" + "time": "2026-04-18T06:12:49+00:00" }, { "name": "sebastian/cli-parser", @@ -11382,16 +11379,16 @@ }, { "name": "sebastian/comparator", - "version": "7.1.4", + "version": "7.1.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6" + "reference": "c769009dee98f494e0edc3fd4f4087501688f11e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a7de5df2e094f9a80b40a522391a7e6022df5f6", - "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/c769009dee98f494e0edc3fd4f4087501688f11e", + "reference": "c769009dee98f494e0edc3fd4f4087501688f11e", "shasum": "" }, "require": { @@ -11450,7 +11447,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.4" + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.6" }, "funding": [ { @@ -11470,7 +11467,7 @@ "type": "tidelift" } ], - "time": "2026-01-24T09:28:48+00:00" + "time": "2026-04-14T08:23:15+00:00" }, { "name": "sebastian/complexity", @@ -11599,16 +11596,16 @@ }, { "name": "sebastian/environment", - "version": "8.0.3", + "version": "8.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68" + "reference": "b121608b28a13f721e76ffbbd386d08eff58f3f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/24a711b5c916efc6d6e62aa65aa2ec98fef77f68", - "reference": "24a711b5c916efc6d6e62aa65aa2ec98fef77f68", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/b121608b28a13f721e76ffbbd386d08eff58f3f6", + "reference": "b121608b28a13f721e76ffbbd386d08eff58f3f6", "shasum": "" }, "require": { @@ -11623,7 +11620,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "8.0-dev" + "dev-main": "8.1-dev" } }, "autoload": { @@ -11651,7 +11648,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/8.0.3" + "source": "https://github.com/sebastianbergmann/environment/tree/8.1.0" }, "funding": [ { @@ -11671,7 +11668,7 @@ "type": "tidelift" } ], - "time": "2025-08-12T14:11:56+00:00" + "time": "2026-04-15T12:13:01+00:00" }, { "name": "sebastian/exporter", @@ -12262,16 +12259,16 @@ }, { "name": "symfony/yaml", - "version": "v7.4.1", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" + "reference": "c58fdf7b3d6c2995368264c49e4e8b05bcff2883" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c58fdf7b3d6c2995368264c49e4e8b05bcff2883", + "reference": "c58fdf7b3d6c2995368264c49e4e8b05bcff2883", "shasum": "" }, "require": { @@ -12314,7 +12311,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.1" + "source": "https://github.com/symfony/yaml/tree/v7.4.8" }, "funding": [ { @@ -12334,27 +12331,27 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:11:45+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", - "version": "0.8.6", + "version": "0.8.7", "source": { "type": "git", "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", - "reference": "ad48430b92901fd7d003fdaf2d7b139f96c0906e" + "reference": "1248f3f506ca9641d4f68cebcd538fa489754db8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/ad48430b92901fd7d003fdaf2d7b139f96c0906e", - "reference": "ad48430b92901fd7d003fdaf2d7b139f96c0906e", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/1248f3f506ca9641d4f68cebcd538fa489754db8", + "reference": "1248f3f506ca9641d4f68cebcd538fa489754db8", "shasum": "" }, "require": { "nikic/php-parser": "^4.18.0 || ^5.0.0", "php": "^8.1.0", "phpdocumentor/reflection-docblock": "^5.3.0 || ^6.0.0", - "phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0 || ^12.0.0 || ^13.0.0", "symfony/finder": "^6.4.0 || ^7.0.0 || ^8.0.0" }, "require-dev": { @@ -12391,9 +12388,9 @@ ], "support": { "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", - "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.6" + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.7" }, - "time": "2026-01-30T07:16:00+00:00" + "time": "2026-02-17T17:25:14+00:00" }, { "name": "theseer/tokenizer", @@ -12447,16 +12444,16 @@ }, { "name": "webmozart/assert", - "version": "2.1.2", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649" + "reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", - "reference": "ce6a2f100c404b2d32a1dd1270f9b59ad4f57649", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/eb0d790f735ba6cff25c683a85a1da0eadeff9e4", + "reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4", "shasum": "" }, "require": { @@ -12503,19 +12500,19 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.1.2" + "source": "https://github.com/webmozarts/assert/tree/2.3.0" }, - "time": "2026-01-13T14:02:24+00:00" + "time": "2026-04-11T10:33:05+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": {}, - "plugin-api-version": "2.9.0" + "platform-dev": [], + "plugin-api-version": "2.6.0" } diff --git a/website/vite.config.ts b/website/vite.config.ts index ab38a59..fcc7c95 100644 --- a/website/vite.config.ts +++ b/website/vite.config.ts @@ -33,6 +33,23 @@ export default defineConfig({ }, }, server: { + host: process.env.VITE_HOST ?? 'localhost', + // When running inside the Docker stack, Vite is reached via Traefik at + // a public hostname. VITE_ORIGIN tells the laravel-vite-plugin + // what URL to write into public/hot so the browser can fetch modules. + origin: process.env.VITE_ORIGIN || undefined, + // Vite 7 defaults to a strict CORS regex that doesn't allow multi-label + // .localhost hosts. When in Docker mode, allow any *.docker.localhost. + cors: process.env.VITE_HMR_HOST + ? { origin: /^https?:\/\/.+\.docker\.localhost(?::\d+)?$/ } + : true, + hmr: process.env.VITE_HMR_HOST + ? { + host: process.env.VITE_HMR_HOST, + protocol: process.env.VITE_ORIGIN?.startsWith('https') ? 'wss' : 'ws', + clientPort: process.env.VITE_ORIGIN?.startsWith('https') ? 443 : 80, + } + : undefined, watch: { ignored: ['**/storage/framework/views/**'], },