diff --git a/routes/api.php b/routes/api.php index a12d8946..46f008e2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,6 +11,9 @@ use Illuminate\Support\Facades\Route; Route::prefix('v1') ->middleware(['auth:sanctum', EnsureApiUserIsActive::class, EnsureApiTokenRateLimit::class]) + // Controller erwarten int-IDs — nicht-numerische Werte (z. B. vergessene + // Platzhalter wie „PM_ID") sollen 404 statt TypeError/500 ergeben. + ->where(['pressRelease' => '[0-9]+', 'pressReleaseImage' => '[0-9]+', 'company' => '[0-9]+']) ->group(function (): void { Route::apiResource('press-releases', PressReleaseController::class) ->parameters(['press-releases' => 'pressRelease']); diff --git a/routes/legacy-api.php b/routes/legacy-api.php index 84f8782d..fb65374a 100644 --- a/routes/legacy-api.php +++ b/routes/legacy-api.php @@ -32,6 +32,9 @@ use Illuminate\Support\Facades\Route; Route::prefix('service') ->name('legacy-service.') ->middleware(['auth:sanctum', EnsureApiUserIsActive::class, EnsureApiTokenRateLimit::class]) + // Nicht-numerische IDs fallen in den 410-Catch-all statt auf einen + // TypeError im Controller zu laufen. + ->where(['pressRelease' => '[0-9]+', 'company' => '[0-9]+']) ->group(function (): void { // Paritäts-Controller (10.07.2026, dev/release/api-legacy-paritaet.md): // die 5 real genutzten Alt-Calls (connektar-Flow) verhaltensgleich — diff --git a/tests/Feature/Api/V1/PressReleaseSubmitApiTest.php b/tests/Feature/Api/V1/PressReleaseSubmitApiTest.php index 881a2e65..0744e0a6 100644 --- a/tests/Feature/Api/V1/PressReleaseSubmitApiTest.php +++ b/tests/Feature/Api/V1/PressReleaseSubmitApiTest.php @@ -214,3 +214,17 @@ test('api submit records the declared ai grade as binding confirmation', functio // Audit-Trail: der Submit protokolliert die Deklaration versioniert. ->and($fresh->aiDeclarations()->count())->toBe(1); }); + +test('api routes respond 404 instead of 500 for non-numeric press release ids', function () { + /** @var TestCase $this */ + $user = User::factory()->create(); + + Sanctum::actingAs($user, ['press-releases:write']); + + // Vergessener Postman-Platzhalter wie „PM_ID" darf nicht als String in + // die int-typisierten Controller-Parameter laufen (TypeError/500). + $this->postJson('/api/v1/press-releases/PM_ID/submit', ['ai_text_declaration' => 'none']) + ->assertNotFound(); + $this->getJson('/api/v1/press-releases/PM_ID') + ->assertNotFound(); +});