Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Redline Laravel Package

zipavlin/redline

Redline is a lightweight Laravel/PHP package that helps you define and enforce boundaries in your application. With simple configuration and a clean API, it adds practical guard rails and limits without heavy dependencies, making it a good fit for small to mid-sized projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Redline is a self-contained issue/report tracker that runs inside a Laravel host app: it ships its own SQLite StorageProvider, an embeddable widget, a dashboard, an HTTP API under /{path}/api/*, and — as of v0.3.0 — an MCP server so coding agents can read and triage reports. Your day-to-day job is wiring auth, roles, feature flags, and the upgrade path — not touching package internals.

  1. Check your Laravel version first. v0.3.0 dropped Laravel 11; you need Laravel 12.41.1+ (or 13). The MCP server's dependencies require it. Upgrade Laravel before you touch Redline.
  2. Turn features back on explicitly. Nothing is enabled until it's listed in REDLINE_FEATURES (e.g. REDLINE_FEATURES=screenshots,comments,mcp). This replaces REDLINE_DISABLED, and existing installs must set it once or every feature stays off. Use php artisan redline:enable to list features and switch them on/off from the CLI; a misspelled name hard-fails the app rather than being ignored.
  3. Install and upgrade. composer require the package, then run php artisan redline:update (alias redline:upgrade). It backs up the SQLite DB, runs pending migrations (including the new redline_tokens table), re-publishes assets, and clears config/view/route caches. It also prints what's enabled. Use --dry-run first, and --no-backup only when your platform already snapshots storage.
  4. Auth is the host app's session. LaravelAuthProvider resolves a Redline identity from your logged-in User; LaravelGuardProvider injects the widget and dashboard for authenticated users. There is no separate Redline login to build.
  5. Look here first: config/redline.php (path prefix, features, auth providers, sanitizer, mail views), routes/redline.php (the v2 wire contract), redline-app/contracts/mcp.md (MCP tool contract), docs/06-guards.md (guard/404 semantics), and the published widget Blade view.
  6. Two first use cases. For the dashboard: log in as a developer, open a report, PATCH /report/{report}/priority to high, set due_at, and POST /report/{report}/member with a user_ids array from GET /user — that exercises auth, roles, priorities, due dates, members, and serialization in one pass. For agents: php artisan redline:enable mcp, php artisan redline:update, then php artisan redline:mcp [email protected] --name=claude to mint a token and get copy-paste config for Claude Code/Codex/Cursor/VS Code/Gemini CLI. Point the agent at {redline.path}/api/mcp and ask it to report_list then report_update_status.

Implementation Patterns

Feature flags are the new deployment contract. GET /bootstrap only advertises enabled features, so drive your widget/UI gating off the bootstrap payload rather than assuming a capability exists. Treat REDLINE_FEATURES as environment-specific config: staging with mcp on and production with it off is a legitimate setup, but then your docs and onboarding must say so.

MCP is a thin, permissioned façade over the same domain rules. Eight tools: report_list, report_get, screenshot_get, comment_list, user_list (read) and report_create, comment_create, report_update_status (write). Writes inherit the dashboard's rules — sanitized HTML, role permissions, status transitions, new-report mail — so you don't need a parallel authorization model. What you do need is a policy on which human's token an agent gets: mint a developer token for triage bots, a lower-privilege one for read-only assistants.

Token lifecycle is CLI-only. Mint via php artisan redline:mcp (interactive) or --user=/--name= for scripts; audit with --list; revoke with --revoke=, --revoke-all, or per-user. Tokens are rlm_-prefixed, accepted only as Authorization: Bearer, never expire, and are invalidated by a password change — but not by logout. There is no UI to revoke them, so put revocation in your offboarding runbook next to password resets.

report_get mutates state unless you ask it not to. Reading a report marks it noticed by default; pass mark_noticed: false (per the MCP contract) when an agent is just surveying. For any "summarize my backlog" workflow, explicitly opt out or your agents will silently clear the new-report queue.

Agent-created reports: send a URL, not a location. report_create derives location from url; the agent supplies element (a precise CSS selector, ≤512 chars, validated against the live page when the agent has a browser) and a viewport-relative pin. Instruct agents to prefer a real selector over a screenshot description — that's what makes the report actionable for a human.

Treat report text as untrusted input to the agent. The MCP server explicitly tells agents that report content is data, not instructions — mirror that in your own system prompts and tool descriptions, and don't let an agent chain report_get straight into shell commands or deployments. Human-authored bodies are the classic injection vector here.

Member assignment is a set operation, not a toggle. Both POST and DELETE /report/{report}/member take user_ids arrays; send the full desired set or computed deltas. Removal is special: developer+ and the report author can remove anyone, but any member can remove themselves. Agents cannot assign members yet (no MCP tool) — route that through the HTTP API from your own client code.

Treat the author and members as disjoint. The author is never a member; posting the author's id is a deliberate silent no-op, and member reads exclude the author. Filter the author out of pickers and don't render an "assign myself" affordance for owners.

Ownership + claim workflow. noticed → progress auto-assigns the acting user when eligible (approved, non-guest). Let your own "claim" button fall through to that transition instead of re-implementing assignment — otherwise you double-assign or assign ineligible users. Note that report_update_status over MCP triggers the same behavior for the token's user.

Priorities and due dates are just report columns. Priority is low|normal|high|critical, defaults to normal, and is patched via PATCH /report/{report}/priority (developer+ or owner). Due dates serialize as RFC3339 Z and are filterable/sortable via the grammar.

Handle the email PII boundary explicitly. Non-developer roles get 422 for include[]=email and filter[email]=… — an intentional denial, not a missing key. Branch your request builder on role instead of stripping keys afterwards; search matches names only for non-developers while ORing emails for developer+. filter[author.email:like] on /report stays rejected for everyone. The same role gates apply to user_list over MCP.

Emails are normalized. Trim + lowercase on write, case-insensitive on lookup. Send what the user typed; apply the same normalization to any mirror table or your joins drift.

Still on wire contract v2. has_media is gone — use filter[screenshot:exists]=1 and filter[video:exists]=1 in query builders, saved views, and client presets. user_agent is no longer serialized. Verify GET /{path}/api/bootstrap reports "version": 2 (and the feature list you expect) when debugging odd widget behavior.

Upgrade mechanics as deployment steps. The post-package-update Composer hook applies migrations (with a pre-migration backup) and re-publishes assets; StorageProvider::ensureSchema() no longer re-runs per-migration guards on boot. In CI prefer composer update + the hook, or run redline:update --dry-run to preview. Where the package version is pinned, run redline:update explicitly in the release step so migrations and asset publishes aren't skipped.

User administration via CLI. redline:user promotes existing users and edits name/email, which is the fastest way to seed a developer in fresh environments without touching the API.

Gotchas and Tips

  • Laravel 11 is a hard blocker. Redline v0.3.0 requires Laravel 12.41.1+/13. Sequence the Laravel upgrade and the Redline upgrade as separate deploys, or you'll be debugging two failure domains at once.
  • Features are opt-in and fail silent-then-loud. Forgetting REDLINE_FEATURES turns everything off — including screenshots and comments — with no error, so the symptom is "the widget lost its buttons." A typo'd feature name, conversely, hard-fails the app; if you hit that after a config change, php artisan config:clear. Remember redline:update shows what's currently enabled — check it as a post-deploy smoke test.
  • REDLINE_DISABLED → REDLINE_FEATURES is a rename, not an addition. Old env vars are ignored. Audit every environment's .env, Dockerfile, Helm values, and Terraform-managed config; a missed environment ships with Redline effectively inert.
  • 404 can now mean "guard inactive," not "route missing." The guard is evaluated on every request for the API, dashboard shell, and MCP route, so route:cache/optimize can no longer leak Redline on hosts where it should be off. If Redline vanished after a deploy, check the guard before checking routes. Caveat: LaravelGuardProvider can't answer before the session stack runs, so its API/MCP surface is token-gated per request instead of 404 — see docs/06-guards.md.
  • route:cache previously dropped Redline routes entirely. That's fixed, but cached routes from before the upgrade may still be stale — redline:update clears config/view/route caches; your deploy pipeline may need to as well.
  • MCP tokens are long-lived secrets. They never expire, work only as a Bearer header (no query-string form), survive logout, and die only on password change or explicit CLI revocation. Don't commit them to repo-local agent config, rotate via --revoke/--revoke-all on offboarding, and prefer one named token per agent per person (--name=) so --list stays legible.
  • MCP capability gaps to design around. No member-assignment tool, so triage flows that need ownership must still go through the HTTP API. Plan agent scope around the eight tools rather than assuming parity with the dashboard.
  • report_get marks reports noticed by default. Agents that "just read" will clear your new-report queue. Make mark_noticed: false the default in your prompt templates and only allow the mutating variant in explicit triage flows.
  • Report bodies are attacker-controllable text for agents. The server warns agents to treat content as data. Keep that guidance in your own prompts, and avoid agent tool chains that turn report text into commands.
  • POST /report now returns 403 for unauthorized users (previously a server error). That makes it safe to branch on: 403 = role problem, 422 = validation problem. Don't retry 403s.
  • Debugging 403s on member/priority writes: it's "developer+ or owner" for priority, "developer+ or author" for member writes, and self-removal is always allowed. Log the acting user's role and report ownership before chasing routing.
  • Storage backend consolidation removed an extension point. StorageProvider is the single concrete SQLite implementation; the old Orbit/FileStorageProvider backend and the Base/Database model layers are gone. Extend via container bindings or wrap the API.
  • Migrations are implicit on package update. The post-package-update hook plus unguarded ensureSchema() means a composer update in a read-only replica, or in a container lacking write access to the SQLite path, can fail or write a backup where you didn't expect. Pin the SQLite path and permissions in config/database.php and config/redline.php.
  • redline:update --force never overwrites customized config or mail views. A feature, but it means new v0.3.0 defaults (features block, MCP settings) won't land once you've customized. Diff your published config against the package's config/redline.php after upgrading.
  • Media URLs no longer carry a JWT (cookie/CSRF auth since v0.2.0). Anything embedding media from another origin, in email, or in a PDF renderer will break — proxy it or attach the session cookie. Relevant again if agents link screenshot_get output into external tooling.
  • Pending accounts fail closed. Pending users get 401, approval bumps token_version so pre-approval tokens die, and login returns 202 without a token. Treat 202 as "awaiting approval" and never cache tokens across the approval boundary.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib