Translates a SCIM 2.0 PATCH request body (RFC 7644 §3.5.2) into a structured input describing both attribute updates and relationship-level operations:
%{
attrs: %{first_name: "Alicia"},
relationships: [
{:append, :memberships, [%{user_id: "u1"}]},
{:remove_where, :memberships, %{user_id: %{eq: "u2"}}}
]
}The router applies attrs via the resource's update action and each
relationship op as either a manage_relationship/4 call or a custom
load+destroy/update step.
Supported operations
add/replacewith no path — value is treated as a partial SCIM resource and decoded viaAshScim.Decoder. Only attribute changes are applied (relationship arrays in path-less ops are ignored, since the semantics of "add a partial resource that includes a member list" aren't well-defined).add/replace/removewith a simple path (e.g.active,name.givenName) — maps to the corresponding Ash attribute.add path: "emails" value: [...]— append-style relationship op.replace path: "emails" value: [...]— full-replace relationship op.remove path: "emails[value eq "x"]"— load-and-destroy op against the related resource matching the bracket filter.
When the multivalued declares mirror_primary_to:, the patch result also
carries a :mirror_sync post-op (or a synchronously-computed attr write
for replace) that keeps the parent's mirrored scalar in sync with the
primary entry's value.
Summary
Functions
Public schema URN for the PatchOp message.
Build the structured patch input from a PATCH body. Returns
{:ok, %{attrs: …, relationships: …}} or {:error, reason}.
Types
@type op() :: :add | :remove | :replace