Dashboard job envelopes

std/dashboard/jobs defines the portable status event Harn emits for Jobs surfaces in local Burin and Harn Cloud. The contract is intentionally a dashboard-facing envelope, not a scheduler API: Harn runtimes and connectors produce ordered events, and hosts render queue/run/approval/DLQ/receipt state from normalized fields.

import { dashboard_job_event, dashboard_jobs_view } from "std/dashboard/jobs"

let event = dashboard_job_event(
  "run.started",
  {
    job_id: "daily-digest",
    run_id: "run-001",
    source_timestamp: "2026-05-11T14:01:10Z",
    workflow_id: "workflow://local/start-my-day",
  },
)

let view = dashboard_jobs_view([event])
log(view.jobs[0].status)

Event envelope

dashboard_job_event(kind, input, options?) returns harn.dashboard_job_event.v1:

FieldPurpose
kindEvent kind such as run.queued, approval.requested, dlq.created, or receipt.available
sourceRuntime and environment, for example local Harn or Harn Cloud
source_clockSource clock label plus timestamp for replayable ordering
tenant_id, workspace_idOptional partition keys for cloud and multi-workspace hosts
job_idStable dashboard job key
run_id, workflow_id, trigger_id, binding_id, event_idRuntime lineage where applicable
statusHost-renderable state: queued, running, waiting approval, succeeded, failed, DLQ, canceled, and related states
queue, queue_depth, priority, attempt, max_attemptsQueue and retry rendering hints
approvalFirst-class approval wait/decision state for approval events
dlqFirst-class DLQ state for replay and dismissal flows
receipt_refs, replay_refs, related_refsLinks or ids for audit receipts, replay fixtures, and source records
action_intentsHost-owned actions such as opening the job, reviewing an approval, replaying DLQ, or dismissing DLQ
raw_payloadOriginal local or cloud payload kept separate from normalized render fields

source_clock.timestamp is mandatory. Run events require run_id, approval events require approval.request_id, DLQ events require dlq.dlq_id, receipt.available requires at least one receipt ref, and replay_fixture.available requires at least one replay ref. Set raw_payload_retained: false when building an event to keep normalized status fields while omitting the original runtime payload.

Event kinds

The stdlib maps these event kinds to default statuses:

KindDefault status
scheduled_job.created, scheduled_job.updatedscheduled
scheduled_job.canceledcanceled
run.queuedqueued
run.started, run.progress, approval.approvedrunning
approval.requestedwaiting_approval
run.succeededsucceeded
run.failed, approval.denied, approval.expiredfailed
dlq.createddlq
dlq.replayedqueued
dlq.dismissedcanceled
receipt.available, replay_fixture.availableunknown; these add refs without changing the current card status

Callers can override status when a runtime has a more specific local state, but hosts should be able to render a useful card from the default mapping.

Static jobs view

dashboard_jobs_view(events, {emit?}) dedupes an ordered event stream and reduces it into harn.dashboard_job_card.v1 cards. The reducer is intentionally order-based: deterministic fixtures can drive a static Burin Home Jobs view without a live scheduler or database.

import { dashboard_job_event, dashboard_jobs_view } from "std/dashboard/jobs"

let events = [
  dashboard_job_event(
    "run.succeeded",
    {job_id: "daily-digest", run_id: "run-001", source_timestamp: "2026-05-11T14:03:00Z"},
  ),
]
let view = dashboard_jobs_view(events, {emit: true, topic: "dashboard.jobs.events"})
for job in view.jobs {
  log(job.job_id + ": " + job.status)
}

When emit is true, each unique event is appended to the EventLog as kind = "dashboard_job_event" and the view returns harn.dashboard_job_event_emit_receipt.v1 receipts.

Host boundary

Action intents are descriptive only. Non-navigation intents such as approval decisions, DLQ replay, and DLQ dismissal must set requires_approval: true; dashboard_job_validate rejects write-like intents that omit that gate. Hosts own the approval UX, persistence, undo semantics, and concrete side effects.