feat: wire Resend mail and Cloudflare R2 storage (#4)
Add production provider deps/config so transactional email and CMS media can use Resend and a dedicated r2 disk with custom-domain URLs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: CMS public image uploads select production object storage disk
|
||||
|
||||
Public content image uploads (Filament FileUpload via `PublicImageUploadRules`) MUST store files on the disk matching the configured default filesystem (SPEC §6.4). When `FILESYSTEM_DISK` is `r2`, uploads MUST use the `r2` disk. When `FILESYSTEM_DISK` is `s3`, uploads MUST use the `s3` disk. Otherwise uploads MUST use the local `public` disk.
|
||||
|
||||
#### Scenario: Production R2 disk is used for CMS uploads
|
||||
|
||||
- **WHEN** `FILESYSTEM_DISK=r2`
|
||||
- **THEN** `PublicImageUploadRules::disk()` MUST return `r2`
|
||||
|
||||
#### Scenario: Legacy S3 default still supported
|
||||
|
||||
- **WHEN** `FILESYSTEM_DISK=s3`
|
||||
- **THEN** `PublicImageUploadRules::disk()` MUST return `s3`
|
||||
|
||||
#### Scenario: Local development uses public disk
|
||||
|
||||
- **WHEN** `FILESYSTEM_DISK` is `local`, unset, or any value other than `r2`/`s3`
|
||||
- **THEN** `PublicImageUploadRules::disk()` MUST return `public`
|
||||
@@ -0,0 +1,44 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Cloudflare R2 is available as dedicated filesystem disk
|
||||
|
||||
The system SHALL provide an `r2` filesystem disk using Laravel's S3-compatible driver pointed at Cloudflare R2 (SPEC §6.4, §9.1, §15.4). Configuration MUST use explicit `R2_*` environment variables: `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`, `R2_BUCKET`, `R2_ENDPOINT`, and `R2_URL`.
|
||||
|
||||
#### Scenario: R2 disk is defined in filesystem config
|
||||
|
||||
- **WHEN** the application boots
|
||||
- **THEN** `config('filesystems.disks.r2')` MUST exist
|
||||
- **AND** the disk driver MUST be `s3`
|
||||
- **AND** credentials MUST resolve from `R2_ACCESS_KEY_ID` and `R2_SECRET_ACCESS_KEY`
|
||||
|
||||
#### Scenario: R2 endpoint uses path-style addressing
|
||||
|
||||
- **WHEN** the `r2` disk is configured
|
||||
- **THEN** `use_path_style_endpoint` MUST be `true`
|
||||
- **AND** `endpoint` MUST resolve from `R2_ENDPOINT`
|
||||
|
||||
#### Scenario: Public URLs use custom domain
|
||||
|
||||
- **WHEN** a file is stored on the `r2` disk with public visibility
|
||||
- **THEN** generated URLs MUST use `R2_URL` as base
|
||||
- **AND** MUST NOT require signed URLs for browser-facing media
|
||||
|
||||
### Requirement: Production default filesystem disk is R2
|
||||
|
||||
Production deployments MUST set `FILESYSTEM_DISK=r2` so application code using the default disk stores files on R2.
|
||||
|
||||
#### Scenario: Default disk resolves to R2 in production
|
||||
|
||||
- **WHEN** `FILESYSTEM_DISK=r2` is set
|
||||
- **THEN** `config('filesystems.default')` MUST be `r2`
|
||||
|
||||
#### Scenario: Local development keeps local disk
|
||||
|
||||
- **WHEN** `FILESYSTEM_DISK` is unset or set to `local`/`public` in development
|
||||
- **THEN** the default disk MUST NOT require R2 credentials to boot
|
||||
|
||||
#### Scenario: Tests do not call R2
|
||||
|
||||
- **WHEN** the test suite runs
|
||||
- **THEN** tests MUST use `Storage::fake('r2')` or local fakes
|
||||
- **AND** no live HTTP request to Cloudflare R2 MUST occur during CI
|
||||
@@ -0,0 +1,32 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Production transactional email uses Resend
|
||||
|
||||
The system SHALL support Resend as the production mail transport via Laravel's native `resend` mailer (SPEC §9.1, §15.4). The Resend API key MUST be read from `RESEND_API_KEY` through `config/services.php`. Production deployments MUST set `MAIL_MAILER=resend` when transactional email is enabled.
|
||||
|
||||
#### Scenario: Resend mailer is configured
|
||||
|
||||
- **WHEN** the application boots with valid configuration
|
||||
- **THEN** a `resend` mailer MUST exist in `config/mail.php`
|
||||
- **AND** `config('services.resend.key')` MUST resolve from `RESEND_API_KEY`
|
||||
|
||||
#### Scenario: Local development uses safe mail default
|
||||
|
||||
- **WHEN** `APP_ENV` is `local` and `MAIL_MAILER` is unset
|
||||
- **THEN** the default mailer MUST be `log`
|
||||
- **AND** no outbound email MUST be sent to external providers
|
||||
|
||||
#### Scenario: Tests do not call Resend
|
||||
|
||||
- **WHEN** the test suite runs
|
||||
- **THEN** `MAIL_MAILER` MUST be `array` (or tests MUST use `Mail::fake`)
|
||||
- **AND** no live HTTP request to Resend MUST occur during CI
|
||||
|
||||
### Requirement: Global from address is configurable
|
||||
|
||||
The system SHALL read the global sender address and name from `MAIL_FROM_ADDRESS` and `MAIL_FROM_NAME` (SPEC §15.4).
|
||||
|
||||
#### Scenario: From address applied to outbound mail
|
||||
|
||||
- **WHEN** the application sends mail through the configured mailer
|
||||
- **THEN** the message MUST use the configured from address and name
|
||||
Reference in New Issue
Block a user