ndovuscim

SCIM PATCH builderno patch applied yetRuns in your browser - nothing leaves this page.
resource id
2819c223-7f76-453a-919d-413861904646
externalId
701984

A PATCH targets one resource matched by its id; externalId is the client's own handle for the same person. Matching the wrong key patches nobody, or patches the wrong user. The guides carry the full matching-key theme.

RFC 7644 · SECTION 3.5.2 PATCH

The PATCH builder

Apply RFC 7644 Section 3.5.2 PATCH operations step by step against the sample resources, with the mutability matrix, the before/after diff, and the Entra default-mode case study.

Runs in your browser - nothing leaves this page.RFC 7644 Section 3.5.2

The playground applies each operation of a PatchOp body in sequence to the sample resources from RFC 7643, rules on the target attribute's mutability, and shows the resource before and after. The presets include the Entra default-mode dialect and the defective response example that erratum 5295 reports. This page is a complement to conformance tools, not another validator: it exists so a single PATCH body can be read op by op against the text, which is where most integration failures actually start.

The history

The failure this playground teaches

PATCH is the partial-update answer, and Section 3.5.2 makes each request a small program: an ordered list of add, remove, and replace operations applied one at a time, each to the result of the previous one, atomic on the first failure. Most PATCH bugs are semantics bugs, not syntax bugs. The body parses; the target attribute is readOnly, so the removal fails mutability. The value is a string where the schema says boolean, so deactivation lands as the truthy text "False". The path filter matched nothing, so the replace answers noTarget. None of these fail at parse time.

The demand survey behind this site found PATCH semantics and deprovisioning at the top of the upvoted technical questions, with Entra quirks the dominant pain cluster: 68 GitHub issues match scim and entra in the title alone (surveyed 2026-11-01). One concrete record: scimmyjs/scimmy #77 (February 2025), PatchOp bodies from Entra for enterprise-extension users throwing exceptions in a conforming library.

The spec has its own PATCH defect: the Section 3.5.2.1 example response for the already-a-member, no-change case carries an Authorization header and a Location header on a 204. Erratum 5295 (Reported) documents it, and the playground rebuilds it as a spot-the-defect exercise.

The application order

Sequential ops, atomic failure

Operations apply in array order, each to the result of the last. The first failure stops the sequence and restores the original resource; a PATCH never half-lands.

PATCH sequential application: operations mutate the working resource in order; a failure at any operation restores the originalPATCH bodyOperations[ ]op 1addop 2replaceop 3removeeach op mutatesthe working copy;diff at the end200 (or 204 no change)all operations applied400 scimType errormutability, noTarget, invalidPath...restore the original resourceatomicity (Section 3.5.2): no operation from a failed request survives -the ops before the failure are rolled back with it
The mechanics

The rules, op by op

add (Section 3.5.2.1). No path: the value object's attributes merge at the resource level. A single-valued attribute with a value is replaced; a multi-valued attribute gains the new values; a complex attribute merges sub-attributes. A value already present in a multi-valued attribute changes nothing, which is the already-a-member case erratum 5295 sits on. Setting a value'sprimary to true resets primary on the other values (Section 3.5.2).

remove (Section 3.5.2.2). No path fails noTarget by definition. A multi-valued attribute with a value filter loses exactly the matching records; a remove that matches nothing succeeds with no change. Removing or emptying a readOnly or required attribute failsmutability, and the attribute counts as unassigned after a removal (RFC 7643 Section 2.5: null, absent, and empty array are one state).

replace (Section 3.5.2.3). A target attribute that does not exist is treated as an add. A value filter that matched no record fails noTarget. Replacing a value with null or an empty array clears it. Complex attributes merge the supplied sub-attributes and leave the rest.

The mutability matrix (Sections 3.5.1 and 3.5.2.4, Table 9). readOnly: every modification fails. immutable: an add is allowed where no value exists, an identical re-assertion is a no-change success, and a different value fails mutability; that is the PUT rule of Section 3.5.1 applied per op. required: clearing or removing fails. PUT itself MUST NOT create: Section 3.5.1 reserves creation for POST, so a PUT to an unknown id answers 404, never 201.

Paths. The path grammar is Figure 7: an optional schema URI, the attribute, an optional bracketed value filter, an optional sub-attribute. A path that does not parse failsinvalidPath (Table 9).

The matching key. A PATCH request names its target by id in the URL;externalId is the client's own handle and is only a match key if the provider's matching rule says so. The playground shows both values for the loaded resource so the two handles stay visible while the ops run.

Case study

The Entra default-mode dialect

Entra ID's provisioning service speaks a documented dialect of PATCH by default: capitalized op values (Add, Replace, Remove), the Boolean activeserialized as the string "False", and group member removal sent as a value array instead of a path filter. Microsoft's SCIM compatibility known-issues page (published 2025-08-25, accessed 2026-11-01) lists the compliant behavior row with "Fixed? No, fix date TBD"; the compliant mode sits behind the tenant-URL flag aadOptscim062020. The presets load both dialect bodies; the engine applies them verbatim and annotates each divergence against the schema and the RFC text, because that is exactly the review a builder performs before wiring a provider.

The lesson generalizes: a SCIM server in production serves at least two clients, and one of them is usually a provisioning service with a dialect. Accepting the dialect is a provider decision; knowing you are speaking one is the builder's job.

Attacks and defenses

What each defense is for

FailureDefenseWhere it is defined
A deactivation that lands as the string "False" and truthy-reads as activeCheck the value type against the schema before applying; the playground annotates Boolean attributes receiving stringsRFC 7643 Section 2.2 types, Section 8.7.1; Entra known-issues page (2025-08-25)
Half-applied PATCHes after an operation fails mid-sequenceAtomicity: the original resource is restored on the first failureRFC 7644 Section 3.5.2
Writes to fields the provider owns: id, meta, server-assigned readOnly valuesThe mutability matrix: readOnly modifications fail with mutabilityRFC 7644 Sections 3.5.2.2 and 3.5.2.4, Table 9
Re-asserting an immutable value slightly differently and corrupting the join keyImmutable accepts only the identical value; a different value fails mutabilityRFC 7644 Section 3.5.1, Table 9
PUT used to create because it looks like an upsertPUT MUST NOT create; an unknown id answers 404RFC 7644 Sections 3.2 and 3.5.1
Member removals silently matching nobody because the filter references the wrong valueA remove that matches nothing succeeds with no change, and the log shows it; the diff shows nothing movedRFC 7644 Section 3.5.2.2
References
  • RFC 7644: System for Cross-domain Identity Management: ProtocolHunt et al. (IETF, September 2015) - the normative text; Sections 3.5.1 and 3.5.2 (with 3.5.2.1-3.5.2.4) define PUT, PATCH, and the mutability rules, Figure 7 the path ABNF, Table 9 the error keywords
  • RFC 7643: SCIM: Core SchemaSection 2.5 defines unassigned; Section 4 carries the resource schemas the mutability checks read; Sections 8.2-8.4 are the sample resources
  • Erratum 5295the reported defect in the Section 3.5.2.1 no-change example response (204 with Authorization and Location headers); the playground's exercise rebuilds it
  • Microsoft Entra SCIM compatibility known issues, Entra provisioning tutorialthe default-mode dialect record: capitalized ops, string "False", value-array member removal, the aadOptscim062020 flag; known-issues page published 2025-08-25, tutorial ms.date 2026-09-15, both accessed 2026-11-01
  • scim-patchthe PATCH-only Node library (0.9.3, published 2026-09-06), credited as prior art for isolated PATCH semantics
  • scimmyjs/scimmy #77 (February 2025); the scim+entra GitHub issue cluster (68 issues by title match)the real-world record, from the GitHub survey behind this lab-site (2026-11-01)