Document
Data Entity
Description
A file attachment linked to an activity record — event invitations, photographs, screenshots, or PDF documents uploaded as supporting evidence for Bufdir compliance verification. Files are stored in object storage with signed URL access and metadata tracked in the database.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Unique identifier for the document record, generated server-side on creation | PKrequiredunique |
activity_id |
uuid |
Foreign key referencing the activity this document is attached to. Documents must always belong to an activity. | required |
uploader_id |
uuid |
Foreign key referencing the user (peer mentor or coordinator) who uploaded this document | required |
storage_key |
string |
The object storage key (path) used to generate signed GET/PUT URLs. Namespaced by organization to prevent cross-tenant access (e.g. org-uuid/activity-uuid/filename-uuid.ext). | requiredunique |
filename |
string |
The original filename as provided by the client at upload time, stored for display purposes | required |
mime_type |
string |
MIME type of the uploaded file, validated against the allowed list: image/jpeg, image/png, image/heic, application/pdf | required |
file_size_bytes |
integer |
File size in bytes, recorded at upload time for display and quota enforcement | required |
organization_id |
uuid |
Foreign key referencing the organization that owns this document, used for tenant-scoped storage namespacing and access control | required |
local_association_id |
uuid |
Foreign key referencing the local association context at time of upload, used for Bufdir report scoping | - |
upload_status |
enum |
Tracks the lifecycle state of the document upload process | required |
is_deleted |
boolean |
Soft-delete flag. Documents are never hard-deleted from the database to preserve Bufdir audit trail integrity. | required |
deleted_at |
datetime |
Timestamp when the document was soft-deleted. NULL when document is active. | - |
deleted_by |
uuid |
Foreign key referencing the user who performed the soft-delete. NULL when document is active. | - |
created_at |
datetime |
Timestamp when the document metadata record was created in the database | required |
updated_at |
datetime |
Timestamp of the last metadata update (e.g. status transition from pending to uploaded) | required |
Database Indexes
idx_document_activity_id
Columns: activity_id
idx_document_uploader_id
Columns: uploader_id
idx_document_organization_id
Columns: organization_id
idx_document_storage_key
Columns: storage_key
idx_document_activity_active
Columns: activity_id, is_deleted
idx_document_upload_status
Columns: upload_status
idx_document_created_at
Columns: created_at
Validation Rules
allowed_mime_types
error
Validation failed
max_file_size_20mb
error
Validation failed
filename_sanitization
error
Validation failed
storage_key_immutable
error
Validation failed
upload_status_transitions
error
Validation failed
organization_scope_matches_activity
error
Validation failed
Business Rules
document_requires_activity
Every document must be linked to an existing activity. Orphaned documents (without a valid activity_id) are not permitted. If the parent activity is deleted, its documents are cascade-soft-deleted.
soft_delete_only
Documents must never be hard-deleted from the database. The is_deleted flag and deleted_at timestamp are used to preserve the Bufdir compliance audit trail. Physical object storage deletion may follow a retention policy but the metadata record is permanent.
storage_key_namespaced_by_org
The storage_key must be prefixed with the organization's UUID to enforce tenant isolation in object storage. Cross-organization access is prevented at both the key-generation and signed-URL-generation layers.
signed_url_access_only
Document file content must never be served via public static URLs. All file access must go through short-lived signed GET URLs generated by document-storage, ensuring that access control is enforced at retrieval time.
uploader_must_own_parent_activity
The uploader (uploader_id) must be the owner of the parent activity or a coordinator with proxy access to that activity. Coordinators uploading on behalf of a peer mentor must have a registered proxy relationship.
max_attachments_per_activity
An activity may not have more than 10 active (non-deleted) document attachments. This prevents abuse and bounds storage costs per activity record.
pending_upload_timeout_cleanup
Documents that remain in 'pending' upload_status for more than 30 minutes (i.e. signed URL was generated but PUT never completed) should be marked 'failed' by a background cleanup job to prevent stale metadata accumulation.
CRUD Operations
Storage Configuration
Entity Relationships
An activity can have multiple file attachments (invitations, photos, PDFs) as supporting evidence