# Media Manager Contract - `media-manager` is dumb and generic: it only parses multipart streams and writes them to storage. - The library never decides filenames, folders, MIME rules, limits, auth, URLs, or database writes. - Each caller provides the full relative path (including filename) for every uploaded file, e.g. `tea/452/photo.jpg`. ## Storage Strategies 1. `LOCAL_ONLY` – persist only to local storage using `//` (prefix defaults to `local`). 2. `S3_ONLY` – always stage the file locally, upload the staged file to S3 (key == `relativePath`), and delete the stage on success. Failure rolls back the stage and returns `status=0`. 3. `S3_AND_LOCAL` – stage locally and try to upload to S3. If S3 succeeds, both storages are considered written (status=1, `storageStrategy='S3_AND_LOCAL'`). If S3 fails, the local stage remains and the result downgrades to `storageStrategy='LOCAL_ONLY'` with `savedPath` pointing at the local file (status=1). ## Inputs & Constraints - `upload(storageStrategy, relativePath[], localStoragePrefix?)` must include exactly one file stream and one relative path entry. If not, return failure before touching any storage. - Every `relativePath` entry must be strictly relative (no leading `/`, drive letters, or `..`) and must include a filename. - Mapping is 1:1 in order: `relativePath[i]` corresponds to the `i`th file stream. ## Outputs ```ts { status: 0 | 1, storageStrategy: 'LOCAL_ONLY' | 'S3_ONLY' | 'S3_AND_LOCAL', relativePath: string[], savedPath: string // absolute local path or `s3://bucket/key` } ``` - `storageStrategy` should reflect what was actually persisted (downgrading to `LOCAL_ONLY` when S3 fails). - `savedPath` is the raw locator returned by the successful adapter: local absolute path for local persistence, or `s3://bucket/key` when S3 won. ## Cleanup - `cleanup(storageStrategy, relativePath[], localStoragePrefix?)` deletes exactly the requested paths/keys according to the strategy. - For `S3_AND_LOCAL`, attempt both deletes; return `status=1` only when every requested deletion succeeded. - No recursive deletion, no filesystem traversal beyond resolving `/`.