Send signed outgoing webhooks

Fed by the records themselves, delivered only to public HTTPS addresses
checked at every attempt, retried, and switched off after repeated failures.
A submitter's details travel only to webhooks that opted into them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 09:42:39 +02:00
parent f93775e549
commit 9bdbf834f6
23 changed files with 1325 additions and 0 deletions

View File

@@ -5,9 +5,13 @@ declare(strict_types=1);
namespace App\Providers;
use App\Auth\PireonTokenGuard;
use App\Models\Application;
use App\Models\ReviewComment;
use App\Models\Revision;
use App\Services\Git\GitManager;
use App\Services\Pireon\PireonClient;
use App\Services\Pireon\TokenStore;
use App\Support\Webhooks\Webhooks;
use Illuminate\Auth\Events\Logout;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Database\Eloquent\Model;
@@ -36,6 +40,12 @@ class AppServiceProvider extends ServiceProvider
public function boot(): void
{
// Outgoing webhooks, fed by the records themselves so the panel, the
// API and a batch all announce the same things the same way.
Application::created(fn (Application $application) => Webhooks::applicationReceived($application));
Revision::created(fn (Revision $revision) => Webhooks::revisionRecorded($revision));
ReviewComment::created(fn (ReviewComment $comment) => Webhooks::reviewRecorded($comment));
// Backs the "api" guard declared in config/auth.php.
Auth::viaRequest('pireon', fn (Request $request) => $this->app
->make(PireonTokenGuard::class)($request));

View File

@@ -20,6 +20,7 @@ use App\Models\Talk;
use App\Models\Technology;
use App\Models\Testimonial;
use App\Models\User;
use App\Models\Webhook;
use App\Policies\ApplicationPolicy;
use App\Policies\CallPolicy;
use App\Policies\CategoryPolicy;
@@ -37,6 +38,7 @@ use App\Policies\TalkPolicy;
use App\Policies\TechnologyPolicy;
use App\Policies\TestimonialPolicy;
use App\Policies\UserPolicy;
use App\Policies\WebhookPolicy;
use App\Support\Permissions;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
@@ -63,6 +65,7 @@ class AuthServiceProvider extends ServiceProvider
Gate::policy(Repository::class, RepositoryPolicy::class);
Gate::policy(User::class, UserPolicy::class);
Gate::policy(Role::class, RolePolicy::class);
Gate::policy(Webhook::class, WebhookPolicy::class);
// The one place a permission is granted — spatie's own gate check is
// switched off (config/permission.php) so nothing answers before this.