jmap-filenode-types
Serde-annotated Rust types for the JMAP FileNode extension (draft-ietf-jmap-filenode-13). Types only — no method handlers, no async, no network I/O.
What it is
| Type | Description |
|---|---|
FileNode |
The core file-system node object (§3.1) — represents a file, directory, or symlink |
NodeType |
Enum: File, Directory, Symlink, Other(String) |
NodeRole |
Well-known directory roles: Root, Home, Temp, Trash, Documents, Downloads, Music, Pictures, Videos, Other(String) |
FilesRights |
Per-user access rights on a FileNode (mayRead, mayWrite, mayAdmin, etc.) |
FileNodeFilterCondition |
Filter arguments for FileNode/query |
FileNodeCapability |
Account-level capability object for the FileNode extension |
FileNodeProperty |
Enum of legal FileNode property names for properties arrays |
Capability URI constant:
| Constant | Value |
|---|---|
JMAP_FILENODE_URI |
"urn:ietf:params:jmap:filenode" |
What it's for
draft-ietf-jmap-filenode data types, consumed by jmap-filenode-server
(method handlers + the FileNodeBackend trait) and jmap-filenode-client
(typed method bindings). Sibling to jmap-mail-types and
jmap-sharing-types in the workspace's extension-types family.
Filter extensibility
Filter types in this crate — FileNodeFilterCondition and the generic
Filter<T> / Operator re-exported from jmap-types — are intentionally
not extensible via vendor "extras" fields. A filter clause the server does
not understand silently breaks query correctness: the client gets the wrong
set of records back with no error signal. So these types deliberately have no
extra catch-all field.
Vendors who need to filter on custom fields have two options:
- IETF-track (recommended). Use the JMAP Object Metadata extension
(
draft-ietf-jmap-metadata, capability URIurn:ietf:params:jmap:metadata), which defines aMetadata/Annotationcompanion object keyed by(relatedType, relatedId)with capability-declared schema (metadataTypes/maxDepth) and aMetadata/querytextMatchfilter. This is the workspace's recommended path for vendor data that needs to be queryable. Implemented injmap-metadata-types,jmap-metadata-server, andjmap-metadata-client(bd JMAP-06zp). - Pre-IETF escape. If you cannot wait for the metadata draft, escape the
filter tree to
serde_json::Valueor fork theFileNodeFilterConditiontype. Seecrate-jmap-calendars-types/PLAN.mdfor the hybrid sloppy-value pattern.
This policy is part of the workspace extras-preservation policy documented in
the workspace AGENTS.md; the filter-algebra exclusion
decision is bd JMAP-lbdy.
Spec coverage
draft-ietf-jmap-filenode-13 sections implemented:
- §3.1 —
FileNodeobject:id,parentId,blobId,target,size,name,type(serialized as"type"),mediaType,created,modified,shareWith,myRights,role - §3.1 (IANA registries §10.4, §10.5) —
NodeTypeandNodeRoleregistered values - §3.2.3 —
FileNodeFilterConditionquery filter - §1.6 —
FileNodeCapabilityandJMAP_FILENODE_URI
How to use
use ;
// Deserialize a file node.
let file_node: FileNode = from_str?;
assert_eq!;
// Deserialize a directory node.
let dir_node: FileNode = from_str?;
assert_eq!;
# Ok::
How it works
All structs carry #[serde(rename_all = "camelCase")] to produce camelCase JSON field names
as required by the JMAP wire format. Two fields require explicit #[serde(rename)]
annotations because their wire names clash with Rust keywords or conventions:
node_typeis serialized as"type"—typeis a reserved keyword in Rust, so the struct field is namednode_typewith#[serde(rename = "type")].media_typeinFileNodeFilterConditionis serialized as"mediaType"— covered by the top-levelrename_all = "camelCase".
NodeType and NodeRole are string-backed enums with an Other(String) fallback variant
so that unrecognised values from the IANA registry (added after this crate was written)
round-trip without data loss.
Gotchas
ArchiveEntryintegration types for the JMAP Blob Extensions draft (`RFC 9404) are not implemented.
References
- draft-ietf-jmap-filenode-13 — JMAP FileNode (normative for all type definitions)
- RFC 8620 — JMAP Core (Id, State, SetError, request/response shape)