wyxos/shift-php adds issue reporting and task follow-up inside a Laravel application. It ships the /shift dashboard, an optional in-app report widget, task and thread routes, external collaborator lookup, browser-based installation, and cleaned backend error reporting.
A Laravel app user reports an issue from the page where it happened, the package sends the page URL, route, environment, and user details to the portal, and the developer follows up on the resulting task.
composer require wyxos/shift-php
php artisan install:shiftThe default installer uses browser verification:
- Reads
APP_ENVandAPP_URLfrom the Laravel app. - Creates an install session in the portal.
- Prints a verification URL and short code for browser approval.
- Waits for approval through Reverb when available, with polling fallback.
- Lets you choose a project or create one when the account has no available option.
- Writes
SHIFT_TOKENandSHIFT_PROJECTto the app.env. - Registers the current app environment and URL.
- Scaffolds
App\Services\ShiftCollaboratorResolverwhen the app does not already have one. - Publishes config and frontend assets.
If SHIFT_TOKEN and SHIFT_PROJECT already exist, the installer keeps those values and skips browser verification.
For manual token setup, run:
php artisan install:shift --manualTypical .env values:
SHIFT_URL=https://shift.wyxos.com
SHIFT_TOKEN=your-shift-api-token
SHIFT_PROJECT=your-shift-project-token
SHIFT_COLLABORATORS_RESOLVER=App\Services\ShiftCollaboratorResolver
SHIFT_ERROR_REPORTING_ENABLED=trueHosted portal:
SHIFT_URL=https://shift.wyxos.comLocal or self-hosted portal:
SHIFT_URL=https://shift.testLocal, .test, .local, localhost, and private IP portal URLs are treated as private by the package client, so SSL verification is skipped for package-to-portal requests. The active portal still needs network access to the app URL when it calls the app for collaborator lookup.
Publish the config when you need to customize middleware, widget behavior, or error-reporting settings:
php artisan vendor:publish --tag=shiftImportant config keys:
return [
'token' => env('SHIFT_TOKEN'),
'project' => env('SHIFT_PROJECT'),
'url' => env('SHIFT_URL', 'https://shift.wyxos.com'),
'routes' => [
'prefix' => 'shift',
'middleware' => ['web', 'auth'],
],
'widget' => [
'enabled' => env('SHIFT_WIDGET_ENABLED', true),
'routes' => [
'middleware' => ['web'],
],
],
'errors' => [
'enabled' => env('SHIFT_ERROR_REPORTING_ENABLED', true),
'endpoint' => env('SHIFT_ERROR_REPORTING_ENDPOINT', '/api/errors'),
'timeout' => env('SHIFT_ERROR_REPORTING_TIMEOUT', 3),
],
];After installation, the dashboard is available at:
/shift
It uses the configured route middleware, which defaults to web and auth. Authenticated users can create tasks, edit task details, comment in threads, upload attachments, and manage collaborators for the linked project.
For a lightweight report form inside the host app, use the widget endpoint:
POST /shift/api/widget/tasksExample browser submission:
await fetch('/shift/api/widget/tasks', {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify({
kind: 'issue',
title: 'Invoice export does not download',
description: 'I clicked Export CSV on invoice INV-1047 and no file downloaded.',
anonymous: false,
metadata: {
page_url: window.location.href,
page_title: document.title,
referrer: document.referrer || null,
},
}),
});For the authenticated dashboard and task routes, the package passes these requests through to SHIFT:
GET /shift/api/tasksPOST /shift/api/tasksGET /shift/api/tasks/{id}PUT /shift/api/tasks/{id}PATCH /shift/api/tasks/{id}/collaboratorsGET /shift/api/tasks/{taskId}/threadsPOST /shift/api/tasks/{taskId}/threads
When SHIFT_ERROR_REPORTING_ENABLED=true, the package registers a Laravel exception reporter. It sends cleaned backend exception details to the configured portal without blocking the app's normal exception handling.
The reporter never blocks the app. Missing credentials, disabled reporting, connection failures, timeouts, or failed portal responses are ignored.
The package detects the revision from deployment commit metadata or the app Git checkout. If the checkout has an exact tag for that revision, the tag is sent as the release.
Task and dashboard requests include:
- Project token.
- Authenticated app user name, email, and ID when available.
- App environment from
APP_ENV. - App URL from
APP_URL. - User-entered task fields such as title, description, status, priority, comments, attachments, and collaborator choices.
Widget submissions include:
- Report kind, title, and description.
- Anonymous flag.
- Page details supplied by the widget, such as current page URL, page title, and referrer.
- Authenticated app user details, or guest name/email when guest details are submitted and anonymous mode is not used.
- Linked app name, environment, and URL.
Backend error reports include:
- Project token.
- App environment, app URL, release, and revision.
- Exception class and cleaned message.
- Stack frames and limited source code for in-app files.
- Request method, URL, path, referrer, IP, user agent, query, and body after scrubbing.
- PHP and Laravel versions.
- Authenticated user details when available.
The error cleaner removes common sensitive fields such as password, token, authorization, and cookie values. You should still avoid adding secrets or sensitive customer data to task descriptions, widget details, or exception messages.
php artisan config:clear
php artisan shift:testshift:test creates a QA task in the configured project. Use a local or self-hosted portal unless you intentionally want that task in a hosted project.
Run the installer or set both SHIFT_TOKEN and SHIFT_PROJECT, then clear cached config:
php artisan install:shift
php artisan config:clearThe default installer needs an interactive terminal. In CI or non-interactive setup, obtain an API token and project token first, then run:
php artisan install:shift --manualThe installer warns when APP_URL is local or private. Task submission still works when the package can reach the portal, but external collaborator lookup requires that portal to reach the app's /shift/api/collaborators/external endpoint.
In a consuming Laravel app, publish the current package assets:
php artisan shift:publish --group=publicCheck whether the portal project allows widget reports and whether guest submissions are allowed. If guest submissions are disabled, the app user must be authenticated through the configured widget guard.
Check the validation response from the portal. Common causes are missing title/description, an invalid project token, or project configuration that does not allow the requested report path.
Check that error reporting is enabled and fully configured:
php artisan config:clear
php artisan tinker
>>> config('shift.errors.enabled')
>>> config('shift.url')
>>> filled(config('shift.token'))
>>> filled(config('shift.project'))The reporter is intentionally silent on network failures and failed portal responses so it does not interfere with application error handling.
MIT Wyxos. See LICENSE.md for details.