core PK: id 12 required 2 unique

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.

15
Attributes
7
Indexes
6
Validation Rules
14
CRUD Operations

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
btree

Columns: activity_id

idx_document_uploader_id
btree

Columns: uploader_id

idx_document_organization_id
btree

Columns: organization_id

idx_document_storage_key
btree unique

Columns: storage_key

idx_document_activity_active
btree

Columns: activity_id, is_deleted

idx_document_upload_status
btree

Columns: upload_status

idx_document_created_at
btree

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
on_create

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
on_delete

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
on_create

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
always

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
on_create

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
on_create

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
always

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.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Entity Relationships

activity
incoming one_to_many

An activity can have multiple file attachments (invitations, photos, PDFs) as supporting evidence

optional cascade delete