diff --git a/app/Rules/ContentTypeMatchesPlatform.php b/app/Rules/ContentTypeMatchesPlatform.php index 56e945c24..fd0da853d 100644 --- a/app/Rules/ContentTypeMatchesPlatform.php +++ b/app/Rules/ContentTypeMatchesPlatform.php @@ -40,7 +40,7 @@ public function validate(string $attribute, mixed $value, Closure $fail): void $parentKey = Str::beforeLast($attribute, '.'); $accountId = data_get($this->data, $parentKey.'.social_account_id'); - if (! $accountId) { + if (! $accountId || ! Str::isUuid((string) $accountId)) { return; } diff --git a/tests/Unit/Rules/ContentTypeMatchesPlatformTest.php b/tests/Unit/Rules/ContentTypeMatchesPlatformTest.php index c3fe5352a..e5a6dedda 100644 --- a/tests/Unit/Rules/ContentTypeMatchesPlatformTest.php +++ b/tests/Unit/Rules/ContentTypeMatchesPlatformTest.php @@ -67,6 +67,14 @@ function runMatchesPlatformRule(string $contentType, ?string $accountId, array $ expect(runMatchesPlatformRule(ContentType::XPost->value, null))->toBe([]); }); +test('skips validation without querying the database when social_account_id is not a uuid', function () { + // Regression: a non-uuid social_account_id (e.g. an MCP client sending a + // placeholder string) must not reach SocialAccount::find(), which throws + // a QueryException on Postgres for invalid uuid input instead of + // returning no rows. + expect(runMatchesPlatformRule(ContentType::XPost->value, 'threads-account'))->toBe([]); +}); + test('skips validation when content_type is not a known enum value', function () { $workspace = Workspace::factory()->create(); $linkedin = SocialAccount::factory()->create([