hive-c0re: rfc3339 timestamps on dashboard api + sse json

This commit is contained in:
damocles 2026-07-02 21:30:16 +02:00 committed by mara
commit bac2c0a65e
6 changed files with 23 additions and 8 deletions

View file

@ -89,6 +89,7 @@ impl AuditOutcome {
#[derive(Debug, Clone, Serialize)]
pub struct AuditEntry {
pub id: i64,
#[serde(with = "hive_sh4re::wire_time::iso")]
pub ts_unix: i64,
/// Agent on whose behalf the action was taken.
pub agent: String,

View file

@ -74,7 +74,9 @@ pub struct PendingReminder {
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_path: Option<String>,
#[serde(with = "hive_sh4re::wire_time::iso")]
pub due_at: i64,
#[serde(with = "hive_sh4re::wire_time::iso")]
pub created_at: i64,
/// Most recent delivery failure for this row, if any. Cleared
/// to NULL on operator retry. Surfaced inline in the dashboard

View file

@ -432,7 +432,8 @@ struct ApprovalHistoryView {
sha_short: Option<String>,
/// `approved` / `denied` / `failed`.
status: &'static str,
/// Unix seconds. Renders as a relative time on the dashboard.
/// RFC 3339 UTC. Renders as a relative time on the dashboard.
#[serde(with = "hive_sh4re::wire_time::iso")]
resolved_at: i64,
/// Operator-supplied deny reason (for `denied`) or build error
/// (for `failed`). None on `approved`.
@ -471,8 +472,10 @@ struct ApprovalView {
/// `None` for every other kind.
#[serde(skip_serializing_if = "Option::is_none")]
commit_ref: Option<String>,
/// Unix seconds the approval was queued. Rendered as a relative
/// time on the card so the operator can spot a stale request.
/// RFC 3339 UTC time the approval was queued. Rendered as a
/// relative time on the card so the operator can spot a stale
/// request.
#[serde(with = "hive_sh4re::wire_time::iso")]
requested_at: i64,
}
@ -1373,7 +1376,7 @@ async fn api_operator_inbox(State(state): State<AppState>) -> Response {
"id": id,
"from": from,
"body": body,
"at": at,
"at": hive_sh4re::wire_time::to_iso(at),
"in_reply_to": in_reply_to,
"file_refs": file_refs,
}))

View file

@ -38,6 +38,7 @@ pub enum DashboardEvent {
from: String,
to: String,
body: String,
#[serde(with = "hive_sh4re::wire_time::iso")]
at: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
in_reply_to: Option<i64>,
@ -53,6 +54,7 @@ pub enum DashboardEvent {
from: String,
to: String,
body: String,
#[serde(with = "hive_sh4re::wire_time::iso")]
at: i64,
#[serde(default, skip_serializing_if = "Option::is_none")]
in_reply_to: Option<i64>,
@ -95,6 +97,7 @@ pub enum DashboardEvent {
sha_short: Option<String>,
/// `"approved"` / `"denied"` / `"failed"`.
status: &'static str,
#[serde(with = "hive_sh4re::wire_time::iso")]
resolved_at: i64,
note: Option<String>,
description: Option<String>,
@ -111,7 +114,9 @@ pub enum DashboardEvent {
question: String,
options: Vec<String>,
multi: bool,
#[serde(with = "hive_sh4re::wire_time::iso")]
asked_at: i64,
#[serde(with = "hive_sh4re::wire_time::iso_opt")]
deadline_at: Option<i64>,
target: Option<String>,
/// Verified file-path tokens that appear in `question`.
@ -130,6 +135,7 @@ pub enum DashboardEvent {
id: i64,
answer: String,
answerer: String,
#[serde(with = "hive_sh4re::wire_time::iso")]
answered_at: i64,
cancelled: bool,
target: Option<String>,

View file

@ -74,11 +74,14 @@ pub struct OpQuestion {
pub question: String,
pub options: Vec<String>,
pub multi: bool,
#[serde(with = "hive_sh4re::wire_time::iso")]
pub asked_at: i64,
/// Absolute unix-seconds deadline after which a watchdog auto-
/// resolves the question with answer `[expired]`. `None` = no
/// expiry. Surfaced on the dashboard as a remaining-time chip.
/// Deadline after which a watchdog auto-resolves the question with
/// answer `[expired]`. `None` = no expiry. Surfaced on the
/// dashboard as a remaining-time chip.
#[serde(with = "hive_sh4re::wire_time::iso_opt")]
pub deadline_at: Option<i64>,
#[serde(with = "hive_sh4re::wire_time::iso_opt")]
pub answered_at: Option<i64>,
pub answer: Option<String>,
/// Recipient of the question. `None` = the operator (dashboard

View file

@ -16,7 +16,7 @@
//! (keep the usual `default` + `skip_serializing_if` attributes).
use chrono::{DateTime, SecondsFormat, Utc};
use serde::{Deserialize, Deserializer};
use serde::Deserialize;
/// Format unix-epoch seconds as an RFC 3339 UTC string with a `Z`
/// suffix. Out-of-range values (never produced by our clocks) clamp to