audit PK: id 9 required 1 unique

Description

Immutable audit record of every Bufdir export operation — mobile one-click and admin portal — capturing who triggered the export, the resulting file, delivery status, and any error details. Supports compliance traceability, rate-limit enforcement, and download history display.

21
Attributes
5
Indexes
7
Validation Rules
14
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Surrogate primary key generated at insert time
PKrequiredunique
bufdir_report_id uuid Foreign key to the bufdir_reports row that was exported
required
organization_id uuid Denormalized tenant key for fast org-scoped queries without joining bufdir_reports
required
exported_by_user_id uuid User who triggered the export; nullable only for system-initiated batch exports
-
export_source enum Which product surface initiated the export
required
export_format enum Output format of the generated file
required
status enum Lifecycle state of the export job
required
file_name string Human-readable filename presented to the user on download (e.g. bufdir-report-2025-q1.pdf)
-
file_path string Storage path or cloud object key for the generated file; null until status = completed
-
file_size_bytes integer Size of the exported file in bytes; populated on completion
-
checksum_sha256 string SHA-256 hex digest of the exported file for integrity verification
-
error_message text Human-readable error detail captured when status = failed; null on success
-
error_code string Machine-readable error code for programmatic retry/alerting (e.g. RATE_LIMIT_EXCEEDED, AGGREGATION_TIMEOUT)
-
download_count integer Number of times the completed export file has been downloaded
required
last_downloaded_at datetime Timestamp of the most recent file download
-
triggered_at datetime UTC timestamp when the export was requested; immutable after insert
required
processing_started_at datetime UTC timestamp when the export job was picked up by the generation service
-
completed_at datetime UTC timestamp when the export reached a terminal state (completed or failed)
-
expires_at datetime UTC timestamp after which the stored file is eligible for deletion; typically triggered_at + 90 days
required
report_period_label string Human-readable label of the reporting period included in the export (e.g. '2025-Q1'); denormalized for display in history lists without joining bufdir_reports
-
metadata json Extensible bag for additional export context: row counts, page count, Bufdir schema version used, mobile OS version, etc.
-

Database Indexes

idx_export_logs_bufdir_report_id
btree

Columns: bufdir_report_id

idx_export_logs_organization_id_triggered_at
btree

Columns: organization_id, triggered_at

idx_export_logs_exported_by_user_id
btree

Columns: exported_by_user_id

idx_export_logs_status
btree

Columns: status

idx_export_logs_expires_at
btree

Columns: expires_at

Validation Rules

bufdir_report_must_exist error

Validation failed

organization_id_matches_report error

Validation failed

valid_status_transition error

Validation failed

file_fields_required_on_completion error

Validation failed

error_message_required_on_failure error

Validation failed

expires_at_in_future error

Validation failed

processing_timestamps_ordered error

Validation failed

Business Rules

immutable_after_terminal_state
on_update

Once status reaches 'completed' or 'failed', all fields except download_count and last_downloaded_at are frozen. No updates are permitted.

no_delete_within_retention_window
on_delete

Export log rows must not be hard-deleted before expires_at. They form part of the compliance audit trail required for Bufdir funding accountability.

rate_limit_enforcement
on_create

No more than 5 export requests per organization per hour. The export-rate-limiter component checks this before a new row is inserted and sets status = failed with error_code = RATE_LIMIT_EXCEEDED when breached.

file_expiry_set_on_create
on_create

expires_at must be set to triggered_at + 90 days at insert time. The object storage adapter and a scheduled cleanup job use this to purge files while the log row is retained for audit.

org_scoped_visibility
always

Users may only read export log rows where organization_id matches their session's tenant. Global admins may query across tenants only via the audit interface.

download_count_increment_only
on_update

download_count must only ever increase. Any update that decrements it is rejected. last_downloaded_at is updated atomically with each increment.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
archive_after_1year