<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
<!ENTITY nbsp "&#160;">
<!ENTITY zwsp "&#8203;">
<!ENTITY nbhy "&#8209;">
<!ENTITY wj "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-calext-jscontact-profiles-05" submissionType="IETF" consensus="true" category="std" xml:lang="en" obsoletes="" updates="" tocInclude="true" symRefs="true" sortRefs="true" version="3">
  <front>
    <title abbrev="JSContact Profiles">Protocol-Specific Profiles for JSContact</title>
    <seriesInfo name="RFC" value="draft-ietf-calext-jscontact-profiles-05"/>
    <author initials="R." surname="Stepanek" fullname="Robert Stepanek">
      <organization>Fastmail</organization>
      <address>
        <postal>
          <extaddr>PO Box 234</extaddr>
          <street>Collins St. West</street>
          <city>Melbourne</city>
          <region>VIC</region>
          <code>8007</code>
          <country>Australia</country>
          <region/>
        </postal>
        <email>rsto@fastmailteam.com</email>
      </address>
    </author>
    <author initials="M." surname="Loffredo" fullname="Mario Loffredo">
      <organization>IIT-CNR</organization>
      <address>
        <postal>
          <street>Via Moruzzi, 1</street>
          <city>Pisa</city>
          <code>56124</code>
          <country>Italy</country>
          <region/>
        </postal>
        <email>mario.loffredo@iit.cnr.it</email>
      </address>
    </author>
    <date year="2025" month="July" day="30"/>
    <area>art</area>
    <workgroup>calext</workgroup>
    <keyword>JSContact</keyword>
    <abstract>
      <t>This document defines JSContact profiles, an IANA registry for named subsets of JSContact elements. It aims to facilitate using JSContact in context of contact data exchange protocols or other use cases, in which supporting all of JSContact semantics might be inappropriate.</t>
    </abstract>
  </front>
  <middle>
    <section anchor="notational-conventions" numbered="true" toc="default">
      <name>Notational Conventions</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" format="default" sectionFormat="of" derivedContent="RFC2119"/> <xref target="RFC8174" format="default" sectionFormat="of" derivedContent="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
      <t>The ABNF definitions in this document use the notations of <xref target="RFC5234"/>. ABNF rules not defined in this document are defined in either <xref target="RFC5234"/> (such as the ABNF for CRLF, WSP, DQUOTE, VCHAR, ALPHA, and DIGIT) or <xref target="RFC6350"/>.</t>
    </section>
    <section anchor="introduction" numbered="true" toc="default">
      <name>Introduction</name>
      <t>The <xref target="RFC9553">JSContact</xref> contact card data model and format is designed for use in address book applications and directory services. Intended as an alternative to the prevalent <xref target="RFC6350">vCard</xref> data format, it covers vCard core semantics and extensions, and provides a rich model for personal names, postal addresses and localization. All JSContact elements are relevant for some contact card use case and, similar to vCard, implementations are expected to support these elements when exchanging contact card information using protocols such as <xref target="RFC6352">CardDAV</xref> and <xref target="RFC9610">JMAP for Contacts</xref>.</t>
      <t>In contrast, other protocols and internet standards might require exchanging <em>some</em> contact card information, but not all of what JSContact provides. <xref target="RFC9553" section="1.7.4"/> outlines how JSContact implementations may ignore unknown JSContact elements, but this only applies to future extensions of <xref target="RFC9553"/>; they are still expected to implement all elements of the core specification. Also, the extensibility of JSContact and the requirement to preserve arbitrary contact elements might not be adequate for some protocols.</t>
      <t>To make use of JSContact under these circumstances, this document defines a new IANA registry for JSContact that allows for registering named subsets of JSContact elements. These subsets are referred to as "JSContact profiles" and are meant to bring the following benefits:</t>
      <ul>
        <li>Protocol designers might be encouraged to use JSContact, rather than coming up with their own contacts format. This facilitates cross-protocol data exchange and migration.</li>
        <li>Different protocols use the same IANA registry to express which JSContact elements they support. This facilitates understanding their commonalities and reusing existing profiles.</li>
        <li>A central registry provides implementors of JSContact libraries with a consistent format documenting which profile supports what elements, rather than having to look up that information from possibly distinctly organized internet drafts.</li>
      </ul>
      <t>This document is organized as follows: <xref target="jscontact-profiles"/> defines JSContact profiles, <xref target="example"/> illustrates JSContact profiles by example, <xref target="iana-considerations"/> summarizes the relevant information for IANA to establish the JSContact Profiles registry.</t>
    </section>
    <section anchor="jscontact-profiles">
      <name>JSContact Profiles</name>
      <t>A JSContact profile is a named, versioned subset of JSContact properties, value types and values. These JSContact elements <bcp14>MAY</bcp14> be further restricted by the profile, but a profile can not loosen restrictions. For example, a profile can define an originally optional property to become mandatory, but it can not make a mandatory property become optional.</t>
      <t>The JSContact elements <bcp14>MUST</bcp14> be registered in the IANA JSContact registry. A JSContact extension <bcp14>MAY</bcp14> define both a new profile and new properties or other elements, as long as they are registered at the same time. A JSContact profile <bcp14>MUST</bcp14> be registered at IANA (see <xref target="iana-considerations"/>). <xref target="name"/> and <xref target="version"/> define how to name and version a JSContact profile, <xref target="properties"/> defines how to define the properties supported by that profile.</t>
      <t>A JSContact object conforms to a profile if all its properties are in the subset of properties defined by that profile and the property values comply with the profile restrictions for that property.</t>
      <section anchor="name">
        <name>Profile Name</name>
        <t>This names the profile. A JSContact profile <bcp14>MUST</bcp14> have a unique name. The name <bcp14>MUST</bcp14> only contain ASCII lowercase alphabetic and numeric characters, optionally separated by hyphens. It <bcp14>MUST</bcp14> start with an alphabetic character and it <bcp14>MUST</bcp14> be of at least 1 character and at most 255 characters in size. Formally, it <bcp14>MUST</bcp14> be a valid "profile-name" defined in <xref target="profile-name-abnf"/>.</t>
      </section>
      <section anchor="version">
        <name>Profile Version</name>
        <t>This defines the current version of the profile. Each profile is versioned independently and version numbers are not related to values in the IANA JSContact Versions registry.  The version identifier <bcp14>MUST</bcp14> be a valid "jsversion" value as defined in <xref target="RFC9553" section="1.9.1"/>. Any addition to the list of <xref target="properties">JSContact properties supported by that profile</xref> <bcp14>MUST</bcp14> update the current version.</t>
        <t>As a note, if a semantic versioning scheme is not adequate for protocol designers making use of JSContact profiles, then an alternative approach is to register a new JSContact profile for each new version.</t>
      </section>
      <section anchor="properties">
        <name>Supported Properties</name>
        <t>A profile defines a list of property entries that together determine the set of properties supported by that profile. Each entry consists of the following elements:</t>
        <dl newline="false">
          <dt>Property Name:</dt>
          <dd>This is the name of the JSContact property that this entry refers to. This <bcp14>MUST</bcp14> be the property name registered in the "JSContact Properties" registry.</dd>
          <dt>Property Context:</dt>
          <dd>This is a comma-separated list of JSContact object types that support this property in this profile. Each of these types <bcp14>MUST</bcp14> also be listed in the property contexts for this property in the "JSContact Properties" registry, but a profile <bcp14>MAY</bcp14> only support the property in a subset of these contexts.</dd>
          <dt>Restricted to be Mandatory:</dt>
          <dd>This restricts the property to be mandatory in the listed property contexts, despite the property originally being defined to be optional in the same contexts. The verbatim value "mandatory" indicates that it is mandatory in this profile, the absence of any value indicates that the property is mandatory or optional according to its original definition. This means that a profile can make an optional property become mandatory, but it can not make a mandatory property become optional.</dd>
          <dt>Restricted Property Type:</dt>
          <dd>This restricts the property value type in the listed property contexts, despite the property originally being defined to have a less restrictive type definition. If set, the value <bcp14>MUST</bcp14> be a type signature as defined in <xref target="RFC9553" section="1.3.2"/> and it <bcp14>MUST</bcp14> be a subtype of the original type signature for these property contexts. The absence of any value indicates that the original type signature applies. This means that a profile can restrict the value types of a property, but it can not add value types for that property.</dd>
          <dt>Restricted Enum Values:</dt>
          <dd>This restricts the enumerated values defined for this property to a subset of those values. The values <bcp14>MUST</bcp14> be listed in the "JSContact Enum Values" registry for this property and context. The allowed values are separated by comma, the absence of any value indicates that all enumerated values are allowed. A profile <bcp14>MAY</bcp14> exclude the default enumerated value of a property, in which case all object instances <bcp14>MUST</bcp14> have this property set to one of the allowed values.</dd>
          <dt>Restricted PatchObject Keys:</dt>
          <dd>This restricts the PatchObject value of this property such that each JSON Pointer key in the PatchObject <bcp14>MUST</bcp14> consist of exactly one <xref target="RFC6901" section="3" sectionFormat="parens">JSON Pointer reference token</xref>. Doing so restricts a PatchObject to only patch properties that are set in the same object and only replace their values entirely. The verbatim value "Yes" indicates that this profile does restrict PatchObject keys, the absence of any value indicates that it does not restrict them. This <bcp14>MUST NOT</bcp14> be set to "Yes", if the property value type is not a PatchObject.</dd>
          <dt>Since Profile Version:</dt>
          <dd>This indicates the highest profile version in which this property definition was added or updated.</dd>
        </dl>
        <t>There <bcp14>MUST NOT</bcp14> be an entry for the "@type" property, it is always supported for any JSContact object in any profile. Similarly, there <bcp14>MUST NOT</bcp14> be an entry for the "version" property of the Card object, it also is supported by any profile.</t>
        <t>The set of supported JSContact properties is then determined by the property entries as follows:</t>
        <ol>
          <li>Initialize the set with all properties of the Card object for which a property entry names this property and contains "Card" in the Property Context. If no property entry contains "Card" in the Property Context, initialize the set with all IANA-registered Card object properties.</li>
          <li>For every property in the set having an object type as value type, add all properties for which a property entry names that property and contains the object type in the Property Context. If no property entry contains the object type in the Property Context, add all IANA-registered properties for that object type to the set.</li>
          <li>Repeat the previous step until no further additions are possible.</li>
        </ol>
        <t>A Card object is supported by the profile, if all its properties are part of the set of supported properties and all property values are valid according to the restrictions defined in the applicable property entries.</t>
      </section>
    </section>
    <section anchor="example">
      <name>Example Profile</name>
      <t>This section provides an example for a JSContact profile, as it would be registered in the IANA JSContact Profiles registry. See <xref target="iana-jscontact-profile-registry-template"/> and <xref target="iana-jscontact-profile-property-template"/> for the exact meaning of each registry item. This profile is just for illustration, it is not registered at IANA.</t>
      <dl newline="true">
        <dt>Name:</dt>
        <dd>jscontact-simple</dd>
        <dt>Profile Version:</dt>
        <dd>1.0</dd>
        <dt>Properties:</dt>
        <dd>
          <table>
            <name>Properties of the "jscontact-simple" profile</name>
            <thead>
              <tr>
                <th>Property Name</th>
                <th>Property Context</th>
                <th>Restricted to be Mandatory</th>
                <th>Restricted Property Type</th>
                <th>Restricted Enum Values</th>
                <th>Restricted PatchObject Keys</th>
                <th>Since Profile Version</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>addresses</td>
                <td>Card</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>emails</td>
                <td>Card</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>kind</td>
                <td>Card</td>
                <td/>
                <td/>
                <td>individual,org</td>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>localizations</td>
                <td>Card</td>
                <td/>
                <td/>
                <td/>
                <td>Yes</td>
                <td>1.0</td>
              </tr>
              <tr>
                <td>name</td>
                <td>Card</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>full</td>
                <td>Address</td>
                <td>mandatory</td>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>components</td>
                <td>Name</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>full</td>
                <td>Name</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>kind</td>
                <td>NameComponent</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
              <tr>
                <td>value</td>
                <td>NameComponent</td>
                <td/>
                <td/>
                <td/>
                <td/>
                <td>1.0</td>
              </tr>
            </tbody>
          </table>
        </dd>
      </dl>
      <t>This profile describes contact cards that can only contain:</t>
      <ul>
        <li>Contact cards for individuals and organizations, but no other kinds such as groups or devices.</li>
        <li>Full postal address lines, but no address components or any other property of the Address object type.</li>
        <li>Full names and name components, but no other properties of the Name object type.</li>
        <li>Email addresses, where all properties of the EmailAddress object are supported.</li>
        <li>Localizations, with the restriction that the PatchObject must only patch properties of the Card object.</li>
      </ul>
      <t>The following Card object conforms to that profile:</t>
      <sourcecode type=""><![CDATA[
{
  "@type": "Card",
  "version": "1.0",
  "name": {
     "components": [
      { "kind": "given", "value": "Hayao" },
      { "kind": "surname", "value": "Miyazaki" }
    ]
  },
  "addresses": {
    "a1": {
      "full": "71 Cherry Court, Somewhere, 123SO, UK"
    }
  },
  "emails": {
    "e1": {
      "address": "hayao@example.com"
    }
  },
  "localizations": {
    "jp": {
      "name": {
        "components": [
         { "kind": "surname", "value": "宮崎" },
         { "kind": "given", "value": "駿" }
        ]
      }
    }
  }
}
]]></sourcecode>
    <t>Note that:</t>
    <ul>
      <li>The Address, Card, Name, and NameComponent object values only contain properties for which a property entry exists in the profile.</li>
      <li>The EmailAddress object contains the "address" property. This is allowed because the profile contains a property entry for the "emails" property of the Card object, but it does not define a property entry for the EmailAddress object type. Consequently, all properties of the EmailAddress object can be set.</li>
      <li>The "full" property of the Address object is set. It is the only property allowed to be set in that profile for Address, and the "full" property is mandatory for this profile.</li>
      <li>The "kind" property of the the NameComponent objects is set to "surname" and "given", respectively. Since the profile does not restrict the enumerated values of this property, all valid NameComponent "kind" property values are supported.</li>
      <li>The "kind" property of the Card object is not set. The profile restricts the enumerated values of this property to "individual" and "org". Since "individual" is the default value for this property, there is no need to set it.</li>
    </ul>
    </section>
    <section anchor="iana-considerations" numbered="true" toc="default">
      <name>IANA Considerations</name>
      <section anchor="iana-jscontact-profile-registry" numbered="true" toc="default">
        <name>Creation of the JSContact Profile Registry</name>
        <t>IANA will add the "JSContact Profile" registry to the "JSContact" registry group originally created in <xref target="RFC9553" section="3.2"/>. The purpose of this new registry is to describe protocol-specific profiles for JSContact data. The registry policy and change procedure of the "JSContact" registry group apply.</t>
        <section anchor="iana-jscontact-profile-registry-template" numbered="true" toc="default">
          <name>JSContact Profile Registry Template</name>
          <t>This template defines how to register a new JSContact profile. It consists of the following items:</t>
          <ul>
            <li>Profile Name</li>
            <li>Profile Version</li>
            <li>Properties</li>
          </ul>
          <t><xref target="name"/> and <xref target="version"/> define the Profile Name and Profile Version item, respectively. For the Properties item, IANA will create a subregistry for each profile name (e.g. "Properties for xyz"), listing the properties supported by that profile. Each entry in that list is registered using the template defined in <xref target="iana-jscontact-profile-property-template"/>.</t>
        </section>
        <section anchor="iana-jscontact-profile-property-template">
          <name>JSContact Profile Property Template</name>
          <t>This template consists of the following items:</t>
          <ul>
            <li>Property Name</li>
            <li>Property Context</li>
            <li>Restricted to be Mandatory</li>
            <li>Restricted Property Type</li>
            <li>Restricted Enum Values</li>
            <li>Restricted PatchObject Keys</li>
            <li>Since Profile Version</li>
          </ul>
          <t>See <xref target="properties"/> for the definitions of these items.</t>
        </section>
        <section>
          <name>Initial Contents of the JSContact Profile Registry</name>
          <t>This document does not define any initial contents for the newly created registries.</t>
        </section>
      </section>
    </section>
    <section anchor="security-considerations" numbered="true" toc="default">
      <name>Security Considerations</name>
      <t>This document does not provide new security considerations. The security considerations of <xref target="RFC9553" section="4" sectionFormat="of"/> apply.</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.5234.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6350.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6352.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6901.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.9553.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9610.xml"/>
      </references>
    </references>
    <section>
      <name>ABNF definition for JSContact Profile Name</name>
      <figure anchor="profile-name-abnf">
        <name>ABNF Rule for JSContact Profile Name</name>
        <sourcecode name="" type="abnf"><![CDATA[
profile-name = LALPHA *254[ ["-"] LALPHA / DIGIT ]

LALPHA       = %x61-7A ; a-z
]]></sourcecode>
      </figure>
    </section>
  </back>
</rfc>
