trypost/app
Paulo Castellano c871edf144 refactor: split MediaAttacher into orchestrator + downloader + safety guard
The previous MediaAttacher had ~5 responsibilities crammed in one class
(URL validation, HTTP fetch, streaming, MIME check, Storage write,
post.media merge) plus an `if ($app->runningUnitTests()) return true`
inside the SSRF guard — production code that knew about test mode.

Split into three:

- UrlSafetyGuard (interface) + DnsUrlSafetyGuard (default impl). The
  full SSRF check is now isolated and unit-testable in
  tests/Unit/Services/Post/DnsUrlSafetyGuardTest. Tests bind a permissive
  guard in tests/TestCase::setUp so feature tests using Http::fake() with
  synthetic hosts (cdn.example.com) still work — the runningUnitTests()
  check inside production code is gone.

- MediaDownloader: takes a URL, returns a temp file + MIME or null. Uses
  Http::sink with a Guzzle progress callback that throws once maxBytes
  is exceeded, so we abort mid-stream without buffering the body in PHP
  memory (the previous chunk loop was append-to-string which defeated
  the whole point of streaming).

- MediaAttacher: pure orchestrator. Calls MediaDownloader, validates the
  MIME against the post's enabled platforms, persists via Storage::putFileAs,
  appends the Media record under a row lock. Drops from 275 to ~190 lines
  with zero responsibility overlap.

The IO contract (`null` on failure, `['path','mime','bytes']` on success)
keeps MediaAttacher free of the temp-file lifecycle on the happy path —
ownership is documented in MediaDownloader's PHPDoc and the orchestrator
unlinks via try/finally in processOne().

Bind the interface in AppServiceProvider so production resolves
DnsUrlSafetyGuard automatically; tests override it.

7 new unit tests cover the SSRF cases (loopback, RFC1918, link-local,
zero/broadcast, IPv6 loopback/ULA/link-local, plus a public-IP positive
test). The 14 existing AttachMedia feature tests stay green.
2026-05-04 13:45:43 -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 refactor: move workspace tenancy check on Post into PostPolicy 2026-05-04 13:20:52 -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 refactor: move workspace tenancy check on Post into PostPolicy 2026-05-04 13:20:52 -03:00
Providers refactor: split MediaAttacher into orchestrator + downloader + safety guard 2026-05-04 13:45:43 -03:00
Rules refactor: derive sibling key in content-type rules without regex 2026-05-04 13:06:13 -03:00
Services refactor: split MediaAttacher into orchestrator + downloader + safety guard 2026-05-04 13:45:43 -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