#[non_exhaustive]pub struct ChangesResponse {
pub account_id: Id,
pub old_state: State,
pub new_state: State,
pub has_more_changes: bool,
pub created: Vec<Id>,
pub updated: Vec<Id>,
pub destroyed: Vec<Id>,
pub updated_properties: Option<Vec<String>>,
pub extra: Map<String, Value>,
}Expand description
RFC 8620 §5.2 — Foo/changes response shape.
Reports the ids of objects created, updated, or destroyed since
old_state. If has_more_changes is true, the client should call
/changes again with since_state = new_state to retrieve the next
page; otherwise new_state is the current state.
§Extension fields and the foundation-coupling trade-off
Some JMAP data-type extensions add an updatedProperties field to
their /changes response shape:
- RFC 8621 §2.2 (
Mailbox/changes): set when onlytotalEmails/unreadEmails/totalThreads/unreadThreadschanged. - RFC 9425 §5 (
Quota/changes): set when only theusedproperty changed.
For all other /changes methods (RFC 8621 §3.2 Thread/changes,
§4.3 Email/changes, plus every extension /changes method not
listed above) the server omits the field, and clients deserialize
it as None.
Architectural decision (bd:JMAP-6xs8.5). Carrying
updatedProperties on this base type, rather than on per-extension
MailboxChangesResponse / QuotaChangesResponse newtypes, is a
deliberate workspace trade-off:
- Chosen shape: one foundation
ChangesResponsewith anOption<Vec<String>>field that two extensions populate. - Alternative (a):
ChangesResponse<Ext = ()>generic with a per-type extension struct. Rejected: would force every/changeshandler in every extension server to thread theExttype parameter, and the 30-crate canonical-template family would have to settle on a single way to express “no extension” vs “Mailbox extension” vs “Quota extension”. - Alternative (b):
MailboxChangesResponseandQuotaChangesResponseas separate types injmap-mail-typesand a futurejmap-quota-types, delegating to a shared base via composition. Rejected: would duplicate the seven base fields (accountId,oldState,newState,hasMoreChanges, three id vectors) at every extension type, and require parallel handler / parse / dispatch code. - Alternative (c): leave
updatedPropertiesas an extras flatten entry that mail/quota types explicitly read viaresp.extra.get("updatedProperties"). Rejected: loses typed access, and the field is RFC-defined (not vendor / site), so the extras pattern (workspace AGENTS.md “Extras-preservation policy”) is the wrong tool.
Drift risk acknowledged: every future /changes extension
(jmap-sharing, jmap-tasks, etc.) will face pressure to add its
own typed field here “for parity”. Each such field would extend
this foundation type by one more extension-specific column.
Cautionary precedent: bd:JMAP-kt5k removed eight cap-advertising
fields from the chat capability after they accreted there for the
same parity-pressure reason. New /changes extension fields land
here only when the field is RFC-defined and the alternative shapes
above have been re-evaluated against the new use case; a vendor
extension belongs in the extras catch-all, not on the typed
surface.
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.account_id: IdThe account the response refers to.
old_state: StateThe state token the client passed in.
new_state: StateThe current (or next-page) state token.
has_more_changes: booltrue if there are more changes the client must page through.
created: Vec<Id>Ids of objects created since old_state.
updated: Vec<Id>Ids of objects updated since old_state.
destroyed: Vec<Id>Ids of objects destroyed since old_state.
updated_properties: Option<Vec<String>>Optional list of property names that changed (RFC 8621 §2.2,
RFC 9425 §5). Servers MAY set this for Mailbox/changes and
Quota/changes responses when the only changes are to a small
known subset of properties; clients can then back-reference
/updatedProperties into a follow-up Mailbox/get or
Quota/get to fetch only those fields. For all other /changes
methods the field is absent on the wire and None here.
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).
Trait Implementations§
Source§impl Clone for ChangesResponse
impl Clone for ChangesResponse
Source§fn clone(&self) -> ChangesResponse
fn clone(&self) -> ChangesResponse
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more