tsafe_collab/types.rs
1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4/// A member of a team, identified by their age X25519 public key.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct MemberEntry {
7 /// The age X25519 bech32 public key for this member.
8 pub pubkey: String,
9 /// UTC timestamp when this member joined the team.
10 pub joined_at: DateTime<Utc>,
11}
12
13/// An age-encrypted DEK envelope. The server stores and returns this blob
14/// opaquely — it cannot decrypt it because it holds no private key material.
15///
16/// JSON schema: `tsafe/collab-dek/v1`
17///
18/// ```json
19/// {
20/// "schema": "tsafe/collab-dek/v1",
21/// "team_id": "<uuid>",
22/// "recipient_pubkey": "<age X25519 bech32 pubkey>",
23/// "age_ciphertext_b64": "<base64(age-armored ciphertext of 32-byte DEK)>",
24/// "delivered_at": "<ISO-8601 UTC>"
25/// }
26/// ```
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct DekEnvelope {
29 /// Always `"tsafe/collab-dek/v1"`.
30 pub schema: String,
31 /// The team this envelope belongs to.
32 pub team_id: String,
33 /// The age bech32 public key of the intended recipient.
34 pub recipient_pubkey: String,
35 /// Base64-encoded age-armored ciphertext of the 32-byte DEK, encrypted to
36 /// `recipient_pubkey`. The server never decrypts this.
37 pub age_ciphertext_b64: String,
38 /// UTC timestamp when the envelope was delivered to the server.
39 pub delivered_at: DateTime<Utc>,
40}
41
42impl DekEnvelope {
43 /// Canonical schema identifier for envelope v1.
44 pub const SCHEMA: &'static str = "tsafe/collab-dek/v1";
45}
46
47/// An opaque invite token produced by `CollabRemote::create_invite`.
48///
49/// The token carries the team ID and the invitee's expected public key so that
50/// the confirm step can enforce the TOFU binding (ADR-028).
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct InviteToken {
53 /// Unique token string delivered to the invitee out-of-band.
54 pub token: String,
55 /// Team the invite is for.
56 pub team_id: String,
57 /// The age public key the invite was bound to.
58 pub bound_pubkey: String,
59}
60
61/// Server-side record for a pending invite.
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct InviteRecord {
64 /// The unique token string.
65 pub token: String,
66 /// Team the invite targets.
67 pub team_id: String,
68 /// The age public key of the intended invitee, bound at creation time.
69 pub invitee_pubkey: String,
70 /// UTC timestamp when the invite expires.
71 pub expires_at: DateTime<Utc>,
72}