<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp "&#160;">
  <!ENTITY zwsp "&#8203;">
  <!ENTITY nbhy "&#8209;">
  <!ENTITY wj "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="std"
     consensus="true"
     docName="draft-kushwaha-scim-didvc-binding-01"
     ipr="trust200902"
     submissionType="IETF"
     sortRefs="true"
     symRefs="true"
     tocInclude="true"
     version="3"
     xml:lang="en">
  <front>
    <title abbrev="SCIM DID/VC Binding">SCIM DID/VC Binding Extension</title>
    <seriesInfo name="Internet-Draft" value="draft-kushwaha-scim-didvc-binding-01"/>

    <author fullname="Saurabh Kushwaha" initials="S." surname="Kushwaha">
      <organization>Oracle Corporation</organization>
      <address>
        <postal>
          <city>Pleasanton</city>
          <region>CA</region>
          <country>United States of America</country>
        </postal>
        <email>saurabh.kushwaha@oracle.com</email>
      </address>
    </author>

    <date year="2026" month="August" day="24"/>
    <area>Security</area>
    <workgroup>Internet Engineering Task Force</workgroup>
    <keyword>SCIM</keyword>
    <keyword>DID</keyword>
    <keyword>Verifiable Credential</keyword>
    <keyword>decentralized identity</keyword>

    <abstract>
      <t>This document defines an extension to the System for Cross-domain Identity
      Management (SCIM) for binding SCIM User resources to decentralized identity
      artifacts, including Decentralized Identifiers (DIDs) and Verifiable
      Credentials (VCs). The extension introduces a read-only SCIM schema extension
      for User resources that exposes binding state for discovery, a new SCIM
      resource type named IdentityBinding that records auditable linkage between a
      SCIM user and one or more DIDs and credential references, and an optional
      SCIM schema extension for ServiceProviderConfig that advertises server
      capabilities for DID and VC binding.</t>
      <t>This specification intentionally does not define DID resolution,
      credential issuance, credential transport, or authentication flows. Instead,
      it defines how a SCIM service provider represents, discovers, queries, and
      manages binding state derived from those systems.</t>
      <t>This specification defines binding lifecycle semantics including
      classification of SCIM attribute changes as material to credential
      claims, partial revocation when only a subset of credential claims is
      affected by a SCIM change, three supported lifecycle interleavings
      between SCIM resources and externally issued credentials, and
      propagation of binding state changes via SCIM Events
      <xref target="RFC9967"/>.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="intro">
      <name>Introduction</name>
      <t>SCIM provides a standard protocol and schema model for provisioning and
      managing identities across administrative domains <xref target="RFC7643"/>
      <xref target="RFC7644"/>. SCIM supports new resource types and schema
      extensions, publishes schema metadata through Schema resources, publishes
      resource metadata through ResourceType resources, and provides service
      capability discovery through ServiceProviderConfig <xref target="RFC7643"/>.
      DID Core defines DID documents, verification methods, and proof-purpose
      relationships, while the Verifiable Credentials Data Model defines issuer,
      holder, verifier, status, schema, and validation concepts for verifiable
      credentials <xref target="DID-CORE"/> <xref target="VC-DATA-MODEL-2.0"/>.</t>
      <t>In many deployments, SCIM is the system of record for account lifecycle,
      while DID and VC systems are the system of record for decentralized
      identifiers and cryptographic trust. Today that linkage is usually
      proprietary: implementers invent local attributes, cannot query
      consistently, and cannot express lifecycle events such as DID deactivation,
      key rotation, or VC revocation in an interoperable SCIM form. This
      specification fills that gap by standardizing binding state, not by
      embedding full DID documents or full VC payloads.</t>

      <section anchor="req-language">
        <name>Requirements Language</name>
        <t>The key words <bcp14>MUST</bcp14>, <bcp14>MUST NOT</bcp14>,
        <bcp14>REQUIRED</bcp14>, <bcp14>SHALL</bcp14>, <bcp14>SHALL NOT</bcp14>,
        <bcp14>SHOULD</bcp14>, <bcp14>SHOULD NOT</bcp14>,
        <bcp14>RECOMMENDED</bcp14>, <bcp14>NOT RECOMMENDED</bcp14>,
        <bcp14>MAY</bcp14>, and <bcp14>OPTIONAL</bcp14> in this document are to be
        interpreted as described in BCP 14 <xref target="RFC2119"/>
        <xref target="RFC8174"/> when, and only when, they appear in all
        capitals, as shown here.</t>
        <t>SCIM resource representations in this document are encoded in JSON
        <xref target="RFC8259"/> as required by <xref target="RFC7643"/>.</t>
      </section>

      <section anchor="scope">
        <name>Scope</name>
        <t>This specification applies to SCIM User resources only.</t>
        <t>This specification defines schema and resource representations,
        discovery behavior, filtering, pagination, and PATCH expectations for
        binding resources, and lifecycle and privacy semantics for DID and VC
        bindings.</t>
        <t>This specification does not define DID method semantics, DID
        resolution protocols, VC issuance or presentation protocols, proof
        formats, wallet protocols, or authentication and federation
        replacement.</t>
      </section>

      <section anchor="problem-statement">
        <name>Problem Statement</name>
        <t>A provisioning client frequently needs to answer questions such as:</t>
        <ul>
          <li>Which SCIM user is bound to this DID?</li>
          <li>Which users have an active workforce or employment credential from a trusted issuer?</li>
          <li>What is the effect of credential revocation on the provisioned account?</li>
          <li>Can the service provider support pairwise DIDs, credential status checking, and external verifier delegation?</li>
        </ul>
        <t>Base SCIM does not answer those questions in an interoperable way.</t>
      </section>

      <section anchor="design-goals">
        <name>Design Goals</name>
        <t>This specification has four goals:</t>
        <ol>
          <li>preserve SCIM as the provisioning and lifecycle layer;</li>
          <li>preserve DID and VC systems as the cryptographic trust layer;</li>
          <li>minimize correlation and over-disclosure; and</li>
          <li>define a small interoperable subset that clients and servers can implement consistently.</li>
        </ol>
      </section>
    </section>

    <section anchor="architecture">
      <name>Architecture Overview</name>
      <t>This specification uses a dual-layer model:</t>
      <ul>
        <li>A read-only User extension provides lightweight discoverability.</li>
        <li>A mutable IdentityBinding resource carries binding state, DID references,
        credential references, and lifecycle state.</li>
      </ul>
      <t>A SCIM service provider <bcp14>MAY</bcp14> validate DID and VC evidence
      itself or <bcp14>MAY</bcp14> delegate validation to an external
      verification service. If validation is delegated, the wire protocol between
      the SCIM service provider and the verifier is out of scope. The SCIM
      service provider remains responsible for exposing standards-conformant SCIM
      resources and state transitions.</t>
      <t>A service provider conforming to this specification <bcp14>MUST NOT</bcp14>
      persist full DID documents in SCIM resources and <bcp14>MUST NOT</bcp14>
      persist full VC payloads in SCIM resources. A service provider
      <bcp14>SHOULD</bcp14> store only references, identifiers, validation
      timestamps, and normalized outcomes.</t>
    </section>

    <section anchor="data-model">
      <name>Data Model</name>
      <t>This specification defines three distinct status vocabularies: per-DID
      status reflects DID document state (such as whether a DID has been
      verified or deactivated), per-credential status reflects verifiable
      credential lifecycle state (such as validity-period or revocation
      outcomes), and binding-level status reflects the composite lifecycle of
      the IdentityBinding resource itself. These vocabularies are intentionally
      not unified. The aggregate User.bindingState additionally defines the
      value <tt>none</tt> to indicate a user with no bindings (see
      <xref target="user-extension"/>), which does not appear in any
      resource-level status.</t>

      <section anchor="user-extension">
        <name>User Extension Schema</name>
        <t>The schema URI for the User extension defined by this specification is
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:User</tt>.</t>
        <t>This extension is a derived, read-only projection of the user's
        decentralized identity binding state. Clients do not create bindings by
        writing this extension; they create or modify IdentityBinding
        resources.</t>

        <table anchor="tbl-user-attrs">
          <name>User Extension Attributes</name>
          <thead>
            <tr>
              <th>Attribute</th>
              <th>Type</th>
              <th>MV</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Values</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>primaryDid</td>
              <td>string</td>
              <td>no</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>The verified primary DID currently associated with the user, if any. Derived from the active primary IdentityBinding per the algorithm in <xref target="primarydid-derivation"/>.</td>
            </tr>
            <tr>
              <td>bindingState</td>
              <td>string</td>
              <td>no</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>none, pending, active, suspended, revoked, rejected</td>
              <td>Aggregate state derived from active bindings for the user. The value <tt>none</tt> indicates the user has no associated IdentityBinding resources and does not appear in binding-level status vocabularies.</td>
            </tr>
            <tr>
              <td>bindingRefs</td>
              <td>complex</td>
              <td>yes</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>References to IdentityBinding resources associated with the user.</td>
            </tr>
          </tbody>
        </table>

        <table anchor="tbl-bindingrefs-subattrs">
          <name>bindingRefs Sub-Attributes</name>
          <thead>
            <tr>
              <th>Sub-Attribute</th>
              <th>Type</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Values</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>value</td>
              <td>string</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>-</td>
              <td>The SCIM id of the IdentityBinding resource.</td>
            </tr>
            <tr>
              <td>$ref</td>
              <td>reference</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>-</td>
              <td>URI of the IdentityBinding resource.</td>
            </tr>
            <tr>
              <td>display</td>
              <td>string</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>Human-readable label for the binding.</td>
            </tr>
            <tr>
              <td>primary</td>
              <td>boolean</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>Indicates whether this binding is the source of primaryDid.</td>
            </tr>
            <tr>
              <td>status</td>
              <td>string</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>pending, active, suspended, revoked, rejected</td>
              <td>Current lifecycle state of the referenced binding.</td>
            </tr>
          </tbody>
        </table>

        <t>A conforming server <bcp14>MUST</bcp14> derive primaryDid,
        bindingState, and bindingRefs from IdentityBinding resources,
        <bcp14>MUST NOT</bcp14> allow clients to directly mutate this extension,
        <bcp14>MUST</bcp14> omit primaryDid when no verified primary DID exists,
        and <bcp14>MUST</bcp14> ensure that at most one bindingRefs entry has
        <tt>primary=true</tt>.</t>

        <section anchor="primarydid-derivation">
          <name>Derivation of primaryDid</name>
          <t>A server <bcp14>MUST</bcp14> derive User.primaryDid using the
          following algorithm:</t>
          <ol>
            <li>Collect all IdentityBinding resources whose <tt>user.value</tt>
            matches the target user and whose binding-level <tt>status</tt> is
            <tt>active</tt>.</li>
            <li>From that set, select the binding for which
            <tt>bindingRefs.primary=true</tt> is set in the User extension
            projection. At most one such binding is permitted.</li>
            <li>Within that binding, select the <tt>dids</tt> entry with
            <tt>primary=true</tt> and <tt>status=verified</tt>.</li>
            <li>Set User.primaryDid to the <tt>value</tt> of that DID entry.
            If no such entry exists, omit User.primaryDid.</li>
          </ol>
          <t>A server <bcp14>MUST NOT</bcp14> set User.primaryDid from a
          binding that is not in <tt>active</tt> status, and <bcp14>MUST</bcp14>
          clear User.primaryDid when the binding that sourced it transitions
          out of <tt>active</tt> status or is deleted.</t>
          <t>If multiple active bindings each contain a DID entry with
          <tt>primary=true</tt>, the server <bcp14>MUST</bcp14> reject creation
          or PATCH operations that would produce this ambiguous state with HTTP
          400 and a SCIM error type of <tt>invalidValue</tt>.</t>
        </section>
      </section>

      <section anchor="identitybinding-resource">
        <name>IdentityBinding Resource</name>
        <t>The IdentityBinding resource type uses the endpoint
        <tt>/IdentityBindings</tt> and the schema URI
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:IdentityBinding</tt>.</t>
        <t>An IdentityBinding resource represents the auditable linkage between
        one SCIM User resource and one or more DIDs, together with optional
        references to credentials whose validation influences the state of the
        binding.</t>
        <t>All IdentityBinding resources include the standard SCIM common
        attributes defined in Section 3.1 of <xref target="RFC7643"/>,
        including <tt>id</tt>, <tt>externalId</tt>, and <tt>meta</tt>. The
        <tt>meta.lastModified</tt> timestamp records the time of the most
        recent update to the resource representation. The
        <tt>lastValidationAttempt</tt> attribute defined in this specification
        is distinct from <tt>meta.lastModified</tt>: it records when a
        validation cycle was last run against the DID and credential evidence,
        which may differ from when the resource itself was last written.</t>

        <table anchor="tbl-identitybinding-attrs">
          <name>IdentityBinding Attributes</name>
          <thead>
            <tr>
              <th>Attribute</th>
              <th>Type</th>
              <th>MV</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Values</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>user</td>
              <td>complex</td>
              <td>no</td>
              <td>yes</td>
              <td>immutable</td>
              <td>-</td>
              <td>Reference to the bound SCIM User.</td>
            </tr>
            <tr>
              <td>correlationModel</td>
              <td>string</td>
              <td>no</td>
              <td>yes</td>
              <td>immutable</td>
              <td>pairwise, shared, public</td>
              <td>Privacy expectation for DID reuse across relying parties. See <xref target="correlation-model-relationship"/> for the relationship between this field and per-DID relationship values.</td>
            </tr>
            <tr>
              <td>dids</td>
              <td>complex</td>
              <td>yes</td>
              <td>yes</td>
              <td>readWrite</td>
              <td>-</td>
              <td>DIDs associated with the binding.</td>
            </tr>
            <tr>
              <td>credentials</td>
              <td>complex</td>
              <td>yes</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Credential references associated with the binding.</td>
            </tr>
            <tr>
              <td>status</td>
              <td>string</td>
              <td>no</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>pending, active, suspended, revoked, rejected</td>
              <td>Binding lifecycle state.</td>
            </tr>
            <tr>
              <td>lastValidationAttempt</td>
              <td>dateTime</td>
              <td>no</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>Timestamp of the most recent validation attempt, regardless of outcome. Updated on both successful and failed validation runs. Distinct from meta.lastModified, which reflects resource write time.</td>
            </tr>
            <tr>
              <td>statusReason</td>
              <td>string</td>
              <td>no</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>Human-readable explanation for the current status.</td>
            </tr>
            <tr>
              <td>materialChangeMask</td>
              <td>string</td>
              <td>no</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>Server-computed opaque fingerprint over the User-attribute values that source bound credential claims. Used internally by the server to detect material changes per <xref target="material-change"/>. Servers MUST NOT expose the algorithm used to compute the fingerprint to clients; the value is intended for comparison only.</td>
            </tr>
          </tbody>
        </table>

        <table anchor="tbl-user-subattrs">
          <name>user Sub-Attributes</name>
          <thead>
            <tr>
              <th>Sub-Attribute</th>
              <th>Type</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>value</td>
              <td>string</td>
              <td>yes</td>
              <td>immutable</td>
              <td>The SCIM id of the bound User.</td>
            </tr>
            <tr>
              <td>$ref</td>
              <td>reference</td>
              <td>yes</td>
              <td>immutable</td>
              <td>URI of the bound User.</td>
            </tr>
            <tr>
              <td>display</td>
              <td>string</td>
              <td>no</td>
              <td>readOnly</td>
              <td>Human-readable display name for the user.</td>
            </tr>
          </tbody>
        </table>

        <table anchor="tbl-dids-subattrs">
          <name>dids Sub-Attributes</name>
          <thead>
            <tr>
              <th>Sub-Attribute</th>
              <th>Type</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Values</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>value</td>
              <td>string</td>
              <td>yes</td>
              <td>readWrite</td>
              <td>-</td>
              <td>DID URI.</td>
            </tr>
            <tr>
              <td>relationship</td>
              <td>string</td>
              <td>yes</td>
              <td>readWrite</td>
              <td>primary, pairwise, delegated, recovery</td>
              <td>Role of the DID in the binding. See <xref target="correlation-model-relationship"/> for the distinction between this field and the binding-level correlationModel. The value <tt>recovery</tt> designates a DID that is authorized to execute key recovery operations for the primary DID of the binding, as defined by the applicable DID method; its presence does not affect binding-level status derivation.</td>
            </tr>
            <tr>
              <td>verificationMethod</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>DID URL of the verification method used for proof evaluation.</td>
            </tr>
            <tr>
              <td>proofPurpose</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>authentication, assertionMethod</td>
              <td>DID proof purpose expected for verification.</td>
            </tr>
            <tr>
              <td>controller</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>DID controller identifier when known.</td>
            </tr>
            <tr>
              <td>primary</td>
              <td>boolean</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Indicates the preferred DID for the binding.</td>
            </tr>
            <tr>
              <td>status</td>
              <td>string</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>pending, verified, deactivated</td>
              <td>Per-DID validation status. The value <tt>deactivated</tt> aligns with the DID Core specification's terminal state for a DID document <xref target="DID-CORE"/>.</td>
            </tr>
          </tbody>
        </table>

        <table anchor="tbl-credentials-subattrs">
          <name>credentials Sub-Attributes</name>
          <thead>
            <tr>
              <th>Sub-Attribute</th>
              <th>Type</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Values</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>credentialId</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Identifier of the VC, if present.</td>
            </tr>
            <tr>
              <td>types</td>
              <td>string</td>
              <td>yes</td>
              <td>readWrite</td>
              <td>-</td>
              <td>VC type values relevant to the binding. Multi-valued.</td>
            </tr>
            <tr>
              <td>issuer</td>
              <td>string</td>
              <td>yes</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Issuer identifier, commonly a DID or URI.</td>
            </tr>
            <tr>
              <td>holder</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Holder identifier, if expressed by the ecosystem. Implementers SHOULD omit this field unless explicitly required, as holder DIDs can create correlation risk (see <xref target="privacy-considerations"/>).</td>
            </tr>
            <tr>
              <td>credentialSubjectId</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Credential subject identifier, if available. Implementers SHOULD omit this field unless explicitly required, as subject DIDs can create correlation risk (see <xref target="privacy-considerations"/>).</td>
            </tr>
            <tr>
              <td>statusRef</td>
              <td>reference</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Reference to credential status information.</td>
            </tr>
            <tr>
              <td>schemaRef</td>
              <td>reference</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Reference to credential schema information.</td>
            </tr>
            <tr>
              <td>validFrom</td>
              <td>dateTime</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Start of credential validity, if known.</td>
            </tr>
            <tr>
              <td>validUntil</td>
              <td>dateTime</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>End of credential validity, if known.</td>
            </tr>
            <tr>
              <td>status</td>
              <td>string</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>pending, active, revoked, expired, unknown</td>
              <td>Server-normalized outcome for the credential reference.</td>
            </tr>
            <tr>
              <td>boundClaims</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Multi-valued. Names of credential claims whose truth depends on the bound SCIM User's attributes. Used together with <tt>boundSourceAttributes</tt> to determine material change. See <xref target="material-change"/>.</td>
            </tr>
            <tr>
              <td>boundSourceAttributes</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>-</td>
              <td>Multi-valued. SCIM attribute paths (e.g., <tt>active</tt>, <tt>groups.value</tt>, <tt>urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department</tt>) whose current values source the credential's bound claims.</td>
            </tr>
            <tr>
              <td>materialChangePolicy</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>strict, role-sensitive, advisory</td>
              <td>Policy that determines server behavior when a material change to a source SCIM attribute is detected for this credential. Defaults to <tt>role-sensitive</tt>. See <xref target="material-change"/>.</td>
            </tr>
            <tr>
              <td>partialRevocationMode</td>
              <td>string</td>
              <td>no</td>
              <td>readWrite</td>
              <td>none, claim-scoped, reissuance, claim-flag</td>
              <td>How the credential supports partial revocation when only a subset of bound claims is affected by a material change. Defaults to <tt>none</tt> (whole-credential revocation only). See <xref target="partial-revocation"/>.</td>
            </tr>
          </tbody>
        </table>

        <t>A conforming server <bcp14>MUST</bcp14> require at least one dids
        entry in every IdentityBinding, <bcp14>MUST</bcp14> permit at most one
        dids entry with <tt>primary=true</tt>, <bcp14>MUST</bcp14> require
        <tt>relationship=primary</tt> on any DID entry with
        <tt>primary=true</tt>, and <bcp14>MUST</bcp14> set
        <tt>status=pending</tt> on creation unless the server can validate
        synchronously before returning the resource.</t>
        <t>A conforming server <bcp14>MUST NOT</bcp14> set
        <tt>status=active</tt> unless at least one DID entry has
        <tt>status=verified</tt>. The server <bcp14>MUST</bcp14> update
        User.primaryDid when the binding becomes active or inactive per the
        algorithm in <xref target="primarydid-derivation"/>, and
        <bcp14>MUST</bcp14> reject creation of more than one active
        IdentityBinding containing the same DID value within a single
        administrative scope (the SCIM service provider, or in multi-tenant
        deployments, a single tenant) when the binding's
        <tt>correlationModel</tt> is <tt>pairwise</tt>, regardless of which
        User is referenced.</t>
      </section>

      <section anchor="correlation-model-relationship">
        <name>Relationship Between correlationModel and dids.relationship</name>
        <t>The <tt>correlationModel</tt> attribute on an IdentityBinding and the
        <tt>relationship</tt> sub-attribute on individual DID entries operate at
        different levels of abstraction and are not redundant.</t>
        <t><tt>correlationModel</tt> is a binding-level declaration of the
        privacy expectation for DID reuse across relying parties. A value of
        <tt>pairwise</tt> means the DIDs in this binding are intended for use
        only with this relying party and MUST NOT be reused at other services.
        A value of <tt>shared</tt> means the DIDs may be shared across a defined
        set of relying parties. A value of <tt>public</tt> means the DIDs are
        publicly shareable without restriction.</t>
        <t><tt>dids.relationship</tt> describes the functional role of a specific
        DID within the binding (e.g., <tt>primary</tt> for the main
        authentication DID, <tt>delegated</tt> for a capability-delegation DID,
        <tt>recovery</tt> for a key-recovery DID). A binding with
        <tt>correlationModel=pairwise</tt> may contain multiple DID entries with
        different <tt>relationship</tt> values; the correlation model applies to
        all of them collectively.</t>
        <t>The combination <tt>correlationModel=shared</tt> with
        <tt>relationship=pairwise</tt> on an individual DID entry is permitted
        when one DID in the binding is used only pairwise while others in the
        same binding are shared.</t>
      </section>

      <section anchor="spconfig-extension">
        <name>ServiceProviderConfig Extension</name>
        <t>The schema URI for the ServiceProviderConfig extension defined by this
        specification is
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:ServiceProviderConfig</tt>.</t>
        <t>This extension advertises the server's DID and VC binding capabilities
        without modifying the core ServiceProviderConfig schema.</t>

        <table anchor="tbl-spconfig-attrs">
          <name>ServiceProviderConfig Extension Attributes</name>
          <thead>
            <tr>
              <th>Attribute</th>
              <th>Type</th>
              <th>MV</th>
              <th>Req</th>
              <th>Mutability</th>
              <th>Values</th>
              <th>Description</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>enabled</td>
              <td>boolean</td>
              <td>no</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>-</td>
              <td>Indicates whether DID/VC binding is currently enabled for new IdentityBinding creation. A server MAY deploy the extension schema while setting this to false to indicate temporary suspension of new binding intake.</td>
            </tr>
            <tr>
              <td>verificationDelegation</td>
              <td>string</td>
              <td>no</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>internal, external, mixed</td>
              <td>Whether verification is performed by the SCIM server (<tt>internal</tt>), an external verifier (<tt>external</tt>), or both depending on DID method or credential type (<tt>mixed</tt>). When <tt>mixed</tt>, clients SHOULD NOT assume a specific verification path for any given DID method or credential type without out-of-band knowledge.</td>
            </tr>
            <tr>
              <td>supportedDidMethods</td>
              <td>string</td>
              <td>yes</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>DID methods accepted by the service provider.</td>
            </tr>
            <tr>
              <td>supportedCredentialChecks</td>
              <td>string</td>
              <td>yes</td>
              <td>no</td>
              <td>readOnly</td>
              <td>status, schema, validity, holderBinding</td>
              <td>VC checks the server is capable of evaluating.</td>
            </tr>
            <tr>
              <td>supportedCorrelationModels</td>
              <td>string</td>
              <td>yes</td>
              <td>yes</td>
              <td>readOnly</td>
              <td>pairwise, shared, public</td>
              <td>Correlation models supported by the server.</td>
            </tr>
            <tr>
              <td>supportedMaterialChangePolicies</td>
              <td>string</td>
              <td>yes</td>
              <td>no</td>
              <td>readOnly</td>
              <td>strict, role-sensitive, advisory</td>
              <td>Material change policies (<xref target="material-change-policies"/>) the server is capable of enforcing. A server that omits this attribute is assumed to support only <tt>role-sensitive</tt>. A client MUST NOT declare a <tt>materialChangePolicy</tt> value on a credential entry that the server does not advertise.</td>
            </tr>
            <tr>
              <td>supportedPartialRevocationModes</td>
              <td>string</td>
              <td>yes</td>
              <td>no</td>
              <td>readOnly</td>
              <td>none, claim-scoped, reissuance, claim-flag</td>
              <td>Partial revocation modes (<xref target="partial-revocation"/>) the server supports. A server that omits this attribute is assumed to support only <tt>none</tt>. A client MUST NOT declare a <tt>partialRevocationMode</tt> value on a credential entry that the server does not advertise.</td>
            </tr>
            <tr>
              <td>propagationIntervalSeconds</td>
              <td>integer</td>
              <td>no</td>
              <td>no</td>
              <td>readOnly</td>
              <td>-</td>
              <td>The maximum interval, in seconds, that the server commits to between a SCIM operation affecting a binding and completion of the propagation procedure of <xref target="revocation-propagation"/>. This value bounds the lifecycle-consistency property of <xref target="prop-lifecycle-consistency"/>. Servers SHOULD publish this value; clients and downstream relying parties MAY use it for risk assessment.</td>
            </tr>
          </tbody>
        </table>
      </section>
    </section>

    <section anchor="processing-model">
      <name>Processing Model</name>

      <section anchor="creation">
        <name>Creation</name>
        <t>A client creates a User resource using normal SCIM semantics.</t>
        <t>A client creates an IdentityBinding by POSTing to
        <tt>/IdentityBindings</tt>. The client <bcp14>MUST</bcp14> provide
        <tt>user</tt>, <tt>correlationModel</tt>, and at least one
        <tt>dids</tt> entry. The client <bcp14>MAY</bcp14> include
        <tt>credentials</tt>. The server <bcp14>MUST</bcp14> verify that
        <tt>user.value</tt> references an existing User resource and
        <bcp14>MUST</bcp14> return HTTP 400 with SCIM error type
        <tt>invalidValue</tt> if the reference cannot be resolved.</t>
        <t>Upon creation, the server <bcp14>MUST</bcp14> create the resource in
        <tt>pending</tt> status unless synchronous validation has already
        completed successfully, <bcp14>MUST</bcp14> record normalized validation
        results in per-DID and per-credential status fields, and
        <bcp14>MUST</bcp14> update the derived User extension when binding state
        changes. The server <bcp14>MUST</bcp14> return HTTP 201 with a
        <tt>Location</tt> header pointing to the created resource.</t>
      </section>

      <section anchor="validation">
        <name>Validation</name>
        <t>This specification requires that DID control be verified before a
        binding may become active. How a client presents DID control evidence
        to the SCIM server (e.g., via a challenge-response protocol, a
        Verifiable Presentation submitted in a related flow, or a proof in a
        request header) is out of scope for this specification. Implementations
        <bcp14>SHOULD</bcp14> consult relevant specifications such as
        OpenID for Verifiable Presentations or DIF Presentation Exchange for
        proof transport mechanisms that can be integrated with SCIM deployment.</t>
        <t>To validate DID control, the server or delegated verifier
        <bcp14>MUST</bcp14> resolve the DID and verify that the verification
        method used for proof checking is authorized for the appropriate
        proof-purpose relationship in the DID document <xref target="DID-CORE"/>.
        The server <bcp14>MUST</bcp14> re-resolve DID documents when
        revalidating a binding, and <bcp14>MUST NOT</bcp14> rely on cached DID
        resolution results whose age exceeds the server's configured
        revalidation window.</t>
        <t>To validate a credential reference, the server or delegated verifier
        <bcp14>MUST</bcp14>, where applicable, verify cryptographic integrity,
        evaluate issuer and controller consistency, evaluate validFrom and
        validUntil, evaluate credential status when status information is
        available, and evaluate credential schema when schema information is
        available <xref target="VC-DATA-MODEL-2.0"/>.</t>
        <t>This specification does not define proof formats or verifier APIs.</t>
      </section>

      <section anchor="lifecycle-interleaving">
        <name>Lifecycle Interleaving</name>
        <t>An IdentityBinding can be created at different points in the
        lifecycle of the credentials it references. Three interleaving patterns
        are supported. The protocol behavior differs at the moment of binding
        creation; subsequent lifecycle handling is identical across all three.</t>

        <section anchor="interleaving-resource-first">
          <name>Resource-First</name>
          <t>The SCIM User resource exists, an IdentityBinding is created, and
          a credential is subsequently issued by the credential issuer under
          the coordination of the binding. At the moment of binding creation,
          the <tt>credentials</tt> array MAY be empty or MAY contain credential
          references with <tt>status=pending</tt>. The server
          <bcp14>MUST</bcp14> permit creation of an active binding (i.e.,
          transition to <tt>active</tt>) once at least one
          <tt>dids</tt> entry is verified, even when no credentials are yet
          referenced. Credentials added later via PATCH undergo per-credential
          validation as defined in <xref target="validation"/>.</t>
        </section>

        <section anchor="interleaving-credential-first">
          <name>Credential-First</name>
          <t>The holder already possesses one or more credentials issued at
          some prior time, and an IdentityBinding is created retrospectively to
          bring those credentials under SCIM-managed governance. At the moment
          of binding creation, the <tt>credentials</tt> array contains
          references to existing credentials.</t>
          <t>For credential-first bindings, the server
          <bcp14>MUST</bcp14> validate each referenced credential as defined in
          <xref target="validation"/> and <bcp14>MUST</bcp14> compute the
          <tt>materialChangeMask</tt> attribute as defined in
          <xref target="material-change"/> based on the current state of the
          bound User's attributes. If any referenced credential is found to
          have status <tt>revoked</tt> or <tt>expired</tt>, the server
          <bcp14>MUST</bcp14> record that per-credential status and
          <bcp14>MUST NOT</bcp14> treat it as active. The binding itself
          <bcp14>MAY</bcp14> still transition to <tt>active</tt> if other DID
          and credential checks succeed.</t>
          <t>A credential-first binding does not retroactively alter the prior
          state of the credential; it begins governance at the time the binding
          is created. The server <bcp14>MUST</bcp14> document this temporal
          boundary in deployment guidance, as activity prior to the binding
          may not produce audit records on the SCIM side.</t>
        </section>

        <section anchor="interleaving-joint">
          <name>Joint</name>
          <t>The binding and the credential are created as part of a single
          coordinated issuance flow. The client submits a binding creation
          request together with (or immediately followed by) credential
          issuance at the credential issuer, with the binding acting as the
          governance record from the start. The server's per-credential
          validation occurs against the newly issued credential and the
          <tt>materialChangeMask</tt> is computed from the User attributes
          present at the time of issuance.</t>
          <t>The protocol does not define the wire-level coordination between
          the SCIM service provider and the credential issuer for joint
          issuance; that coordination is out of scope and is expected to use
          existing issuance protocols such as OpenID for Verifiable Credential
          Issuance.</t>
        </section>
      </section>

      <section anchor="state-transitions">
        <name>State Transitions</name>
        <t>The server <bcp14>MUST</bcp14> implement the following binding-state semantics:</t>
        <table anchor="tbl-state-transitions">
          <name>Binding State Transitions</name>
          <thead>
            <tr>
              <th>From</th>
              <th>To</th>
              <th>Condition</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>pending</td>
              <td>active</td>
              <td>Required DID proof and all required credential checks succeed.</td>
            </tr>
            <tr>
              <td>pending</td>
              <td>suspended</td>
              <td>Validation attempt is temporarily inconclusive before the binding has ever been active (e.g., DID resolver unavailable at creation time).</td>
            </tr>
            <tr>
              <td>pending</td>
              <td>rejected</td>
              <td>Validation fails conclusively before the binding has ever been active.</td>
            </tr>
            <tr>
              <td>active</td>
              <td>suspended</td>
              <td>Revalidation is temporarily inconclusive, such as unavailable resolver or unknown credential status.</td>
            </tr>
            <tr>
              <td>active</td>
              <td>revoked</td>
              <td>DID deactivation, credential revocation, or policy failure is confirmed.</td>
            </tr>
            <tr>
              <td>suspended</td>
              <td>active</td>
              <td>Revalidation succeeds.</td>
            </tr>
            <tr>
              <td>suspended</td>
              <td>revoked</td>
              <td>Negative status is later confirmed.</td>
            </tr>
            <tr>
              <td>rejected</td>
              <td>pending</td>
              <td>Client corrects DID evidence via PATCH and requests re-evaluation (see <xref target="reevaluation"/>).</td>
            </tr>
          </tbody>
        </table>
        <t>Once a binding has transitioned to active, subsequent conclusive
        validation failure results in transition to <tt>revoked</tt>, not
        <tt>rejected</tt>. The <tt>rejected</tt> state applies only to
        bindings that never achieved <tt>active</tt> status.</t>
        <t>The revoked state is terminal. To re-establish trust after a
        binding reaches the revoked state, a client <bcp14>MUST</bcp14> create
        a new IdentityBinding resource; a server <bcp14>MUST NOT</bcp14>
        transition a revoked binding back to pending, active, or suspended.</t>
        <t>A server <bcp14>MUST NOT</bcp14> treat unknown or missing validation
        results as equivalent to active.</t>

        <section anchor="reevaluation">
          <name>Re-evaluation of Rejected Bindings</name>
          <t>A client <bcp14>MAY</bcp14> request re-evaluation of a binding in
          the <tt>rejected</tt> state by submitting a SCIM PATCH request that
          replaces or updates one or more <tt>dids</tt> entries (for example,
          correcting an invalid <tt>verificationMethod</tt>, replacing an
          unresolvable DID value, or adding a new DID entry). Upon receiving
          such a PATCH, the server <bcp14>MUST</bcp14> transition the binding
          to <tt>pending</tt> status and <bcp14>MUST</bcp14> initiate a new
          validation cycle. The server <bcp14>MUST NOT</bcp14> require the
          client to delete and recreate the resource solely to trigger
          re-evaluation after a correctable rejection.</t>
        </section>
      </section>

      <section anchor="material-change">
        <name>Material Change Classification</name>
        <t>A material change to a SCIM User is a change to one or more of the
        User's attributes whose values source the bound claims of a credential
        in an associated IdentityBinding. Material changes invalidate, in
        whole or in part, the truth of those bound claims. The protocol
        defines how a service provider classifies SCIM operations as material
        with respect to each credential it governs and how the classification
        drives the binding lifecycle.</t>

        <section anchor="material-change-mask">
          <name>materialChangeMask Computation</name>
          <t>At binding creation, and at every operation that modifies the
          bound User, the server <bcp14>MUST</bcp14> compute, for each
          credential <tt>c</tt> in the binding, a fingerprint over the values
          of the SCIM attributes listed in <tt>c.boundSourceAttributes</tt>.
          The aggregated fingerprint across all bound credentials in the
          binding is stored in <tt>materialChangeMask</tt>. A change to
          <tt>materialChangeMask</tt> between successive validation cycles
          indicates that at least one bound source attribute has changed
          value.</t>
          <t>The fingerprint algorithm is server-internal. A server
          <bcp14>SHOULD</bcp14> use a cryptographic hash over the canonical
          JSON representation of the source attribute values, ordered by
          attribute path. The server <bcp14>MUST NOT</bcp14> expose the
          fingerprint construction in a way that reveals individual attribute
          values to clients that do not otherwise have authorization to read
          them.</t>
        </section>

        <section anchor="material-change-policies">
          <name>Per-Credential Policies</name>
          <t>The behavior of a service provider on detection of a material
          change is determined by the <tt>materialChangePolicy</tt>
          sub-attribute of the affected credential entry. The protocol
          defines three policies:</t>
          <ul>
            <li><tt>strict</tt>: any change to any attribute listed in
            <tt>boundSourceAttributes</tt> for this credential triggers
            transition of the binding's status with respect to this credential
            to <tt>revoked</tt>. If the credential supports partial revocation
            (see <xref target="partial-revocation"/>), only the affected
            claims are revoked.</li>
            <li><tt>role-sensitive</tt>: only changes to attributes mapped to
            claims about role, group membership, employment status, or
            entitlement trigger revocation. Changes to attributes such as
            contact information, postal address, or display name do not.
            A server implementing this policy <bcp14>MUST</bcp14> document
            which SCIM attribute paths are treated as role-related for the
            purpose of this classification, either in deployment documentation
            or through the ServiceProviderConfig extension. This is the
            default policy.</li>
            <li><tt>advisory</tt>: the change is recorded in
            <tt>statusReason</tt> and surfaced via SCIM Events (see
            <xref target="revocation-propagation"/>) but no automatic
            revocation is performed. Operators or downstream automation are
            expected to act on the advisory signal.</li>
          </ul>
          <t>A server <bcp14>MUST</bcp14> apply the policy declared on each
          credential entry independently. Different credentials in the same
          binding <bcp14>MAY</bcp14> declare different policies.</t>
        </section>

        <section anchor="material-change-examples">
          <name>Classification Examples</name>
          <t>The following table illustrates the default
          (<tt>role-sensitive</tt>) classification of common SCIM attribute
          changes. The classification of any specific attribute is
          deployment-dependent and is determined by the
          <tt>boundSourceAttributes</tt> declared on each credential entry.</t>

          <table anchor="tbl-material-classification">
            <name>Example Classification of SCIM Attribute Changes</name>
            <thead>
              <tr>
                <th>Attribute change</th>
                <th>Default classification</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td><tt>active</tt>: true to false</td>
                <td>Material (terminal)</td>
              </tr>
              <tr>
                <td><tt>groups</tt>: removal of a group claimed in credential</td>
                <td>Material</td>
              </tr>
              <tr>
                <td>Enterprise <tt>department</tt>: change</td>
                <td>Material if department is in bound claims</td>
              </tr>
              <tr>
                <td>Enterprise <tt>manager</tt>: change</td>
                <td>Advisory by default</td>
              </tr>
              <tr>
                <td><tt>phoneNumbers</tt>: update</td>
                <td>Not material</td>
              </tr>
              <tr>
                <td><tt>emails</tt>: primary address change</td>
                <td>Advisory by default</td>
              </tr>
              <tr>
                <td><tt>name.formatted</tt>: spelling correction</td>
                <td>Not material</td>
              </tr>
              <tr>
                <td><tt>addresses</tt>: relocation</td>
                <td>Not material</td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>

      <section anchor="partial-revocation">
        <name>Partial Revocation</name>
        <t>A credential MAY carry multiple claims, only some of which are
        invalidated by a given material change. Whole-credential revocation in
        such cases is unnecessarily destructive. The protocol supports partial
        revocation through three mechanisms, selected per credential entry via
        the <tt>partialRevocationMode</tt> sub-attribute.</t>

        <section anchor="partial-claim-scoped">
          <name>Claim-Scoped Status References</name>
          <t>A credential issued under <tt>partialRevocationMode=claim-scoped</tt>
          carries one status reference per bound claim, in addition to (or in
          place of) a whole-credential status reference. When a material
          change affects a subset of bound claims, the server (or the credential
          issuer notified via the propagation procedure of
          <xref target="revocation-propagation"/>) updates only the
          per-claim status references corresponding to the affected claims;
          the whole-credential status remains active.</t>
          <t>The credential format used to express per-claim status references
          is out of scope for this specification. Implementations expecting
          interoperability <bcp14>SHOULD</bcp14> consult the W3C Bitstring
          Status List specification, the SD-JWT family of specifications, or
          other published profiles that define per-claim status semantics for
          the credential format in use.</t>
        </section>

        <section anchor="partial-reissuance">
          <name>Reissuance for Claim Subset</name>
          <t>A credential issued under <tt>partialRevocationMode=reissuance</tt>
          is replaced, on detection of an affecting material change, by a
          newly issued credential containing only the still-true claims; the
          prior credential is revoked in full. The server <bcp14>MUST</bcp14>
          notify the credential issuer via the propagation procedure of
          <xref target="revocation-propagation"/> and <bcp14>MUST</bcp14>
          record the prior credential's reference as historical (using the
          <tt>relationship=historical</tt> indicator if defined by the
          deployment's credentials sub-attribute extensions) and the newly
          issued credential's reference as the current entry. Until the
          credential issuer confirms reissuance, the server
          <bcp14>MUST</bcp14> set the prior credential entry's <tt>status</tt>
          to <tt>pending</tt> revocation by recording the transitional state
          in <tt>statusReason</tt>.</t>
        </section>

        <section anchor="partial-claim-flag">
          <name>Claim-Level Revocation Flag</name>
          <t>For credentials that cannot be split or reissued (for example,
          opaque legacy credentials), a credential entry under
          <tt>partialRevocationMode=claim-flag</tt> carries a server-recorded
          list of revoked claims. The whole-credential status remains active,
          but the binding's <tt>statusReason</tt> records that specific
          claims are revoked. A verifier that consults the binding can observe
          the claim-level state; a verifier that consults only the
          credential's primary status reference cannot. This mechanism is the
          weakest of the three because it depends on the verifier reaching
          the binding directly, but it provides an audit record where the
          other mechanisms are unavailable.</t>
        </section>

        <section anchor="partial-mode-default">
          <name>Default Behavior</name>
          <t>A credential entry that does not declare
          <tt>partialRevocationMode</tt>, or declares
          <tt>partialRevocationMode=none</tt>, is subject to
          whole-credential revocation on any material change classified as
          revocation-triggering by the applicable policy.</t>
        </section>
      </section>

      <section anchor="revocation-propagation">
        <name>Revocation Propagation</name>
        <t>When a SCIM operation on a User causes a transition that affects
        an associated IdentityBinding (deactivation, suspension, material
        change beyond the per-credential threshold, or other policy-driven
        outcome), the server <bcp14>MUST</bcp14> perform the following
        propagation procedure:</t>
        <ol>
          <li>Enumerate all IdentityBinding resources whose
          <tt>user.value</tt> references the changed User and whose
          <tt>status</tt> is <tt>active</tt> or <tt>suspended</tt>.</li>
          <li>For each enumerated binding, recompute the
          <tt>materialChangeMask</tt> per <xref target="material-change-mask"/>
          and classify the change per the policies declared on each
          credential entry.</li>
          <li>For each affected credential entry, apply the per-credential
          policy (revoke the entry, mark the binding revoked, mark
          claims-level revocation per
          <xref target="partial-revocation"/>, or record an advisory).</li>
          <li>If the User is deactivated, the binding's overall <tt>status</tt>
          <bcp14>MUST</bcp14> transition to <tt>revoked</tt> within the
          server's documented propagation interval and the per-credential
          revocation procedure <bcp14>MUST</bcp14> be triggered for every
          credential entry in the binding.</li>
          <li>Emit a SCIM Event per <xref target="RFC9967"/> for each affected
          binding. The event type <bcp14>SHOULD</bcp14> indicate whether the
          change is a material-attribute change, an explicit revocation, or
          an advisory signal.</li>
          <li>For each affected credential entry, notify the credential
          issuer via an out-of-band mechanism. The notification mechanism is
          out of scope for this specification, but implementations
          <bcp14>SHOULD</bcp14> use a SCIM Event subscription, a webhook, or
          another reliable asynchronous channel. The notification
          <bcp14>MUST</bcp14> identify the affected credential, the affected
          claims (if known), and the binding-level outcome.</li>
        </ol>
        <t>The propagation procedure <bcp14>MUST</bcp14> be idempotent: a
        server that re-runs the procedure for the same input
        <bcp14>MUST</bcp14> produce the same SCIM-side outcome and
        <bcp14>SHOULD</bcp14> deduplicate notifications to the same
        credential issuer for the same logical change.</t>
        <t>A conforming server <bcp14>SHOULD</bcp14> publish its propagation
        interval (the maximum time between the SCIM operation and the
        completion of the propagation procedure) via the
        <tt>propagationIntervalSeconds</tt> attribute of the
        ServiceProviderConfig extension (<xref target="spconfig-extension"/>).
        The propagation interval bounds the lifecycle-consistency property
        defined in <xref target="security-properties"/>.</t>

        <section anchor="group-cascade">
          <name>Group Change Cascade</name>
          <t>SCIM Group operations can affect bindings indirectly: a User's
          bound credentials may claim group membership, and a change to the
          Group rather than the User is then the material event. A conforming
          server <bcp14>MUST</bcp14> extend the propagation procedure to
          Group operations as follows:</t>
          <ol>
            <li>On removal of a member from a Group (via PATCH on the Group's
            <tt>members</tt> attribute or via PUT replacement), the server
            <bcp14>MUST</bcp14> treat the removal as a change to the affected
            User's <tt>groups</tt> attribute and run the propagation
            procedure for that User. Only bindings whose credential entries
            list <tt>groups</tt> or <tt>groups.value</tt> among
            <tt>boundSourceAttributes</tt> are affected.</li>
            <li>On deletion or deactivation of a Group, the server
            <bcp14>MUST</bcp14> enumerate the Group's members and run the
            propagation procedure for each affected User. The server
            <bcp14>SHOULD</bcp14> process the cascade asynchronously for
            large groups and <bcp14>MUST</bcp14> complete the cascade within
            its published propagation interval. If the cascade cannot
            complete within the published interval (for example, for groups
            whose membership exceeds an implementation limit), the server
            <bcp14>MUST</bcp14> emit a SCIM Event indicating a delayed
            cascade so that subscribers can distinguish an in-progress
            cascade from a completed one.</li>
            <li>Nested group membership (groups whose members are groups)
            <bcp14>MUST</bcp14> be expanded transitively before enumeration,
            subject to the same completion and signaling requirements.</li>
          </ol>
          <t>The cascade is classification-driven, not unconditional: a Group
          change that no bound credential depends on (per the declared
          <tt>boundSourceAttributes</tt>) results in mask recomputation but
          no revocation. This bounds the blast radius of large Group
          operations to the bindings that actually claim membership.</t>
        </section>
      </section>

      <section anchor="deletion">
        <name>Deletion</name>
        <t>A service provider implementing this specification
        <bcp14>MUST</bcp14> support DELETE for IdentityBinding resources.</t>
        <t>Upon successful deletion of an IdentityBinding resource, the server
        <bcp14>MUST</bcp14> remove the corresponding entry from the associated
        User's <tt>bindingRefs</tt> and <bcp14>MUST</bcp14> clear
        User.primaryDid if the deleted binding was the source of that value.
        The server <bcp14>MUST</bcp14> recalculate User.bindingState after
        deletion.</t>
        <t>A server <bcp14>MAY</bcp14> reject deletion of a binding in
        <tt>active</tt> status and require the client to first transition it to
        a non-active state via PATCH. If such a restriction is imposed, the
        server <bcp14>MUST</bcp14> document this behavior in its
        ServiceProviderConfig or deployment documentation.</t>
        <t>A server <bcp14>MUST</bcp14> return HTTP 204 on successful deletion.</t>
      </section>
    </section>

    <section anchor="protocol-behavior">
      <name>Query, Filtering, PATCH, and Pagination</name>

      <section anchor="filtering">
        <name>Filtering</name>
        <t>SCIM filter expressions and fully qualified attribute notation are
        defined by <xref target="RFC7644"/>. Filter attribute values in request
        URIs <bcp14>MUST</bcp14> be percent-encoded as required by RFC 3986;
        the examples in this section show decoded values for readability.</t>
        <t>A service provider implementing this specification
        <bcp14>MUST</bcp14> support GET filtering on
        <tt>/IdentityBindings</tt> using the <tt>eq</tt> operator for the
        following attributes:</t>
        <ul>
          <li>user.value</li>
          <li>dids.value</li>
          <li>dids.relationship</li>
          <li>credentials.issuer</li>
          <li>credentials.types</li>
          <li>status</li>
          <li>externalId (a common attribute defined in Section 3.1 of <xref target="RFC7643"/> and inherited by all SCIM resource types)</li>
        </ul>
        <t>A service provider implementing this specification
        <bcp14>MUST</bcp14> additionally support the <tt>co</tt> (contains)
        and <tt>pr</tt> (present) operators for the multi-valued string
        attributes <tt>credentials.types</tt> and <tt>dids.value</tt>.
        This allows clients to filter by partial VC type values (e.g.,
        <tt>credentials.types co "EmploymentCredential"</tt>) and to find
        resources that have at least one credential or DID present.</t>
        <t>A service provider implementing the User extension
        <bcp14>MUST</bcp14> support <tt>eq</tt> filtering on
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:User:primaryDid</tt>.</t>
        <t>A service provider implementing this specification
        <bcp14>MUST</bcp14> support the <tt>and</tt> logical operator in
        combination with the attributes above. Support for the <tt>or</tt>
        and <tt>not</tt> operators is <bcp14>OPTIONAL</bcp14>.</t>

        <figure anchor="ex-filter-did">
          <name>Example Filter by DID (values shown decoded; apply percent-encoding in actual requests)</name>
          <sourcecode type="http"><![CDATA[
GET /IdentityBindings?filter=dids.value eq "did:example:123"
          ]]></sourcecode>
        </figure>

        <figure anchor="ex-filter-combined">
          <name>Example Combined Filter</name>
          <sourcecode type="http"><![CDATA[
GET /IdentityBindings?filter=status eq "active" and credentials.issuer eq "did:example:issuer:acme"
          ]]></sourcecode>
        </figure>

        <figure anchor="ex-filter-types">
          <name>Example Filter Using co Operator on Multi-valued types</name>
          <sourcecode type="http"><![CDATA[
GET /IdentityBindings?filter=credentials.types co "EmploymentCredential"
          ]]></sourcecode>
        </figure>

        <figure anchor="ex-user-filter-primarydid">
          <name>Example User Filter by primaryDid</name>
          <sourcecode type="http"><![CDATA[
GET /Users?filter=urn:ietf:params:scim:schemas:extension:didvc:2.0:User:primaryDid eq "did:example:123"
          ]]></sourcecode>
        </figure>
      </section>

      <section anchor="patching">
        <name>PATCH</name>
        <t>A service provider implementing IdentityBinding <bcp14>MUST</bcp14>
        support SCIM PATCH as defined by <xref target="RFC7644"/>. PATCH
        request bodies <bcp14>MUST</bcp14> conform to the PatchOp message
        format defined in Section 3.5.2 of <xref target="RFC7644"/>, which
        requires the <tt>schemas</tt> member and an <tt>Operations</tt> array
        wrapping all individual operation objects.</t>
        <t>Clients <bcp14>SHOULD</bcp14> target explicit paths.</t>
        <t>A server <bcp14>MUST</bcp14> return HTTP 400 with a SCIM error
        type of <tt>mutability</tt> when a PATCH attempts to modify an
        attribute declared as <tt>immutable</tt> (such as <tt>user</tt> or
        <tt>correlationModel</tt>) or <tt>readOnly</tt> (such as
        <tt>status</tt> or <tt>lastValidationAttempt</tt>).</t>

        <figure anchor="ex-patch-primary">
          <name>Example PATCH to Set a Primary DID Flag</name>
          <sourcecode type="json"><![CDATA[
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "path": "dids[value eq \"did:example:123\"].primary",
      "value": true
    }
  ]
}
          ]]></sourcecode>
        </figure>

        <figure anchor="ex-patch-schemaRef">
          <name>Example PATCH to Update a Credential Schema Reference</name>
          <sourcecode type="json"><![CDATA[
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "path": "credentials[issuer eq \"did:example:issuer:acme\"].schemaRef",
      "value": "https://issuer.example/schemas/employment-v1"
    }
  ]
}
          ]]></sourcecode>
        </figure>

        <figure anchor="ex-patch-reevaluation">
          <name>Example PATCH to Correct a DID and Trigger Re-evaluation of a Rejected Binding</name>
          <sourcecode type="json"><![CDATA[
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "path": "dids[value eq \"did:example:old\"].verificationMethod",
      "value": "did:example:abc123#key-2"
    }
  ]
}
          ]]></sourcecode>
        </figure>
      </section>

      <section anchor="pagination">
        <name>Pagination</name>
        <t>List operations for IdentityBinding resources <bcp14>MUST</bcp14>
        support SCIM list pagination as defined by <xref target="RFC7644"/>.
        A service provider <bcp14>MAY</bcp14> additionally support cursor-based
        pagination as defined by <xref target="RFC9865"/>.</t>
      </section>
    </section>

    <section anchor="error-handling">
      <name>Error Handling</name>
      <t>A conforming server <bcp14>MUST</bcp14> return SCIM error responses
      as defined in Section 3.12 of <xref target="RFC7644"/> for all error
      conditions. The following table enumerates error conditions specific to
      this specification.</t>

      <table anchor="tbl-errors">
        <name>Binding-Specific Error Conditions</name>
        <thead>
          <tr>
            <th>Condition</th>
            <th>HTTP Status</th>
            <th>SCIM scimType</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>user.value references a non-existent User</td>
            <td>400</td>
            <td>invalidValue</td>
          </tr>
          <tr>
            <td>Request includes more than one dids entry with primary=true</td>
            <td>400</td>
            <td>invalidValue</td>
          </tr>
          <tr>
            <td>A dids entry has primary=true but relationship is not primary</td>
            <td>400</td>
            <td>invalidValue</td>
          </tr>
          <tr>
            <td>Creation of a pairwise binding with a DID already used in another active pairwise binding within the same administrative scope</td>
            <td>409</td>
            <td>uniqueness</td>
          </tr>
          <tr>
            <td>PATCH attempts to modify an immutable attribute (user, correlationModel)</td>
            <td>400</td>
            <td>mutability</td>
          </tr>
          <tr>
            <td>PATCH attempts to modify a readOnly attribute (status, lastValidationAttempt)</td>
            <td>400</td>
            <td>mutability</td>
          </tr>
          <tr>
            <td>Multiple active bindings with primary=true would result from the operation</td>
            <td>400</td>
            <td>invalidValue</td>
          </tr>
          <tr>
            <td>DELETE attempted on an active binding when the server requires non-active status first</td>
            <td>409</td>
            <td>-</td>
          </tr>
          <tr>
            <td>A credentials entry declares a boundSourceAttributes path that is not a valid SCIM attribute path on the bound User's schemas</td>
            <td>400</td>
            <td>invalidPath</td>
          </tr>
          <tr>
            <td>A credentials entry declares a materialChangePolicy value not advertised in the server's supportedMaterialChangePolicies</td>
            <td>400</td>
            <td>invalidValue</td>
          </tr>
          <tr>
            <td>A credentials entry declares a partialRevocationMode value not advertised in the server's supportedPartialRevocationModes</td>
            <td>400</td>
            <td>invalidValue</td>
          </tr>
        </tbody>
      </table>
    </section>

    <section anchor="discovery-and-deployment">
      <name>Discovery and Deployment</name>
      <t>A service provider implementing this specification <bcp14>MUST</bcp14>
      publish the User extension schema via <tt>/Schemas</tt>,
      <bcp14>MUST</bcp14> publish the IdentityBinding schema via
      <tt>/Schemas</tt>, <bcp14>MUST</bcp14> publish the IdentityBinding
      resource type via <tt>/ResourceTypes</tt>, and <bcp14>SHOULD</bcp14>
      publish the ServiceProviderConfig extension when supported. Examples of
      the expected <tt>/Schemas</tt> and <tt>/ResourceTypes</tt> entries are
      provided in <xref target="app-discovery-examples"/>.</t>
      <t>A SCIM client unaware of this specification will continue to interoperate
      with base User provisioning because unknown schema extensions and unknown
      resource types are discoverable rather than mandatory for unrelated
      operations.</t>
    </section>

    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <section anchor="threat-model">
        <name>Threat Model</name>
        <t>Relevant attackers include a client that attempts to bind a DID it
        does not control, a client that replays stale credentials or proofs, an
        attacker exploiting DID key rotation or deactivation lag, an attacker
        inducing false correlation by reusing identifiers across relying parties,
        a malicious or unexpected issuer, and a compromised or confused
        delegated verifier.</t>
      </section>

      <section anchor="security-properties">
        <name>Security Properties</name>
        <t>A conforming implementation, together with conforming clients and
        a trustworthy credential issuer, is expected to provide the following
        security properties. Each property is stated informally and then
        precisely; the precise statement is the obligation that the protocol
        behavior defined elsewhere in this document is required to satisfy.</t>

        <section anchor="prop-binding-integrity">
          <name>Binding Integrity</name>
          <t>No party other than a SCIM client authorized over both the
          target SCIM User resource and the DID being bound is able to create
          or modify an IdentityBinding linking the two.</t>
          <t>Precisely: if at any time an IdentityBinding resource <tt>B</tt>
          exists with <tt>B.status != revoked</tt>, the binding's
          <tt>user</tt> reference and at least one verified DID entry, then
          at some prior time an authenticated SCIM client with administrative
          authorization over the referenced User and demonstrated control
          over the DID submitted a creation or modification request that
          produced <tt>B</tt>.</t>
        </section>

        <section anchor="prop-revocation-soundness">
          <name>Revocation Soundness</name>
          <t>After the propagation procedure of
          <xref target="revocation-propagation"/> completes for a binding
          that has transitioned to <tt>revoked</tt>, no verifier following
          the credential-status verification procedure of
          <xref target="VC-DATA-MODEL-2.0"/> accepts a credential bound by
          that IdentityBinding.</t>
          <t>This property holds only for credentials that publish
          status references and for verifiers that consult them. The
          protocol does not constrain verifiers that fail to check
          status.</t>
        </section>

        <section anchor="prop-lifecycle-consistency">
          <name>Lifecycle Consistency</name>
          <t>If the principal SCIM User resource referenced by an
          IdentityBinding is in a deactivated state, no binding linked to
          that User remains in the <tt>active</tt> state beyond the server's
          documented propagation interval.</t>
          <t>Precisely: for any IdentityBinding <tt>B</tt> with
          <tt>B.user = u</tt>, if <tt>u.active = false</tt> at time
          <tt>t</tt>, then <tt>B.status != active</tt> at all times
          <tt>t + Delta</tt> and later, where <tt>Delta</tt> is the
          server's documented propagation interval (see
          <xref target="revocation-propagation"/>).</t>
        </section>

        <section anchor="prop-freshness">
          <name>Freshness and Replay Resistance</name>
          <t>A binding creation or modification request cannot be effected
          by replaying a previously legitimate request.</t>
          <t>The protocol relies on DID control proofs that bind to a
          server-issued challenge (see <xref target="did-proof-delivery"/>)
          and on credential validation results that bind to a specific
          validation timestamp (see <xref target="replay-attacks"/>).</t>
        </section>

        <section anchor="prop-por">
          <name>Principal-of-Record Consistency</name>
          <t>At most one principal SCIM User resource is authoritatively
          bound to a given DID under a given correlation model at any one
          time.</t>
          <t>Precisely: for every DID value <tt>d</tt> and every time
          <tt>t</tt>, the number of IdentityBinding resources <tt>B</tt>
          such that <tt>B.dids[i].value = d</tt>,
          <tt>B.dids[i].status = verified</tt>,
          <tt>B.status = active</tt>, and
          <tt>B.correlationModel != pairwise</tt> is at most 1. Under
          <tt>correlationModel = pairwise</tt>, the property is satisfied
          trivially by the uniqueness check defined in
          <xref target="identitybinding-resource"/>.</t>
        </section>
      </section>

      <section anchor="required-mitigations">
        <name>Required Mitigations</name>
        <t>A conforming implementation <bcp14>MUST</bcp14> evaluate DID proof
        authorization against the relevant DID verification relationship at
        verification time, <bcp14>MUST</bcp14> re-resolve DID information when
        revalidating a binding after key rotation or deactivation events are
        possible, <bcp14>MUST</bcp14> treat credential status as a verifier-side
        check when status information is available, <bcp14>MUST</bcp14>
        integrity-protect communication with any delegated verifier and
        authenticate that verifier, <bcp14>MUST</bcp14> apply normal SCIM
        authorization controls to IdentityBinding resources, and
        <bcp14>MUST NOT</bcp14> treat unverified bindings as equivalent to active
        verified bindings.</t>
      </section>

      <section anchor="did-proof-delivery">
        <name>DID Control Proof Delivery</name>
        <t>This specification requires that a SCIM server verify DID control
        before activating a binding, but the mechanism by which a client
        presents DID control evidence is intentionally out of scope.
        Implementers are responsible for defining or adopting a proof transport
        mechanism appropriate for their deployment. Relevant existing
        specifications include OpenID for Verifiable Presentations (OID4VP) and
        the DIF Presentation Exchange specification. The SCIM service provider
        <bcp14>MUST</bcp14> document the proof delivery mechanism it accepts as
        part of its deployment documentation.</t>
        <t>Regardless of the mechanism chosen, a server
        <bcp14>MUST NOT</bcp14> accept a DID control proof that was generated
        for a different relying party, binding resource, or session. Servers
        <bcp14>SHOULD</bcp14> require proof presentations to include a
        challenge or nonce issued by the server to prevent replay of previously
        valid proofs.</t>
      </section>

      <section anchor="replay-attacks">
        <name>Replay Attack Mitigation</name>
        <t>A server <bcp14>SHOULD</bcp14> issue a fresh, single-use nonce or
        challenge when initiating a DID control proof exchange and
        <bcp14>MUST</bcp14> reject proof presentations that do not bind to the
        current challenge. Similarly, credential validation results
        <bcp14>MUST</bcp14> be treated as bound to a specific validation
        timestamp and <bcp14>MUST NOT</bcp14> be replayed from a prior
        successful validation to satisfy a new validation request.</t>
      </section>

      <section anchor="delegated-verifier-trust">
        <name>Delegated Verifier Trust Scope</name>
        <t>When a SCIM service provider delegates DID or VC validation to an
        external verifier, the verifier becomes a critical trust anchor for the
        entire binding model. A compromised or misconfigured delegated verifier
        that returns <tt>status=verified</tt> for any DID can activate
        bindings without genuine cryptographic proof of control. Implementations
        <bcp14>MUST</bcp14> scope the trust granted to a delegated verifier
        to the minimum necessary (e.g., specific DID methods or credential
        types), <bcp14>MUST</bcp14> authenticate the verifier at the transport
        layer, and <bcp14>SHOULD</bcp14> audit verifier responses for anomalies
        such as bulk activation of previously-pending bindings.</t>
      </section>

      <section anchor="did-method-considerations">
        <name>DID Method Considerations</name>
        <t>The security and freshness characteristics of a binding depend on
        the DID methods the server accepts. This specification is
        method-agnostic, but implementers selecting values for
        <tt>supportedDidMethods</tt> should account for the following
        method-class differences.</t>
        <ul>
          <li><t>Statically derived methods (e.g., <tt>did:key</tt>): the DID
          document is computed from the identifier itself and cannot be
          rotated or deactivated. Deactivation of the DID is therefore not
          observable through resolution, and the binding's revocation path
          runs entirely through SCIM-side state and credential status. Such
          methods are appropriate where key compromise is handled by binding
          replacement rather than key rotation.</t></li>
          <li><t>Web-based methods (e.g., <tt>did:web</tt>): resolution
          inherits the trust properties of TLS, DNS, and the hosting domain.
          A domain takeover or web-server compromise permits substitution of
          the DID document, including its verification methods. Servers
          accepting web-based methods <bcp14>SHOULD</bcp14> cache resolved
          documents with bounded TTLs and <bcp14>SHOULD</bcp14> treat
          resolution anomalies (changed keys without corresponding binding
          updates) as validation failures that suspend rather than silently
          re-verify the binding.</t></li>
          <li><t>Ledger-based methods: resolution freshness depends on the
          consistency and finality properties of the underlying ledger,
          which vary by method. Deactivation lag between a controller's
          deactivation request and its observability through resolution
          contributes directly to the binding's effective revocation
          latency and <bcp14>SHOULD</bcp14> be considered part of the
          server's propagation interval when such methods are accepted.</t></li>
        </ul>
        <t>Because re-validation behavior differs by method class, a server
        <bcp14>SHOULD</bcp14> document, per supported method, the events that
        trigger re-validation (TTL expiry, SCIM Events, explicit client
        request) and the failure semantics applied when resolution is
        unavailable (transient suspension per
        <xref target="state-transitions"/> rather than terminal
        revocation).</t>
      </section>
    </section>

    <section anchor="privacy-considerations">
      <name>Privacy Considerations</name>
      <t>DID Core warns that globally unambiguous identifiers create correlation
      risk and recommends pairwise DIDs where correlation is not desired. DID
      Core also warns that even pairwise DIDs can be re-correlated if DID
      documents reuse identical verification methods or correlating service
      endpoints. VC Data Model 2.0 separately warns about identifier-based,
      signature-based, and metadata-based correlation and recommends selective
      disclosure or unlinkable disclosure when strong anti-correlation properties
      are needed <xref target="DID-CORE"/> <xref target="VC-DATA-MODEL-2.0"/>.</t>
      <t>Accordingly, an implementation conforming to this specification
      <bcp14>SHOULD</bcp14> prefer <tt>correlationModel=pairwise</tt> unless
      public reuse is intentionally desired, <bcp14>MUST NOT</bcp14> require
      storage of full VC payloads for routine SCIM provisioning behavior,
      <bcp14>SHOULD</bcp14> store only references and normalized validation
      outcomes, <bcp14>SHOULD</bcp14> avoid exposing DID values to clients that
      do not need them, <bcp14>SHOULD</bcp14> support privacy-preserving
      credential ecosystems that use selective disclosure or unlinkable
      disclosure, and <bcp14>SHOULD</bcp14> ensure that pairwise bindings do not
      accidentally reuse correlating DID material within the same
      administrative domain.</t>
      <t>The <tt>credentials.holder</tt> and
      <tt>credentials.credentialSubjectId</tt> sub-attributes, while optional,
      present a specific privacy risk: both typically contain DID URIs that
      directly identify the subject, and storing them in a SCIM resource makes
      the SCIM server itself a correlation point linking subject DIDs to SCIM
      account identifiers. This partially defeats the anti-correlation goals of
      pairwise DID usage. Implementations <bcp14>SHOULD</bcp14> omit these
      fields unless there is a specific operational requirement for them, and
      <bcp14>SHOULD</bcp14> apply appropriate access controls to limit which
      clients can read them when they are stored.</t>
      <t>Even with pairwise DIDs and minimal storage, the SCIM service provider
      itself becomes a correlation point because it holds the mapping between
      all of a user's pairwise DIDs and their single SCIM account identifier.
      Access to IdentityBinding resources <bcp14>MUST</bcp14> be restricted to
      authorized clients, and implementations <bcp14>SHOULD</bcp14> apply
      data-minimization principles to SCIM query responses (e.g., using SCIM
      attribute projection via the <tt>attributes</tt> or
      <tt>excludedAttributes</tt> query parameters).</t>
    </section>

    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document requests registration of the following URIs in the
      "System for Cross-domain Identity Management (SCIM) Schema URIs" registry
      defined by <xref target="RFC7643"/>:</t>
      <ul>
        <li><tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:User</tt></li>
        <li><tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:IdentityBinding</tt></li>
        <li><tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:ServiceProviderConfig</tt></li>
      </ul>
      <t>The registration templates appear in <xref target="app-registry-templates"/>.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>

      <references>
        <name>Normative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7643.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7644.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8259.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9967.xml"/>

        <reference anchor="DID-CORE" target="https://www.w3.org/TR/did-1.0/">
          <front>
            <title>Decentralized Identifiers (DIDs) v1.0</title>
            <author>
              <organization>World Wide Web Consortium</organization>
            </author>
            <date year="2022" month="July" day="19"/>
          </front>
          <seriesInfo name="W3C Recommendation" value="did-1.0"/>
        </reference>

        <reference anchor="VC-DATA-MODEL-2.0" target="https://www.w3.org/TR/vc-data-model-2.0/">
          <front>
            <title>Verifiable Credentials Data Model v2.0</title>
            <author>
              <organization>World Wide Web Consortium</organization>
            </author>
            <date year="2025" month="May" day="15"/>
          </front>
          <seriesInfo name="W3C Recommendation" value="vc-data-model-2.0"/>
        </reference>
      </references>

      <references>
        <name>Informative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9865.xml"/>
      </references>

    </references>

    <section anchor="app-registry-templates">
      <name>SCIM Schema URI Registration Templates</name>

      <section anchor="app-user-template">
        <name>User Extension</name>
        <t>Schema URI:
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:User</tt></t>
        <t>Schema Name: DID and VC User Extension</t>
        <t>Intended or Associated Resource Type: User</t>
        <t>Purpose: Read-only discovery of DID and VC binding state for a SCIM user.</t>
        <t>Single-value Attributes: <tt>primaryDid</tt>, <tt>bindingState</tt>.</t>
        <t>Multi-valued Attributes: <tt>bindingRefs</tt>.</t>
      </section>

      <section anchor="app-binding-template">
        <name>IdentityBinding</name>
        <t>Schema URI:
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:IdentityBinding</tt></t>
        <t>Schema Name: IdentityBinding</t>
        <t>Intended or Associated Resource Type: IdentityBinding</t>
        <t>Purpose: Mutable binding resource linking a SCIM User to one or more DIDs and optional credential references.</t>
        <t>Single-value Attributes: <tt>user</tt>, <tt>correlationModel</tt>,
        <tt>status</tt>, <tt>lastValidationAttempt</tt>, <tt>statusReason</tt>,
        and <tt>materialChangeMask</tt>.</t>
        <t>Multi-valued Attributes: <tt>dids</tt> and <tt>credentials</tt>.</t>
      </section>

      <section anchor="app-spconfig-template">
        <name>ServiceProviderConfig Extension</name>
        <t>Schema URI:
        <tt>urn:ietf:params:scim:schemas:extension:didvc:2.0:ServiceProviderConfig</tt></t>
        <t>Schema Name: DID and VC ServiceProviderConfig Extension</t>
        <t>Intended or Associated Resource Type: ServiceProviderConfig</t>
        <t>Purpose: Capability discovery for DID and VC binding support.</t>
        <t>Single-value Attributes: <tt>enabled</tt> and
        <tt>verificationDelegation</tt>.</t>
        <t>Multi-valued Attributes: <tt>supportedDidMethods</tt>,
        <tt>supportedCredentialChecks</tt>, and
        <tt>supportedCorrelationModels</tt>.</t>
      </section>
    </section>

    <section anchor="app-examples">
      <name>Examples</name>

      <section anchor="app-example-user">
        <name>Example User Representation</name>
        <figure>
          <sourcecode type="json"><![CDATA[
{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "urn:ietf:params:scim:schemas:extension:didvc:2.0:User"
  ],
  "id": "2819c223-7f76-453a-919d-413861904646",
  "userName": "alice@example.com",
  "name": {
    "givenName": "Alice",
    "familyName": "Ng"
  },
  "urn:ietf:params:scim:schemas:extension:didvc:2.0:User": {
    "primaryDid": "did:example:abc123",
    "bindingState": "active",
    "bindingRefs": [
      {
        "value": "c3a801b0-0b28-4c9c-a7fb-9964a6d916c1",
        "$ref": "/IdentityBindings/c3a801b0-0b28-4c9c-a7fb-9964a6d916c1",
        "display": "Primary workforce binding",
        "primary": true,
        "status": "active"
      }
    ]
  }
}
          ]]></sourcecode>
        </figure>
      </section>

      <section anchor="app-example-binding">
        <name>Example IdentityBinding Representation</name>
        <figure>
          <sourcecode type="json"><![CDATA[
{
  "schemas": [
    "urn:ietf:params:scim:schemas:extension:didvc:2.0:IdentityBinding"
  ],
  "id": "c3a801b0-0b28-4c9c-a7fb-9964a6d916c1",
  "meta": {
    "resourceType": "IdentityBinding",
    "created": "2026-04-20T09:00:00Z",
    "lastModified": "2026-04-21T14:37:00Z",
    "location": "/IdentityBindings/c3a801b0-0b28-4c9c-a7fb-9964a6d916c1",
    "version": "W/\"3694e05afa83191e\""
  },
  "user": {
    "value": "2819c223-7f76-453a-919d-413861904646",
    "$ref": "/Users/2819c223-7f76-453a-919d-413861904646",
    "display": "Alice Ng"
  },
  "correlationModel": "pairwise",
  "dids": [
    {
      "value": "did:example:abc123",
      "relationship": "primary",
      "verificationMethod": "did:example:abc123#key-1",
      "proofPurpose": "authentication",
      "controller": "did:example:abc123",
      "primary": true,
      "status": "verified"
    }
  ],
  "credentials": [
    {
      "credentialId": "urn:uuid:4dd2dc49-9c0f-43f8-b96e-4f4d1f578a2d",
      "types": ["VerifiableCredential", "EmploymentCredential"],
      "issuer": "did:example:issuer:acme",
      "statusRef": "https://issuer.example/status/94567",
      "schemaRef": "https://issuer.example/schema/employment-v1",
      "validFrom": "2026-04-01T00:00:00Z",
      "validUntil": "2027-04-01T00:00:00Z",
      "status": "active",
      "boundClaims": ["employed", "role", "department"],
      "boundSourceAttributes": [
        "active",
        "groups.value",
        "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department"
      ],
      "materialChangePolicy": "role-sensitive",
      "partialRevocationMode": "claim-scoped"
    }
  ],
  "status": "active",
  "lastValidationAttempt": "2026-04-21T14:37:00Z",
  "statusReason": "DID control and required credential checks succeeded",
  "materialChangeMask": "sha256:9c8b4a..."
}
          ]]></sourcecode>
        </figure>
      </section>

      <section anchor="app-example-spconfig">
        <name>Example ServiceProviderConfig Representation</name>
        <figure>
          <sourcecode type="json"><![CDATA[
{
  "schemas": [
    "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",
    "urn:ietf:params:scim:schemas:extension:didvc:2.0:ServiceProviderConfig"
  ],
  "patch": { "supported": true },
  "filter": { "supported": true, "maxResults": 200 },
  "sort": { "supported": false },
  "etag": { "supported": true },
  "urn:ietf:params:scim:schemas:extension:didvc:2.0:ServiceProviderConfig": {
    "enabled": true,
    "verificationDelegation": "mixed",
    "supportedDidMethods": ["did:web", "did:key", "did:example"],
    "supportedCredentialChecks": ["status", "schema", "validity", "holderBinding"],
    "supportedCorrelationModels": ["pairwise", "shared", "public"],
    "supportedMaterialChangePolicies": ["strict", "role-sensitive", "advisory"],
    "supportedPartialRevocationModes": ["none", "claim-scoped", "reissuance"],
    "propagationIntervalSeconds": 300
  }
}
          ]]></sourcecode>
        </figure>
      </section>
    </section>

    <section anchor="app-discovery-examples">
      <name>Discovery Examples</name>

      <section anchor="app-resourcetype-example">
        <name>Example /ResourceTypes Entry for IdentityBinding</name>
        <t>The following illustrates the ResourceType entry a conforming server
        MUST publish at <tt>/ResourceTypes</tt> for the IdentityBinding resource.</t>
        <figure>
          <sourcecode type="json"><![CDATA[
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"],
  "id": "IdentityBinding",
  "name": "IdentityBinding",
  "endpoint": "/IdentityBindings",
  "description": "Auditable linkage between a SCIM User and one or more DIDs and credential references.",
  "schema": "urn:ietf:params:scim:schemas:extension:didvc:2.0:IdentityBinding",
  "meta": {
    "resourceType": "ResourceType",
    "location": "/ResourceTypes/IdentityBinding"
  }
}
          ]]></sourcecode>
        </figure>
      </section>

      <section anchor="app-schema-example">
        <name>Example /Schemas Entry for the User Extension</name>
        <t>The following illustrates the Schema entry a conforming server
        MUST publish at <tt>/Schemas</tt> for the User extension defined by
        this specification. The entry for the IdentityBinding schema and the
        ServiceProviderConfig extension schema follow the same pattern.</t>
        <figure>
          <sourcecode type="json"><![CDATA[
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
  "id": "urn:ietf:params:scim:schemas:extension:didvc:2.0:User",
  "name": "DID and VC User Extension",
  "description": "Read-only discovery of DID and VC binding state for a SCIM user.",
  "attributes": [
    {
      "name": "primaryDid",
      "type": "string",
      "multiValued": false,
      "required": false,
      "mutability": "readOnly",
      "returned": "default"
    },
    {
      "name": "bindingState",
      "type": "string",
      "multiValued": false,
      "required": true,
      "canonicalValues": ["none", "pending", "active", "suspended", "revoked", "rejected"],
      "mutability": "readOnly",
      "returned": "default"
    },
    {
      "name": "bindingRefs",
      "type": "complex",
      "multiValued": true,
      "required": false,
      "mutability": "readOnly",
      "returned": "default",
      "subAttributes": [
        { "name": "value", "type": "string", "required": true, "mutability": "readOnly" },
        { "name": "$ref", "type": "reference", "required": true, "mutability": "readOnly" },
        { "name": "display", "type": "string", "required": false, "mutability": "readOnly" },
        { "name": "primary", "type": "boolean", "required": false, "mutability": "readOnly" },
        {
          "name": "status",
          "type": "string",
          "required": true,
          "canonicalValues": ["pending", "active", "suspended", "revoked", "rejected"],
          "mutability": "readOnly"
        }
      ]
    }
  ],
  "meta": {
    "resourceType": "Schema",
    "location": "/Schemas/urn:ietf:params:scim:schemas:extension:didvc:2.0:User"
  }
}
          ]]></sourcecode>
        </figure>
      </section>
    </section>

    <section anchor="app-existing-mechanisms" numbered="false">
      <name>Relationship to Existing Mechanisms (Informative)</name>
      <t>Several deployed mechanisms address adjacent parts of the problem
      this specification targets. This appendix summarizes why each is
      complementary to, rather than a substitute for, the binding layer, and
      how a deployment composes them.</t>
      <ul>
        <li><t>Credential status mechanisms (W3C Bitstring Status List and
        similar): provide the publication channel through which a verifier
        learns a credential's revocation state. They do not specify when the
        issuer should update the status in response to provisioning events.
        This specification supplies that trigger: the propagation procedure
        of <xref target="revocation-propagation"/> drives issuer
        notification from SCIM lifecycle events, and the status mechanism
        remains the channel through which the resulting update reaches
        verifiers.</t></li>
        <li><t>Security Event Tokens and shared-signals profiles (CAEP,
        RISC): propagate session- and account-level signals to subscribed
        relying parties. They invalidate live sessions but do not affect
        credentials in a holder's possession, and they leave the mapping
        from account events to credential-level actions unspecified. This
        specification defines that mapping (material change classification,
        <xref target="material-change"/>) and uses SCIM Events
        <xref target="RFC9967"/> as one transport for the resulting
        signals.</t></li>
        <li><t>OAuth token introspection and revocation: apply to tokens
        issued by a specific authorization server and consumed within its
        trust boundary. A verifier consuming a holder-presented credential
        has no introspection endpoint to consult. The IdentityBinding
        resource provides the SCIM-side record from which an equivalent
        freshness signal can be derived for credentials.</t></li>
        <li><t>Identity governance and administration platforms: operate the
        approval, attestation, and recertification workflows over directory
        state. They are the natural clients of this specification: an
        IGA-driven provisioning decision can create or revoke an
        IdentityBinding via standard SCIM operations, gaining an auditable
        credential-governance record without bespoke integration to each
        credential issuer.</t></li>
      </ul>
      <t>In combination: IGA and SCIM clients decide; the IdentityBinding
      records the decision and its lifecycle; the propagation procedure
      notifies issuers; status mechanisms publish the outcome; SET-based
      signals carry the event to subscribers. The binding layer is the
      governance contract that connects the other mechanisms.</t>
    </section>

    <section anchor="app-changes" numbered="false">
      <name>Document History</name>

      <section anchor="app-changes-01-02" numbered="false">
        <name>Changes Since -01</name>
        <ul>
          <li>Added <tt>supportedMaterialChangePolicies</tt>,
          <tt>supportedPartialRevocationModes</tt>, and
          <tt>propagationIntervalSeconds</tt> to the ServiceProviderConfig
          extension (<xref target="spconfig-extension"/>), making the
          capabilities introduced in -01 discoverable, and updated the
          propagation procedure to reference the concrete attribute.</li>
          <li>Added <xref target="group-cascade"/> specifying propagation
          cascade behavior for SCIM Group operations: member removal, group
          deletion and deactivation, transitive expansion of nested groups,
          and delayed-cascade signaling for large groups.</li>
          <li>Added three error conditions for the attributes introduced in
          -01: invalid <tt>boundSourceAttributes</tt> paths, and undeclared
          <tt>materialChangePolicy</tt> or <tt>partialRevocationMode</tt>
          values.</li>
          <li>Added <xref target="did-method-considerations"/> discussing
          the security and freshness characteristics of statically derived,
          web-based, and ledger-based DID method classes and their effect on
          re-validation behavior.</li>
          <li>Added <xref target="app-existing-mechanisms"/>, an informative
          appendix positioning this specification relative to credential
          status mechanisms, shared-signals profiles, token introspection,
          and IGA platforms.</li>
          <li>Updated the example ServiceProviderConfig representation to
          illustrate the new discovery attributes.</li>
        </ul>
      </section>

      <section anchor="app-changes-00-01" numbered="false">
        <name>Changes Since -00</name>
      <t>This appendix summarizes substantive changes since the
      <tt>-00</tt> revision of this document.</t>
      <ul>
        <li>Added the <tt>materialChangeMask</tt> attribute to the
        IdentityBinding resource.</li>
        <li>Added the <tt>boundClaims</tt>, <tt>boundSourceAttributes</tt>,
        <tt>materialChangePolicy</tt>, and <tt>partialRevocationMode</tt>
        sub-attributes to the <tt>credentials</tt> sub-attribute of the
        IdentityBinding resource.</li>
        <li>Added <xref target="lifecycle-interleaving"/> defining
        resource-first, credential-first, and joint lifecycle interleaving
        patterns between SCIM resources and externally issued credentials.</li>
        <li>Added <xref target="material-change"/> defining material change
        classification, the <tt>materialChangeMask</tt> fingerprint, the
        per-credential <tt>strict</tt>, <tt>role-sensitive</tt>, and
        <tt>advisory</tt> policies, and an example classification table.</li>
        <li>Added <xref target="partial-revocation"/> defining three
        partial-revocation mechanisms: claim-scoped status references,
        reissuance for claim subset, and claim-level revocation flag.</li>
        <li>Added <xref target="revocation-propagation"/> specifying the
        propagation procedure from SCIM lifecycle events to credential-level
        status updates, including required emission of SCIM Events per
        <xref target="RFC9967"/> and required out-of-band issuer
        notification.</li>
        <li>Added <xref target="security-properties"/> enumerating five
        named security properties of the protocol: binding integrity,
        revocation soundness, lifecycle consistency, freshness and replay
        resistance, and principal-of-record consistency.</li>
        <li>Promoted <xref target="RFC9967"/> to a normative reference.</li>
        <li>Updated the example IdentityBinding representation in
        <xref target="app-example-binding"/> to illustrate the new
        attributes.</li>
      </ul>
      </section>
    </section>

    <section anchor="acknowledgments" numbered="false">
      <name>Acknowledgments</name>
      <t>The author thanks contributors and reviewers whose feedback will be
      acknowledged in future revisions of this document.</t>
    </section>
  </back>
</rfc>
