Skip to main content

ant_types/
author.rs

1//! Record authorship — the provenance stamp carried on insight-plane
2//! records.
3//!
4//! Only the part of the engine's auth model that appears ON RECORDS
5//! lives here. Roles, tokens, memberships, scope grants and everything
6//! else about authenticating a caller stay in `antares-core`: a reader
7//! of an `.ant` file has to understand who authored a belief, not how
8//! the engine decided to let them.
9
10use chrono::{DateTime, Utc};
11use serde::{Deserialize, Serialize};
12
13/// Stable identifier for a user.
14#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
15#[cfg_attr(feature = "utoipa", schema(value_type = String))]
16#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
17#[serde(transparent)]
18pub struct UserId(pub String);
19
20/// Stable identifier for a token record.
21#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
22#[cfg_attr(feature = "utoipa", schema(value_type = String))]
23#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
24#[serde(transparent)]
25pub struct TokenId(pub String);
26
27/// Token subject class. Lets a consumer tell "a person wrote this in
28/// the client" from "a service connector wrote this".
29#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(rename_all = "snake_case")]
32pub enum SubjectType {
33    /// A person, acting through an interactive client.
34    User,
35    /// A service connector or automation.
36    Service,
37    /// A desktop client instance.
38    Desktop,
39}
40
41/// Per-record authorship stamp.
42///
43/// Carried as `Option<AuthorStamp>` on `Observation`, `Belief` and
44/// `Evidence` so "whose call produced this insight" survives an export,
45/// even though every team member writes into the same tenant-scoped
46/// store. `None` for records written before authorship existed and for
47/// anonymous compat-mode calls.
48#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub struct AuthorStamp {
52    /// The originating user id. For service tokens this is
53    /// `"service:<subject_id>"` so service-written records are
54    /// visually distinguishable from human-written ones.
55    pub user_id: UserId,
56    /// The token id that minted the context, when present. None for
57    /// local-bootstrap contexts that don't transit a token.
58    #[serde(default, skip_serializing_if = "Option::is_none")]
59    pub token_id: Option<TokenId>,
60    /// What class of subject authored the record.
61    pub subject_type: SubjectType,
62    /// Wall-clock time the authoring happened. Distinct from
63    /// `observed_at` / `extracted_at`, which are content timestamps;
64    /// this is the persistence timestamp.
65    pub authored_at: DateTime<Utc>,
66}