#[non_exhaustive]pub struct Session {
pub capabilities: HashMap<String, Value>,
pub accounts: HashMap<String, AccountInfo>,
pub primary_accounts: HashMap<String, String>,
pub username: Username,
pub api_url: JmapUrl,
pub download_url: JmapUrlTemplate,
pub upload_url: JmapUrlTemplate,
pub event_source_url: JmapUrlTemplate,
pub state: State,
pub extra: Map<String, Value>,
}Expand description
JMAP Session object returned by GET /.well-known/jmap (RFC 8620 §2).
Contains only the base RFC 8620 fields. Extension-specific fields
(e.g. JMAP Chat ownerUserId) are surfaced by extension crates that
parse the capabilities and accounts maps.
§extra equality is feature-flag-dependent (bd:JMAP-6r7c.43)
The derived PartialEq / Eq impl’s behaviour on the extra field
depends on the global serde_json/preserve_order feature flag — see
the crate-level note
for the canonical statement.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.capabilities: HashMap<String, Value>Map of capability URI → capability object (RFC 8620 §2).
Values are kept as raw JSON so callers can extract extension-specific capability objects without this crate knowing their schema.
accounts: HashMap<String, AccountInfo>Map of account ID → AccountInfo (RFC 8620 §2).
primary_accounts: HashMap<String, String>Map of capability URI → primary account ID (RFC 8620 §2).
username: UsernameUsername associated with the current credentials (RFC 8620 §2).
§⚠ PII — handle with the same care as a credential (bd:JMAP-6r7c.35, bd:JMAP-6r7c.63)
This field is typically an email address and is therefore PII
under GDPR / CCPA. The Username wrapper redacts both
Display and Debug:
println!("User: {}", session.username)—Displayrenders"[REDACTED]"(perUsername’s impl).format!("hello {}", session.username)— same.tracing::info!(user = %session.username, ...)— same.format!("{:?}", session.username)—DebugrendersUsername("[REDACTED]").
Two paths still expose the raw value, both deliberately explicit at the call site:
Username::expose_unredactedreturns&str. Use only when the wire requires it (constructing anAuthorizationheader that re-uses the username, audit logging under a separate policy).serde_json::to_string(&session)?—SessionderivesSerializefor wire round-trip and emits the raw value verbatim. Callers who want to scrub PII before serialising MUST replace or clear the field first.
If you need a non-PII session-scoped identifier, prefer
primary_accounts account IDs
(RFC 8620 §2’s accountId is server-opaque and is not PII).
api_url: JmapUrlURL for JMAP API POST requests (RFC 8620 §2).
Typed as JmapUrl (plain URL — no template variables) to
distinguish from the template-shaped URL fields below
(bd:JMAP-6r7c.40). Borrow as &str via
JmapUrl::as_str when calling
&str-accepting APIs.
download_url: JmapUrlTemplateURL template for blob downloads (RFC 8620 §2).
URI Template (level 1) containing variables accountId, blobId,
type, and name. Typed as JmapUrlTemplate so it cannot be
confused with api_url at the type level
(bd:JMAP-6r7c.40); expand via
expand_url_template before use.
upload_url: JmapUrlTemplateURL template for blob uploads (RFC 8620 §2).
URI Template (level 1) containing variable accountId. Typed
as JmapUrlTemplate (bd:JMAP-6r7c.40); see
download_url for the type-distinction
rationale.
event_source_url: JmapUrlTemplateURL template for SSE push event stream (RFC 8620 §2, §7.3).
URI Template (level 1) containing variables types, closeafter,
and ping. Typed as JmapUrlTemplate (bd:JMAP-6r7c.40); see
download_url for the type-distinction
rationale.
state: StateOpaque session state token (RFC 8620 §2).
Changes whenever any session property changes. Returned in every API
response as sessionState; clients compare to detect staleness.
extra: Map<String, Value>Catch-all for vendor / site / private extension fields not covered by the typed fields above. Preserves unknown fields across deserialize/serialize round-trip per workspace extras-preservation policy (see workspace AGENTS.md).
Implementations§
Source§impl Session
impl Session
Sourcepub fn primary_account_id(&self, capability: &str) -> Option<&str>
pub fn primary_account_id(&self, capability: &str) -> Option<&str>
Returns the primary account ID for the given capability URI, if set.
Example: session.primary_account_id("urn:ietf:params:jmap:mail")
Sourcepub fn websocket_capability(
&self,
) -> Result<Option<WebSocketCapability>, ClientError>
pub fn websocket_capability( &self, ) -> Result<Option<WebSocketCapability>, ClientError>
Returns the parsed WebSocketCapability for the JMAP WebSocket
transport, if advertised (RFC 8887).
Ok(None)— server does not advertise JMAP WebSocket support.Ok(Some(...))— WebSocket is supported; useresult.urlto connect.Err— capability key is present but the value is malformed.
Sourcepub fn extension_capability<T>(
&self,
capability_uri: &str,
) -> Result<Option<T>, ClientError>where
T: DeserializeOwned,
pub fn extension_capability<T>(
&self,
capability_uri: &str,
) -> Result<Option<T>, ClientError>where
T: DeserializeOwned,
Returns the parsed extension-capability object for capability_uri,
deserialized into the caller-supplied type T (bd:JMAP-6r7c.22).
Use this when an extension defines a typed capability struct (the
way urn:ietf:params:jmap:websocket maps to WebSocketCapability)
and you want a typed view instead of poking at the raw
serde_json::Value in Session::capabilities. Each extension
*-client crate should expose a typed XxxCapability struct and
a thin wrapper like:
pub fn mail_capability(session: &Session) -> Result<Option<MailCapability>, ClientError> {
session.extension_capability("urn:ietf:params:jmap:mail")
}§Returns
Ok(None)— server does not advertise this capability.Ok(Some(_))— capability is advertised AND the value parsed intoT.Err(ClientError::Parse)— capability is advertised but the value could not be deserialised intoT. Indicates either a server bug, a schema-version mismatch, or aTtype that does not match the spec forcapability_uri.
The function only inspects the value when the key is present; an
absent key always returns Ok(None) regardless of T.
Sourcepub fn supports_cid(&self) -> bool
pub fn supports_cid(&self) -> bool
Returns true if the server advertises the JMAP Blob Content
Identifiers extension (draft-atwood-jmap-cid-00).
Checks for presence of capabilities["urn:ietf:params:jmap:cid"].
The capability value object is empty per the draft (§2: “no
capability fields defined at this time”), so the presence of the
key is sufficient — no value-shape check is required.
When true, the server commits to including a sha256 field
(the 64-character lowercase-hex SHA-256 digest of the uploaded
content) on Blob upload responses, and on FileNode objects when
the JMAP FileNode extension is also supported. See
jmap_cid_types::Sha256 for the typed wire shape.
Mirrors the supports_* capability-probe pattern established by
ChatSessionExt::supports_quotas and
ChatSessionExt::supports_refplus in jmap-chat-client.
Trait Implementations§
Source§impl Debug for Session
Manual Debug impl that redacts privacy-sensitive fields (bd:JMAP-sc1b.99).
impl Debug for Session
Manual Debug impl that redacts privacy-sensitive fields (bd:JMAP-sc1b.99).
Session.username is the authenticated user’s identifier — typically a
full email address, which is PII under GDPR/CCPA. Session.state is the
opaque RFC 8620 §2 session-state token; it is not an auth credential, but
it uniquely identifies the client’s session and is the same shape of leak
as logging a session cookie. Both are replaced with "[REDACTED]" /
"[opaque]" in the Debug output.
All other URL/map fields are surfaced — they are deployment metadata and
not credential-grade. AccountInfo.name is redacted by AccountInfo’s
own manual Debug impl, so the accounts map below does not leak
owner emails transitively (bd:JMAP-sc1b.104).