Service Layer medium complexity mobile
2
Dependencies
1
Dependents
1
Entities
1
Integrations

Description

Orchestrates the full attachment lifecycle: validates file size (max 10 MB) and MIME type, uploads the binary to Supabase Storage, persists metadata to the activity_attachments table, and rolls back the storage object on any database failure.

Feature: Document Attachments for Activities

attachment-upload-service

Summaries

The Attachment Upload Service is the business-critical component that enables staff to attach photographic evidence and PDF documentation directly to activity records within the mobile app. This capability supports regulatory compliance reporting requirements — particularly Bufdir exports — by ensuring that supporting files are stored securely, linked to the correct organisational context, and immediately available for audit. The 10 MB file size cap and MIME type restriction reduce storage costs and prevent accidental uploads of unsupported formats. The automatic rollback mechanism, which removes an uploaded file if its database record fails to persist, protects against orphaned storage objects that would silently inflate storage bills without providing any retrieval value.

The Attachment Upload Service carries medium development complexity due to its orchestration of two external systems — Supabase Storage and the activity_attachments database table — with a coordinated rollback requirement if persistence fails. The critical delivery dependency is the Supabase Storage bucket configuration (org-scoped paths, RLS policies) being in place before integration testing begins. Testing must cover: file size boundary conditions (exactly 10 MB, 10 MB + 1 byte), MIME type rejection, successful upload and metadata persistence, storage rollback on database failure, and network interruption scenarios. Coordinate with the backend or platform team to confirm the bucket naming and org_id path convention before implementation to avoid late-stage refactoring.

The Attachment Upload Service orchestrates a two-phase write: (1) binary upload to an org-scoped Supabase Storage path via `supabase-storage-adapter.upload()`, followed by (2) metadata persistence via `activity-attachment-repository.insertAttachment()`. If phase 2 fails, the service must call `supabase-storage-adapter.delete()` with the path returned from phase 1 to prevent orphaned blobs. Validation via `validateFile(file)` runs synchronously before any I/O: check `file.size <= 10_485_760` and that `file.type` is in an allowlist of accepted MIME types (application/pdf, image/jpeg, image/png). The storage path should follow the convention `{orgId}/{activityId}/{uuid}.{ext}` to ensure org-level isolation.

Expose `getAttachmentsForActivity(activityId)` and `getAttachmentCountForActivity(activityId)` as thin pass-throughs to the repository for use by UI components.

Responsibilities

  • Validate file size against 10 MB limit
  • Validate MIME type against allowed formats (PDF, JPEG, PNG)
  • Upload binary to org-scoped Supabase Storage bucket
  • Persist attachment metadata (storage path, file name, size, MIME type) to database
  • Delete storage object if metadata persistence fails

Interfaces

uploadAttachment(activityId, orgId, file)
deleteAttachment(attachmentId)
validateFile(file)
getAttachmentsForActivity(activityId)
getAttachmentCountForActivity(activityId)

Relationships

Dependencies (2)

Components this component depends on

Dependents (1)

Components that depend on this component

Related Data Entities (1)

Data entities managed by this component

Used Integrations (1)

External integrations and APIs this component relies on

API Contract

View full contract →
REST /api/v1/attachments 6 endpoints
GET /api/v1/attachments
GET /api/v1/attachments/:id
POST /api/v1/attachments
PUT /api/v1/attachments/:id
DELETE /api/v1/attachments/:id
POST /api/v1/attachments/validate