Digital Asset & Media Management

Resumable chunked file uploads, multi-cloud storage backends, ClamAV anti-malware pipeline, and signed temporary download URLs.

The Media module delivers a unified Digital Asset Management (DAM) service across the entire SCRIPE ecosystem. It powers athlete profile photos, coach certification scans, tournament video highlights, branded tenant logos, and financial receipts, supporting high-throughput chunked uploads and bank-grade cryptographic access tokens.

Media Architecture

Built with pluggable storage backends (Local Disk, AWS S3, Azure Blob Storage, MinIO) and automated thumbnail generation.

  • Hierarchical Folder Taxonomy

    Nested directories with tenant scoping, permissions inheritance, and system-level asset libraries.

  • Unified File Metadata

    Detailed file tracking including original name, storage provider, MIME type, byte size, and cryptographic hash.

  • Granular Access Grants

    Time-bound, role-restricted, or user-specific permissions for private documents, contracts, and ID scans.

  • Resumable Chunked Uploads

    Reliable streaming upload protocol supporting gigabyte-scale videos and network resumption on mobile connections.

  • Automated Malware Scanning

    Background antivirus evaluation before files are flagged as safe for downstream tenant consumption.

  • Signed Temporary URLs

    HMAC-SHA256 signed download links with configurable expiration to prevent hotlinking and data leaks.

Domain Aggregate Root: MediaFile

The MediaFile aggregate encapsulates storage metadata, access grants, public/private visibility, and signed URL generation.

src/Modules/Media/Media.Domain/Entities/MediaFile.csC#
public sealed class MediaFile : TenantAggregateRoot
{
    public Guid? FolderId { get; private set; }
    public string OriginalFileName { get; private set; } = string.Empty;
    public string StoredFileName { get; private set; } = string.Empty;
    public string ContentType { get; private set; } = string.Empty;
    public long FileSizeBytes { get; private set; }
    public string Sha256Checksum { get; private set; } = string.Empty;
    public string StorageProvider { get; private set; } = "Local";
    public bool IsPublic { get; private set; }
    public List<MediaAccessGrant> AccessGrants { get; private set; } = new();

    public Result<string> GenerateSignedDownloadUrl(TimeSpan validityWindow, string secretKey)
    {
        // Generates HMAC-SHA256 signed temporary access token
        var expiry = DateTimeOffset.UtcNow.Add(validityWindow).ToUnixTimeSeconds();
        var token = MediaSignatureGenerator.Sign(Id, TenantId, expiry, secretKey);
        return Result<string>.Success($"/api/v1/media/files/{Id}/download?exp={expiry}&sig={token}");
    }
}

Resumable Chunked Upload & Verification Pipeline

From initial client handoff through anti-malware verification to production CDN distribution:

Client initiates chunked upload session
Validate file size against edition quota
Stream binary chunks into isolated staging bucket
Assemble chunks & compute SHA-256 integrity checksum
ClamAV asynchronous anti-malware scan verification
Move to production storage (S3 / Azure Blob / MinIO)
Emit MediaFileCreatedDomainEvent & trigger image optimizer

Primary API Endpoints

Key endpoints exposed by MediaControllers for directory organization, upload sessions, access grants, and file delivery.

MethodEndpointDescriptionAuth
GET/api/v1/media/foldersList media folders and taxonomy within current tenant scope🔒 Required
POST/api/v1/media/foldersCreate a new media folder for asset categorization🔒 Required
GET/api/v1/media/filesBrowse uploaded media files with metadata and filter options🔒 Required
POST/api/v1/media/files/uploadInitiate a multipart upload session or upload a binary file🔒 Required
POST/api/v1/media/files/{id}/grantsGrant temporary or persistent access rights to a restricted file🔒 Required
GET/api/v1/media/files/{id}/downloadDownload a media file via Bearer token or signed access URL🔒 Required