At a Glance
Owner:micro-reportexecutor (read-only UI) · Table:tb_report_job· Retention:expires_atper tenant policy (artefact reaped; row kept) · Used by: Reports → History, Print History drawer · Append-only audit log of every report run.

Report History is the append-only execution log for every report run on the tenant — ad-hoc exports, Print invocations, and scheduled runs all land here. Each row captures the report identifier, the concrete filter set, requesting user (or schedule), lifecycle state, and a pointer to the produced artefact in blob storage.
Audience: Auditor (who ran what), Sysadmin (failed-run triage), Compliance (export trail), Tester (verify the right template fired).
| Task | Where | Notes |
|---|---|---|
| Find yesterday's report run | Reports → History | Filter by date range + report type |
| Re-download an output | History row → Download | Works until expires_at reaper deletes artefact |
| See who triggered a run | History row → Requester column | Schedule runs show schedule owner via requested_by_id |
| Re-run a report with the same filters | History row → Re-run | Re-enqueues a fresh job with identical filters / options |
| View full filter set used | History row → View Details | Renders the filters and options JSON |
| Investigate a failed run | Filter by status = failed, open Details |
error_message carries the scrubbed cause |
| Confirm a Print fired | Document detail → Print History drawer | Shows recent jobs against that document |
| Symptom / Question | Cause / Answer | Action |
|---|---|---|
| Download link returns 404 | expires_at passed; reaper deleted the artefact |
Row remains for audit; Re-run to regenerate |
| Why is my row missing? | RBAC filtered — you are neither the requester nor a category reader | Ask Sysadmin or hold the report's read permission |
| Can I edit a row? | No — table is append-only; only the executor mutates status / terminal fields |
Re-run instead |
Why is started_at null? |
Job is still queued (executor hasn't picked it up) |
Wait, or check executor health |
| What format will I get? | Whatever was requested at enqueue: pdf / excel / csv / json |
Pick at submit, not re-download |
| Where do output files live? | Blob storage; file_url is the resolved download URL |
Backed by tenant storage config |
| Is the error message safe to share? | Yes — credentials, tokens, raw SQL values are scrubbed; only bound param names survive | — |
expires_at; row stays so "who ran what against which filters" survives forever (subject to tenant policy).Timestamptz(6) UTC; UI renders in profile timezone. Scheduled runs encode intended fire time in options.scheduled_fire_at.Source: tenant schema (packages/prisma-shared-schema-tenant/prisma/schema.prisma).
tb_report_job| Field | Prisma Type | Nullable | Description |
|---|---|---|---|
id |
String @db.Uuid |
No | Primary key. |
report_type |
String @db.VarChar(100) |
No | Logical identifier matching the template. |
report_category |
enum_report_category |
No | inventory / procurement / recipe / vendor / financial / operational. |
format |
enum_report_format |
No | pdf / excel / csv / json. |
status |
enum_report_job_status |
No | Default queued. queued / processing / completed / failed / cancelled. |
filters |
Json? @db.JsonB |
Yes | Default {}. Concrete filter values for this run. |
options |
Json? @db.JsonB |
Yes | Default {}. Render options + scheduled_fire_at for scheduled runs. |
file_url, file_name, file_size, row_count |
mixed | Yes | Artefact metadata. |
error_message |
String? |
Yes | Populated when status = failed; scrubbed of secrets. |
started_at, completed_at, expires_at, duration_ms |
mixed | Yes | Execution / retention timestamps. |
requested_by_id |
String @db.Uuid |
No | Requesting user (or schedule's created_by_id). |
| Audit columns | — | Yes | created_*, updated_*, deleted_*. |
Constraints: indexes on status, report_type, requested_by_id, and created_at DESC (dominant access pattern). No FK to tb_report_schedule; the link is logical via matching report_type + correlation id in options.
queued → processing → (completed | failed | cancelled). started_at set on entering processing; completed_at + duration_ms set on every terminal state. cancelled reachable from queued or processing.expires_at drives the storage reaper. After it passes, the artefact behind file_url is deleted; the row remains.options.scheduled_fire_at so review is unambiguous.kind = report template firing produces a row here.last_run_at derived from latest completed job.export and print actions are also logged with entity_type = 'report_job'.requested_by_id resolves through platform tb_user.../carmen-turborepo-backend-v2/packages/prisma-shared-schema-tenant/prisma/schema.prisma — tb_report_job (lines 5652-5683), enum_report_job_status (5644-5650), enum_report_format (~5628-5633), enum_report_category (~5635-5642).../carmen-inventory-frontend/app/(root)/report/history/.../micro-report/controller/report_controller.go, ../micro-report/db/report_job_repo.go.