Rust SDK · Event shape
The event model is a set of structs (serde-derived):
pub struct Event {
pub id: String, // uuid v4; auto-generated
pub tenant_id: String, // optional; partition by end-customer
pub occurred_at: DateTime<Utc>, // auto-populated
pub actor: Actor, // who caused the event
pub action: String, // dotted verb, e.g. "user.lock"
pub target: Target, // what was acted on
pub metadata: BTreeMap<String, Value>, // freeform context
pub origin: Origin, // IP, user-agent, request ID
pub outcome: Outcome, // serialized to the wire field "result"
pub change: Option<Change>, // before/after for mutations
pub idempotency_key: String, // optional dedup key
}
pub struct Actor { pub r#type: String, pub id: String, pub display_name: String, pub email: String }
pub struct Target { pub r#type: String, pub id: String }
pub struct Outcome { pub status: String, pub code: i32, pub message: Option<Value> } // status: "ok"|"error"|"denied"
pub struct Origin { pub ip: String, pub user_agent: String, pub request_id: String }
Fields use plain values with empty defaults; empty means "not set" and the serializer omits them. Field names are snake_case and match the JSON wire format. The outcome type is named
Outcometo avoid clashing with [std::result::Result], but serializes to the wire fieldresult. The JSON payload is byte-compatible with the Go, Node, and Python SDKs.
Metadata helpers and construction:
let mut e = everscribe::event::Event::new("user.lock");
e.with_field("reason", "policy_violation");
e.actor = everscribe::event::Actor { r#type: "user".into(), id: "u1".into(), ..Default::default() };