trypost/app
Paulo Castellano c1418c9d21 fix: address PR review findings — publish, REST store, SSRF, race
Code-review surfaced two correctness bugs and a security gap that
needed to land before merging.

- UpdatePost::execute disabled every platform when called without
  a `platforms` key. PublishPostTool relied on that path, so every
  publish-via-MCP queued a job whose handler then found nothing
  enabled to publish to. Wrap the platform toggle in
  `Arr::has($data, 'platforms')` (matches the existing label_ids
  guard a few lines up). Add a regression assertion to
  `PostPublishToolTest::publish post immediate dispatches PublishPost
  job` that the previously-enabled platform stays enabled.

- StorePostRequest declared rules for only `platforms`,
  `scheduled_at`, and `status`. `validated()` then stripped
  `content`, `media`, and `label_ids`, so REST `POST /api/posts`
  silently created empty drafts. Added rules for content / media /
  label_ids (with workspace-scoped `Rule::exists` for labels) and
  dropped the unused `status` field — REST callers transition state
  via `PUT /posts/{id}`. Removed the dead `platforms.*.content`
  rule. Added a feature test that asserts content + media + labels
  roundtrip on create, plus a regression that an `is_active=false`
  social_account is rejected at validation.

- CreatePost::execute now syncs label_ids itself so REST and MCP
  share the behavior. Removed the duplicate sync from CreatePostTool.

- MCP UpdatePostTool didn't scope `platforms.*.id` to the post being
  updated, drifting from the REST UpdatePostRequest which adds
  `Rule::exists('post_platforms','id')->where('post_id', ...)`. Now
  it loads the post first (failing fast with `Post not found.` if
  the workspace check rejects), then uses the same Rule::exists.

- MediaAttacher fetched any URL the caller passed, including
  loopback / link-local / private targets — classic SSRF pivot.
  Now `isPublicHttpUrl` rejects non-http(s) schemes, restricted IP
  ranges, and DNS hostnames whose A/AAAA records resolve into those
  ranges (covers DNS rebinding). Bypassed under
  `app()->runningUnitTests()` so `Http::fake()` keeps working.
  Streaming the response body lets us abort early once we exceed
  MAX_BYTES instead of buffering the full payload first; redirects
  are disabled so a 200→302 trick can't bypass the host check.

- The `media[]` JSON column had a lost-update race in
  `attachFromUrls`: read `$post->media`, mutate in PHP, write back.
  Two concurrent calls clobbered each other. Now wrapped in a
  transaction with `lockForUpdate()`.

- ESLint: `resources/js/actions/**` and `resources/js/routes/**`
  are auto-generated by Wayfinder on every build. Their import
  order matches PHP scan order, not alphabetical, so import/order
  fought eslint-fix forever. Added them to ignores.
2026-05-04 12:16:39 -03:00
..
Actions fix: address PR review findings — publish, REST store, SSRF, race 2026-05-04 12:16:39 -03:00
Ai feat: transition AI usage from feature-based limits to a centralized monthly credit system with token tracking. 2026-05-03 19:36:26 -03:00
Broadcasting feat: replace legacy AI assistant with modular post content generation, review, and template management system 2026-05-03 09:36:50 -03:00
Concerns refactor: settings redesign, Spanish translations, language system, strict_types 2026-03-30 00:20:43 -03:00
Console/Commands feat: transition AI usage from feature-based limits to a centralized monthly credit system with token tracking. 2026-05-03 19:36:26 -03:00
DataTransferObjects feat: add PostCommentCreated broadcast event 2026-04-15 20:11:36 -03:00
Enums feat: complete create + publish post flow via MCP and REST API 2026-05-04 08:12:28 -03:00
Events feat: add image title and body fields to AI post creation and register PostTemplateSeeder in local environments 2026-05-03 10:06:02 -03:00
Exceptions feat: @mentions in comments, AI Action layer + MCP tools, settings tabs 2026-05-01 20:59:03 -03:00
Features feat: transition AI usage from feature-based limits to a centralized monthly credit system with token tracking. 2026-05-03 19:36:26 -03:00
Helpers fix: correct Upload.php filename case for Linux CI 2026-03-31 12:01:48 -03:00
Http fix: address PR review findings — publish, REST store, SSRF, race 2026-05-04 12:16:39 -03:00
Jobs feat: transition AI usage from feature-based limits to a centralized monthly credit system with token tracking. 2026-05-03 19:36:26 -03:00
Listeners feat: redesign billing, onboarding, sidebar, and settings architecture 2026-04-15 00:33:38 -03:00
Mail feat: @mentions in comments, AI Action layer + MCP tools, settings tabs 2026-05-01 20:59:03 -03:00
Mcp fix: address PR review findings — publish, REST store, SSRF, race 2026-05-04 12:16:39 -03:00
Models refactor: standardize post platform data structure and simplify display logic in PostResource 2026-05-03 22:11:58 -03:00
Policies feat: add duplicate post functionality and migrate LinkedIn analytics to the /rest/ API. 2026-05-03 22:37:51 -03:00
Providers refactor: replace Inertia-based OAuth authorization view with a static Blade template and remove unused language files. 2026-05-03 20:26:09 -03:00
Rules feat: complete create + publish post flow via MCP and REST API 2026-05-04 08:12:28 -03:00
Services fix: address PR review findings — publish, REST store, SSRF, race 2026-05-04 12:16:39 -03:00
Socialite refactor: centralize social API base URLs into the configuration file to improve maintainability and environment flexibility 2026-05-02 13:49:20 -03:00
Support feat: @mentions in comments, AI Action layer + MCP tools, settings tabs 2026-05-01 20:59:03 -03:00