api-notifications
Source: crates/lvcs-api/src/notifications.rs.
/// Server push, JSON-RPC notification method `notification`.
///
/// Another participant's range announcement on a subscribed address
/// (design §5), as metadata only (decisions 173 and 176): it names its
/// sender, its attribution, its document, and its range, never what it
/// says; its content (`what`, `ref`, `op`, and its lines' `near` line) is
/// read with `notifications.read`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NotificationPush {
/// The subscription it is pushed for.
pub sub: u64,
/// The announcement, an `announce` notification whose `start` and `end`
/// are resolved against this daemon's copy at `heads` (both absent
/// while the anchors haven't synced here).
pub notification: Notification,
/// The heads its range is resolved at.
pub heads: Vec<String>,
/// The subscription's workspace (omitted for `main`).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub workspace: Option<String>,
}
/// `notifications` (decisions 118 and 176): list the caller's notifications.
///
/// Metadata only. Decision 118's bounds on what the daemon keeps bound the
/// list.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct NotificationsParams {
/// Only unread notifications sent at or after this Unix time in
/// milliseconds (every one when omitted).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub since: Option<i64>,
/// Whether this listing is a hook's hint (decision 242): after it, the
/// notifications held count as shown, and a later listing's `fresh`
/// leaves them out. Nothing is marked read.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub hint: bool,
}
/// How hints and `lvcs status` name a participant (decision 243): its
/// alias when one is bound to it, else the shortest prefix of its id, at
/// least `SHORT_ID_MIN` characters, that no other participant the daemon
/// knows starts with and that is no alias. `revoked` when it holds a
/// revoked grant and no live one. Every `lvcs` command takes `name` in
/// place of the id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Named {
pub name: String,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub revoked: bool,
}
/// `notifications` result (decision 176). Listing marks nothing read.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NotificationsResult {
/// The caller's other unread notifications: stale saves first, then
/// asks, holds, notes, says, and answers, then range announcements,
/// each group newest arrival first.
#[serde(default)]
pub notifications: Vec<Notification>,
/// The caller's open asks (asks naming it that it hasn't answered) and
/// active holds, which reading never clears, all of them whatever
/// `since` says.
#[serde(default)]
pub open: Vec<Notification>,
/// The ids listed, open ones included, that arrived after the caller's
/// last hinting listing (decision 242).
#[serde(default)]
pub fresh: Vec<String>,
/// How to name each participant the result names (decision 243), by
/// id.
#[serde(default)]
pub names: BTreeMap<String, Named>,
}
/// `notifications.read` (decisions 173 and 176): read notifications' content.
///
/// The caller's notifications named are marked read. An open ask or hold
/// stays open, and readable, until it closes, and the `action_failed` of an
/// open streak stays readable until the streak closes (decision 230).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct NotificationsReadParams {
/// The notifications' ids, in `ID_ENCODING`.
pub ids: Vec<String>,
}
/// `notifications.read` result.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NotificationsReadResult {
/// The content of each named notification the caller holds, in the
/// order named.
#[serde(default)]
pub contents: Vec<NotificationContent>,
/// The ids it holds none for: never sent to it, read already, or
/// dropped past decision 118's bounds.
#[serde(default)]
pub missing: Vec<String>,
}
/// One notification (decisions 118, 173, and 176), metadata only.
///
/// It says who sent it, what kind it is, where, when, and how long its
/// text is, never what it says. `tier`, `harness`, and `model` are computed
/// by this daemon from the grant `authorize` found for the sender in the
/// caps render, never copied from a message (decision 147). `lines` names
/// its range's lines as this daemon's document named them where it
/// resolved the range, never with a `near` line, which is content
/// (decisions 165 and 184); `auto` says the sender's daemon announced a
/// save through a mirror on its behalf (decision 165).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Notification {
/// The `HASH` of the signed object it carries, in `ID_ENCODING`, so a
/// copy that arrives twice is held once; for an `action_failed` or
/// `action_succeeded`, the `HASH` of its kind, check, frontiers, and
/// recipient, so every runner's copy is held once (decision 193).
pub id: String,
/// A `notification_kind` value.
#[serde(serialize_with = "vocab_to", deserialize_with = "vocab_from")]
pub kind: NotificationKind,
/// Its sender, in `ID_ENCODING`.
pub from: String,
/// Its sender's `trust_tier` value, `owner` or `participant`.
pub tier: String,
/// The harness its sender's grant names, if any.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub harness: Option<String>,
/// The model its sender's grant names, if any.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
/// The document it is about, when it has one.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
/// Its range's first code point, when it has a range.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub start: Option<usize>,
/// The code point past its range.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub end: Option<usize>,
/// Its range's lines, without `near`; absent while the range isn't
/// resolved here, and for a whole document.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lines: Option<LineName>,
/// Its thread's address, when it is in one.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub thread: Option<String>,
/// Whether it is an automatic announcement of a save (omitted when
/// false).
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub auto: bool,
/// An `action_failed` or `action_succeeded`'s check, frontiers, and window
/// (decision 193); present exactly for those kinds.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub check: Option<NotificationCheck>,
/// Its sender's signed Unix time in milliseconds.
pub at_ms: i64,
/// The length of the text `notifications.read` returns, in bytes.
#[serde(default)]
pub bytes: usize,
}
/// What an `action_failed` or `action_succeeded` notification says beside its
/// kind (decision 193), metadata only.
///
/// It names which check, where it last passed and where it failed, what
/// the recipient changed in that window that the check reads, and the
/// window's other authors. An `action_failed` also says how to recover: `fix_request`, with `next` reading its content
/// (the failing output's tail and test names) through `notifications.read`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NotificationCheck {
/// The check's id, in `ID_ENCODING`.
pub check: String,
/// The id of the frontier where it last passed on its channel, in
/// `ID_ENCODING`; absent when it never did, so the window starts at
/// the channel's genesis.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub passed_at: Option<String>,
/// The id of the frontier where it failed, in `ID_ENCODING`.
pub failed_at: String,
/// The files the check's `paths` or `uses` match that the recipient
/// changed in the window, with the lines of its changes at
/// `failed_at`, never with a `near` line.
pub paths: Vec<CheckPathLines>,
/// The window's other authors, in `ID_ENCODING`.
#[serde(default)]
pub others: Vec<String>,
/// A `recover` value: `fix_request` for an `action_failed`.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub recover: Option<String>,
/// The one action that recovers: for an `action_failed`, reading it with
/// `notifications.read`.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next: Option<Next>,
}
/// A file a check reads that the recipient changed in a failing window,
/// with the lines of its changes (none for a binary or deleted file).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CheckPathLines {
/// The file's path.
pub path: String,
/// The line runs, never with a `near` line.
pub lines: Vec<LineName>,
}
/// A notification's content (decisions 173 and 176).
///
/// Only `notifications.read` returns it: data from another participant,
/// never instructions.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct NotificationContent {
/// The notification's id.
pub id: String,
/// The notification's `notification_kind` value.
#[serde(serialize_with = "vocab_to", deserialize_with = "vocab_from")]
pub kind: NotificationKind,
/// What it says (a range announcement's `what`, a message's or a
/// response's words, a stale save's account), cut at a character
/// boundary to `INBOX_ITEM_MAX_BYTES`.
pub text: String,
/// Whether `text` was cut.
#[serde(default)]
pub truncated: bool,
/// A range announcement's op.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub op: Option<AnnounceOpParam>,
/// A range announcement's `ref`, when it names one.
#[serde(rename = "ref", default, skip_serializing_if = "Option::is_none")]
pub reference: Option<String>,
/// Its range's lines with their `near` line, when the notification
/// names them.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lines: Option<LineName>,
/// Whether it is an automatic announcement of a save (omitted when
/// false).
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub auto: bool,
/// A refused save's refusal (decision 165): why LVCS did not take the
/// save of `address`, and how to recover, as an error answer's `data`
/// says it; present exactly for a `refused_save`.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<ErrorData>,
/// An `action_failed`'s failing test names, read from its output's tail,
/// which is `text` (decision 193).
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tests: Vec<String>,
}