miraheze/ts-portal
A Laravel/PHP package from Miraheze for the TS Portal. It provides the portal’s PHP components and integration points, making it easy to add TS Portal functionality to a Laravel application via Composer.
Architecture fit. TSPortal is not a drop-in library — it's a full Laravel application (Miraheze's Trust & Safety portal) that we would consume as a service, a fork, or a reference implementation. Fit therefore depends on the target: as an application to deploy, it aligns with a standard Laravel 13 / PHP 8.4+ stack and a Socialite-based MediaWiki OAuth identity path; as a package to embed, it does not fit — there is no published contract, no semver surface for the domain layer, and the release notes are application-level (views, models, HTTP client). Treat it as a forkable app, not a dependency.
Integration feasibility. Moderate-to-high effort. The v37 delta is small in surface area but two items carry real weight: (1) two security fixes, one of which (GHSA-4835-jf76-3g69, underage check) sits directly on an access-control decision path in a trust-and-safety context; (2) guzzlehttp/guzzle 7.10.0 → 8.2.0 is a major version jump, and Guzzle is the transport for outbound HTTP (OAuth token exchange via Socialite, any webhook/API clients). Laravel 13.2.0 → 13.36.0, Socialite 5.26 → 5.31, PHPUnit 13.0.5 → 13.4.2, Mockery, and Tinker are routine minor/patch bumps with low risk.
Technical risk.
hash_equals fix (GHSA-86xc-5q56-p5pg) confirms the API writekey comparison was previously vulnerable to a timing oracle. Any deployment on ≤ v36 should assume the writekey may have been probed and must rotate it, not just patch.WithoutTimestamps attribute changes how created_at/updated_at are managed on affected models. On a T&S platform where activity timestamps are evidentiary, silently dropping timestamp writes on even one model is a compliance-relevant regression.laravel/framework 13.36.0 within the same major; contrast/accessibility change on the home view is cosmetic-positive.Key questions.
WithoutTimestamps, and does any of them feed an audit/evidence trail?Stack fit. Laravel 13.x, PHP 8.4+, MySQL/MariaDB, Redis for sessions/queues, Socialite with the MediaWiki provider for OAuth, and a container-based deploy. Nothing in v37 changes the runtime envelope; the only environmental sensitivity is the Guzzle major.
Migration path. Do not composer update this in place on a production branch.
hash_equals changes independently so they can ship ahead of the dependency churn.WithoutTimestamps change last, after confirming no audit model is affected.Compatibility. Verify our own Guzzle consumers against 8.x semantics, including any custom middleware and HandlerStack configuration; verify Socialite 5.31 still resolves the MediaWiki provider we use. PHPUnit 13.4.2 is test-only. Confirm the framework bump does not pull a transitive requirement that conflicts with pinned packages.
Sequencing. Security patch + key rotation (day 0–2) → retroactive underage-gate audit (day 0–5, parallel) → Guzzle 8 / dependency bundle in staging (week 1) → production dependency cutover (week 2) → timestamp-attribute verification and home-page contrast check folded into the same release QA rather than a separate deploy.
Maintenance. Upstream is a volunteer-run Miraheze project; release cadence is irregular and version numbers are coarse (v37 implies a long tail). The security posture is a positive signal — advisories are published with GHSA identifiers and fixed promptly — but bus factor and long-term support guarantees are weak. Budget for a fork-and-maintain posture, not a consume-and-forget one.
Support. No commercial support; escalation is GitHub issues plus Miraheze's own operational channel. We should own an internal patch queue and be prepared to backport security fixes ourselves if upstream stalls.
Scaling. No scaling-relevant change in v37. The application's profile is request/response with queue-backed jobs and an outbound HTTP dependency; Guzzle 8 has no throughput implications. Watch the outbound HTTP path if Socialite token exchange becomes a hot path under login bursts.
Failure modes. (a) Guzzle 8 breaks an outbound integration silently at runtime rather than at install — mitigate with contract tests against each external endpoint. (b) Writekey rotation without a dual-key window locks out automated writers — coordinate with every API consumer. (c) WithoutTimestamps producing null or stale timestamps in reporting, discovered late. (d) Upstream abandonment mid-cycle, leaving us pinned to a version with unpublished fixes.
Ramp-up. Low for a Laravel-fluent engineer — conventional structure, Socialite, standard Blade views. The real ramp-up cost is domain knowledge: trust-and-safety case lifecycle, the underage/access-control rules, and what the writekey actually authorizes. Allocate a domain walkthrough alongside the technical onboarding; a patch applied to the wrong model or a rotation to the wrong credential is the likely first incident, not a framework mistake.
How can I help you explore Laravel packages today?