feat(api): expose webhook secret routes

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 18:32:39 +00:00
parent 3b26a15048
commit 69beb451b5
2 changed files with 64 additions and 0 deletions

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
use Core\Api\Controllers\Api\UnifiedPixelController;
use Core\Api\Controllers\Api\EntitlementApiController;
use Core\Api\Controllers\Api\SeoReportController;
use Core\Api\Controllers\Api\WebhookSecretController;
use Core\Api\Controllers\McpApiController;
use Core\Api\Middleware\PublicApiCors;
use Core\Mcp\Middleware\McpApiKeyAuth;
@ -57,6 +58,41 @@ Route::middleware(['auth.api', 'api.scope.enforce'])
->name('show');
});
// ─────────────────────────────────────────────────────────────────────────────
// Webhook secret rotation (authenticated)
// ─────────────────────────────────────────────────────────────────────────────
Route::middleware(['auth.api', 'api.scope.enforce'])
->prefix('webhooks')
->name('api.webhooks.')
->group(function () {
Route::prefix('social/{uuid}/secret')
->name('social.')
->group(function () {
Route::post('/rotate', [WebhookSecretController::class, 'rotateSocialSecret'])
->name('rotate-secret');
Route::get('/', [WebhookSecretController::class, 'socialSecretStatus'])
->name('status');
Route::delete('/previous', [WebhookSecretController::class, 'invalidateSocialPreviousSecret'])
->name('invalidate-previous');
Route::patch('/grace-period', [WebhookSecretController::class, 'updateSocialGracePeriod'])
->name('grace-period');
});
Route::prefix('content/{uuid}/secret')
->name('content.')
->group(function () {
Route::post('/rotate', [WebhookSecretController::class, 'rotateContentSecret'])
->name('rotate-secret');
Route::get('/', [WebhookSecretController::class, 'contentSecretStatus'])
->name('status');
Route::delete('/previous', [WebhookSecretController::class, 'invalidateContentPreviousSecret'])
->name('invalidate-previous');
Route::patch('/grace-period', [WebhookSecretController::class, 'updateContentGracePeriod'])
->name('grace-period');
});
});
// ─────────────────────────────────────────────────────────────────────────────
// MCP HTTP Bridge (API key auth)
// ─────────────────────────────────────────────────────────────────────────────

View file

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
use Illuminate\Support\Facades\Route;
it('registers webhook secret management routes', function () {
$socialRotate = Route::getRoutes()->getByName('api.webhooks.social.rotate-secret');
$socialStatus = Route::getRoutes()->getByName('api.webhooks.social.status');
$contentRotate = Route::getRoutes()->getByName('api.webhooks.content.rotate-secret');
$contentStatus = Route::getRoutes()->getByName('api.webhooks.content.status');
expect($socialRotate)->not->toBeNull();
expect($socialRotate->uri())->toBe('api/webhooks/social/{uuid}/secret/rotate');
expect($socialRotate->methods())->toContain('POST');
expect($socialStatus)->not->toBeNull();
expect($socialStatus->uri())->toBe('api/webhooks/social/{uuid}/secret');
expect($socialStatus->methods())->toContain('GET');
expect($contentRotate)->not->toBeNull();
expect($contentRotate->uri())->toBe('api/webhooks/content/{uuid}/secret/rotate');
expect($contentRotate->methods())->toContain('POST');
expect($contentStatus)->not->toBeNull();
expect($contentStatus->uri())->toBe('api/webhooks/content/{uuid}/secret');
expect($contentStatus->methods())->toContain('GET');
});