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 User,
34 Service,
35 Desktop,
36}
37
38/// Per-record authorship stamp.
39///
40/// Carried as `Option<AuthorStamp>` on `Observation`, `Belief` and
41/// `Evidence` so "whose call produced this insight" survives an export,
42/// even though every team member writes into the same tenant-scoped
43/// store. `None` for records written before authorship existed and for
44/// anonymous compat-mode calls.
45#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47#[serde(rename_all = "camelCase")]
48pub struct AuthorStamp {
49 /// The originating user id. For service tokens this is
50 /// `"service:<subject_id>"` so service-written records are
51 /// visually distinguishable from human-written ones.
52 pub user_id: UserId,
53 /// The token id that minted the context, when present. None for
54 /// local-bootstrap contexts that don't transit a token.
55 #[serde(default, skip_serializing_if = "Option::is_none")]
56 pub token_id: Option<TokenId>,
57 pub subject_type: SubjectType,
58 /// Wall-clock time the authoring happened. Distinct from
59 /// `observed_at` / `extracted_at`, which are content timestamps;
60 /// this is the persistence timestamp.
61 pub authored_at: DateTime<Utc>,
62}