Exact backend contract. Conventions (envelope, errors, versioning): 00-shared/07_API_Conventions .
Source: files.controller.ts:29-71, files.service.ts, file.schema.ts,
src/modules/rbac/permissions.constants.ts:86-88.
# Method Path Permission Source Purpose
1 POST /api/v1/files/uploadfile.uploadfiles.controller.ts:29-41Upload single file (multipart)
2 GET /api/v1/filesfile.readfiles.controller.ts:43-47List tenant files, createdAt desc
3 GET /api/v1/files/:idfile.readfiles.controller.ts:49-53File metadata; 404 if missing
4 GET /api/v1/files/:id/downloadfile.readfiles.controller.ts:55-64Download raw bytes (attachment)
5 DELETE /api/v1/files/:idfile.deletefiles.controller.ts:66-71Storage delete + metadata soft-delete
Request: multipart/form-data, part file (binary) (files.controller.ts:31-37).
Client-supplied: originalname, mimetype, size (used verbatim, files.service.ts:32-33).
Flow: tenant from TenantContextService.requireTenantId() (files.service.ts:28) →
storage.upload({buffer, filename: <uuid>--<originalName>, mimeType, tenantId})
(files.service.ts:29-34) → record create (files.service.ts:36-45).
Response body: FileRecord — {id, originalName, mimeType, size, storageProvider, storageFileId, storagePath, createdAt, updatedAt}. storageFileId/storagePath are
internal; do not expose in UI.
Errors: 400 (malformed multipart), 401/403 (guards (planned)), 500 (provider).
Query: no params (no pagination/filter; gap). Sorted createdAt: -1
(files.service.ts:48-50). Tenant-scoped + soft-delete filtered via BaseRepository
(file.repository.ts:9-15).
404 File not found (files.service.ts:54) for unknown or soft-deleted ids.
Headers: Content-Type: <mimeType> (files.controller.ts:60);
Content-Disposition: attachment; filename="<originalName>" (files.controller.ts:61).
Body: full bytes (res.send, files.controller.ts:63) — proxied buffer, no
redirect, no signed URL, no Range/streaming today.
Flow: findById → storage.download(storageFileId) (files.service.ts:58-64).
Response: { message: 'File deleted' } (files.controller.ts:70).
Flow: findById (404 if gone) → storage.delete(storageFileId) →
repo.softDelete(id) (files.service.ts:66-70). Object hard-deleted; metadata retained
(soft).
Permission Endpoints Note
file.readlist, get, download permissions.constants.ts:86
file.uploadupload permissions.constants.ts:87
file.deletedelete permissions.constants.ts:88
No file.update/file.share — matching UI (no replace, no share UI).
Endpoint Status Source
GET /files/:id/signed-url?expiresInSeconds= (TTL)(planned) — provider method exists (storage-provider.ts:25), service never calls it; blueprint TTL STORAGE_ARCHITECTURE.md:44,66r2.provider.ts:77-86
Upload limits (multer limits.fileSize, MIME allowlist) (planned) — nothing enforces today—
Pagination ?page&limit, filters (planned) / (proposed)—
Multi-delete, restore (planned)—
Streaming / Range for large downloads (planned)STORAGE_ARCHITECTURE.md:67
Retention/cleanup jobs (3-day tier) (planned)IMPLEMENTATION_PLAN.md:176
Screen/Cubit Endpoint(s)
FilesCubit (list) GET /files
UploadCubit POST /files/upload
Detail sheet GET /files/:id
DownloadCubit GET /files/:id/download
Delete flow DELETE /files/:id
Success/failure envelopes per 00-shared/07_API_Conventions and
common/interceptors/response-envelope.interceptor.ts /
common/filters/http-exception.filter.ts.
HTTP statuses above are what the client must handle; 401/403 require guards which are
(planned) (AGENTS.md: auth not yet implemented).