CmsMediaStorageSpec.java
package com.cloudforge.core.interfaces;
import java.util.Map;
/**
* Media storage configuration for CMS platforms.
*
* <p>Defines S3 offloading capabilities and plugin configurations for
* CMS media uploads. When enabled, media files are stored in S3 instead
* of the local filesystem, enabling:</p>
* <ul>
* <li>Horizontal scaling (multiple container instances)</li>
* <li>CDN integration via CloudFront</li>
* <li>Reduced EFS/EBS storage costs</li>
* <li>Better performance through S3's distributed storage</li>
* </ul>
*
* <h2>Usage Example:</h2>
* <pre>{@code
* if (spec instanceof CmsMediaStorageSpec mediaSpec) {
* if (mediaSpec.isS3OffloadingEnabled()) {
* String bucket = mediaSpec.getMediaBucketName();
* Map<String, String> env = mediaSpec.getS3PluginEnvironment();
* }
* }
* }</pre>
*
* <h2>4.0 migration intent</h2>
* <p>This is a CMS compatibility/binding contract, not a CMS-only infrastructure model. During
* the 4.0 migration, its shared storage and delivery concerns are adapted to named typed
* requirements such as {@code storage.media} and an optional delivery/CDN policy. Provider
* selection, bucket naming, IAM, encryption, public-access blocking, retention, versioning,
* target support, entitlement restrictions, and compliance evidence are resolved by the platform,
* not by this interface or a CMS plugin.</p>
*
* <p>Methods that describe how a particular CMS configures its S3/offload extension remain
* application-owned binding behavior. New application plugins should request reusable object
* storage and delivery capabilities directly; existing implementations remain supported through
* the 4.0 compatibility adapter until their regression coverage proves equivalent behavior.</p>
*
* @since 3.1.0
* @see CmsSpec
*/
public interface CmsMediaStorageSpec {
/**
* Returns whether S3 media offloading is enabled.
*
* <p>When enabled, media uploads are stored in S3 instead of
* local filesystem. This requires proper IAM permissions and
* plugin configuration.</p>
*
* @return true if S3 offloading is enabled
*/
boolean isS3OffloadingEnabled();
/**
* Returns the S3 bucket name for media storage.
*
* <p>This bucket should be provisioned with appropriate policies:</p>
* <ul>
* <li>Block public access enabled</li>
* <li>Versioning enabled for recovery</li>
* <li>Lifecycle rules for old version cleanup</li>
* <li>CORS configuration for browser uploads</li>
* </ul>
*
* @return S3 bucket name for media storage
*/
String getMediaBucketName();
/**
* Returns the S3 key prefix for media files.
*
* <p>Organizes media files within the bucket. Common patterns:</p>
* <ul>
* <li>"uploads/" - WordPress standard</li>
* <li>"media/" - Generic pattern</li>
* <li>"pub/media/" - Magento pattern</li>
* </ul>
*
* @return S3 key prefix (default: "uploads/")
*/
default String getMediaKeyPrefix() {
return "uploads/";
}
/**
* Returns the S3 region for the media bucket.
*
* <p>Should match the deployment region for optimal performance.</p>
*
* @return AWS region (e.g., "us-east-1")
*/
String getMediaBucketRegion();
/**
* Returns environment variables for S3 plugin configuration.
*
* <p>CMS-specific environment variables for configuring S3 media plugins:</p>
*
* <p><b>WordPress (WP Offload Media):</b></p>
* <ul>
* <li>AS3CF_SETTINGS - JSON configuration</li>
* <li>WP_OFFLOAD_MEDIA_BUCKET - Bucket name</li>
* <li>WP_OFFLOAD_MEDIA_REGION - AWS region</li>
* </ul>
*
* <p><b>Magento:</b></p>
* <ul>
* <li>AWS_S3_BUCKET - Bucket name</li>
* <li>AWS_S3_REGION - AWS region</li>
* <li>AWS_S3_PREFIX - Key prefix</li>
* </ul>
*
* <p><b>Drupal (S3FS):</b></p>
* <ul>
* <li>S3FS_BUCKET - Bucket name</li>
* <li>S3FS_REGION - AWS region</li>
* </ul>
*
* @return map of environment variable key-value pairs
*/
Map<String, String> getS3PluginEnvironment();
/**
* Returns whether to delete local files after S3 upload.
*
* <p>When true, files are removed from local storage after
* successful S3 upload. This saves local storage but requires
* reliable S3 connectivity.</p>
*
* <p>Recommended settings:</p>
* <ul>
* <li>Fargate: true (ephemeral storage)</li>
* <li>EC2 with EFS: true (saves EFS costs)</li>
* <li>EC2 with EBS: false (keep local backup)</li>
* </ul>
*
* @return true to delete local files after upload (default: false)
*/
default boolean deleteLocalAfterUpload() {
return false;
}
/**
* Returns the CloudFront URL for media if CDN is enabled.
*
* <p>When a CloudFront distribution is configured for the media bucket,
* this URL is used for serving media files to visitors.</p>
*
* @return CloudFront URL (e.g., "https://d1234.cloudfront.net") or null
*/
String getCdnMediaUrl();
/**
* Returns whether to rewrite URLs to use CDN.
*
* <p>When enabled, media URLs in content are rewritten to use
* the CDN domain instead of S3 or local URLs.</p>
*
* @return true to rewrite URLs (default: true if CDN URL is set)
*/
default boolean rewriteUrlsForCdn() {
return getCdnMediaUrl() != null && !getCdnMediaUrl().isEmpty();
}
/**
* Returns the allowed MIME types for media uploads.
*
* <p>Used for S3 bucket policy and upload validation.
* Empty list means all types are allowed.</p>
*
* @return list of allowed MIME types, or empty for all
*/
default java.util.List<String> allowedMimeTypes() {
return java.util.List.of(
"image/jpeg",
"image/png",
"image/gif",
"image/webp",
"image/svg+xml",
"video/mp4",
"video/webm",
"audio/mpeg",
"audio/ogg",
"application/pdf",
"application/zip"
);
}
/**
* Returns the maximum file size for uploads in megabytes.
*
* <p>Used for S3 bucket policy and CMS configuration.</p>
*
* @return max file size in MB (default: 128MB)
*/
default int maxUploadSizeMb() {
return 128;
}
/**
* Returns whether to enable S3 Transfer Acceleration.
*
* <p>Transfer Acceleration uses CloudFront edge locations for
* faster uploads, useful for global teams.</p>
*
* @return true to enable Transfer Acceleration (default: false)
*/
default boolean enableTransferAcceleration() {
return false;
}
/**
* Returns the storage class for media files.
*
* <p>S3 storage classes:</p>
* <ul>
* <li>STANDARD - Frequently accessed</li>
* <li>INTELLIGENT_TIERING - Auto-tiering</li>
* <li>STANDARD_IA - Infrequent access</li>
* </ul>
*
* @return S3 storage class (default: "STANDARD")
*/
default String storageClass() {
return "STANDARD";
}
}