<?xml version="1.0" encoding="utf-8"?>
<!-- name="GENERATOR" content="github.com/mmarkdown/mmark Mmark Markdown Processor - mmark.miek.nl" -->
<rfc version="3" ipr="trust200902" docName="draft-newton-regext-rdap-simple-redaction-01" submissionType="IETF" category="std" xml:lang="en" xmlns:xi="http://www.w3.org/2001/XInclude" indexInclude="true">

<front>
<title abbrev="simple-redaction">RDAP Simple Redaction</title><seriesInfo value="draft-newton-regext-rdap-simple-redaction-01" stream="IETF" status="standard" name="Internet-Draft"></seriesInfo>
<author initials="A." surname="Newton" fullname="Andy Newton"><organization>ICANN</organization><address><postal><street></street>
</postal><email>andy@hxr.us</email>
</address></author><date/>
<area>Applications and Real-Time Area (ART)</area>
<workgroup>Registration Protocols Extensions (regext)</workgroup>

<abstract>
<t>This document defines a simple redaction extension for the Registration Data Access Protocol
(RDAP).</t>
</abstract>

</front>

<middle>

<section anchor="background"><name>Background</name>
<t>This document defines a simple redaction extension for redacting information from Registration
Data Access Protocol (RDAP) responses. This extension offers a much simpler approach to the
redaction of information than RFC 9537. Additionally, it has several advantages over RFC 9537:</t>

<ul spacing="compact">
<li>The reasons for a redaction may be specified in multiple languages.</li>
<li>All redactions may be processed by a client programmatically.</li>
<li>String data may be partially redacted.</li>
<li>It re-uses remarks and notices from <xref target="RFC9083"></xref> and is backward-compatible with clients that do no support this extension.</li>
<li>Re-use of remarks and notices enables linking of redacted data to redaction policies.</li>
<li>In most cases, notifications of redacted data is passed to the user with clients that do not support this extension.</li>
<li>Clients are not required to evaluate complicated and error-prone JSONPath expressions.</li>
<li>Usage in RDAP object containers, such as RDAP search results or bulk Whois-like documents, does not require rewriting of JSONPath expressions.</li>
</ul>
<t>The following is an example of an RDAP response using simple redaction:</t>

<artwork><![CDATA[{
  "rdapConformance" : [ "Rdap_level_0", “simpleRedaction” ],
  "objectClassName" : "entity",
  "handle":"////REDACTED_HANDLE////",
  "vcardArray":[
    "vcard",
    [
      ["version", {}, "text", "4.0"],
      ["fn", {}, "text", "////REDACTED_FULL_NAME////"],
      ["email",
        { "type":"work" },
        "text", "redacted_email@redacted.invalid"
      ]
    ]
  ],
  "remarks": [
    {
      "description": [
        "These values have been redacted according to policy."
      ],
      “simpleRedaction_keys”: {
        “keys”: [
          “////REDACTED_HANDLE////”,
          “////REDACTED_FULL_NAME////”,
          “redacted_email@redacted.invalid”
        ]
      }
    }
  ]
}

]]></artwork>
<t>The methods for noting redactions in this extension cannot redact numbers or booleans in
JSON arrays. However, there are no known RDAP data structures either in <xref target="RFC9083"></xref> or any
RDAP extension that use arrays containing numbers or booleans.</t>
<t>Additionally, there are no known redaction policies that require anything more than redaction of string data.</t>
</section>

<section anchor="redaction_keys"><name>Redaction Keys</name>
<t>Simple redaction allows a server to define a set of keys, each used to signify when data
has been redacted. Clients use these keys to notify a user of redacted information.</t>

<section anchor="redaction-of-data-in-strings"><name>Redaction of Data in Strings</name>
<t>Data found in strings is the most common data type to be redacted. As of this writing,
there are no known redaction policies that require the redaction of non-string data.</t>

<section anchor="unstructured_keys"><name>Unstructured Text</name>
<t>Keys signifying redaction for unstructured text, i.e. free form text, take the form of <tt>////REDACTION_KEY////</tt>.
These keys begin with four forward-slash characters (&quot;////&quot;), followed by one or more of the upper and lower case characters
<tt>A</tt> through <tt>Z</tt>, <tt>0</tt> through <tt>9</tt>, hyphen (&quot;-&quot;), or under-bar (&quot;_&quot;), followed by four more forward-slash characters.</t>
<t>The following example demonstrates redaction of the full name value from a jCard (<xref target="RFC7095"></xref>) array:</t>

<artwork><![CDATA[["fn", {}, "text", "////REDACTED_FULL_NAME////"]    
]]></artwork>
<t>These keys may be placed in a string with other characters thus allowing for the partial redaction of a string:</t>

<artwork><![CDATA["Alice ////LAST_NAME_REDACTION////"
]]></artwork>
</section>

<section anchor="telephone-numbers"><name>Telephone Numbers</name>
<t>Keys for telephone numbers may either be represented as text or &quot;tel&quot; URIs. Both jCard and JSContact allow
telephone numbers to be represented in either format.</t>

<section anchor="telephone-numbers-as-text"><name>Telephone Numbers as Text</name>
<t>Keys for telephone numbers represented as text use the same format as unstructured text (see <xref target="unstructured_keys"></xref>).</t>
<t>The following is an example for jCard (<xref target="RFC7095"></xref>).</t>

<artwork><![CDATA[["tel", {}, "text", "////TELEPHONE_REDACTION////"]    
]]></artwork>
</section>

<section anchor="tel_uri_keys"><name>TEL URIs</name>
<t>Keys for use in &quot;tel&quot; URIs (<xref target="RFC3966"></xref>) use local numbers with the phone context of &quot;redacted.example&quot;.
These keys begin with four dash characters (&quot;----&quot;), followed by one or more HEXDIGITs as defined by <xref target="RFC3966"></xref>,
followed by four more dash characters.</t>
<t>The following is an example of a &quot;tel&quot; URI used in a jCard array:</t>

<artwork><![CDATA[["tel", {}, "uri", "tel:----0000000----;extension=----999999----;phone-context=redacted.invalid"]    
]]></artwork>
<t>When possible, it is RECOMMENDED to use a text representation as keys for &quot;tel&quot; URIs are more complex.</t>
</section>
</section>

<section anchor="email-addresses"><name>Email Addresses</name>
<t>Keys for email addresses MUST use a host part that is &quot;redacted.invalid&quot; but may use any local part
allowable in an email address. For example: <tt>redacted_email@redacted.invalid</tt>.</t>
<t>The &quot;.invalid&quot; TLD is a special-use domain defined in <xref target="RFC6761"></xref> and is unusable on the Internet.</t>
</section>

<section anchor="uris-with-host-names"><name>URIs with Host Names</name>
<t>Keys used in a URI with host names, such as an HTTP URI, MUST use a host name that is &quot;redacted.invalid&quot;.
For example: <tt>https://redacted.invalid/redacted_web_page</tt>.</t>
<t>The &quot;.invalid&quot; TLD is a special-use domain defined in <xref target="RFC6761"></xref> and is unusable on the Internet.</t>
</section>

<section anchor="dates-and-times"><name>Dates and Times</name>
<t>Date and times in RDAP use <xref target="RFC3339"></xref>. Keys for these MUST use the year 0000.
For example: <tt>0000-00-00T23:20:50.52Z</tt>.</t>
</section>
</section>

<section anchor="redaction-of-other-json-object-members"><name>Redaction of Other JSON Object Members</name>
<t>Signaling of the redaction of other JSON data type is a JSON object use the insertion of the &quot;simpleRedaction_data&quot; member
into the object where the data has been redacted by removal. For example, consider an RDAP autnum object:</t>

<artwork><![CDATA[{
  "objecClassName": "autnum",
  "handle": "AS-RANGE-FOO",
  "startNum": 
  "startAutnum" : 65536,
  "endAutnum" : 65541
}  
]]></artwork>
<t>Should policy dictate the redaction of &quot;endAutnum&quot;, this could be signaled in the following way:</t>

<artwork><![CDATA[{
  "objecClassName": "autnum",
  "handle": "AS-RANGE-FOO",
  "startNum": 
  "startAutnum" : 65536,
  "simpleRedaction_data" : [
    { "key": "////NO_END_NUMBERS////", "members": ["endAutnum"]}  
  ]
  "remarks": [
    {
      "description": [
        "No sane redaction policy would do this."
      ],
      “simpleRedaction_keys”: {
        “keys”: [
          “////NO_END_NUMBERS////”
        ]
      }
    }
  ]
}  
]]></artwork>
<t>The &quot;simpleRedaction_data&quot; member is an array of objects. Each object contains a &quot;key&quot; string signifying the
redaction key and a &quot;members&quot; string array signifying the JSON members associated with the redaction key.</t>
</section>
</section>

<section anchor="specifying_keys"><name>Specifying Keys</name>
<t>All redaction keys (<xref target="redaction_keys"></xref>) are explicitly specified by the server, inside a structure called
&quot;simpleRedaction_keys&quot; which is inserted in either an RDAP remark or notice. Keys MUST be specified
at least once but MAY be specified more than once.</t>
<t>Each &quot;simpleRedaction_keys&quot; object MUST have a member named &quot;keys&quot; which is an array of strings
containing the redaction keys <xref target="redaction_keys"></xref>.</t>
<t>The following is an example:</t>

<artwork><![CDATA["remarks": [
  {
    "description": [
      "These values have been redacted according to policy."
    ],
    “simpleRedaction_keys”: {
      “keys”: [
        “////REDACTED_HANDLE////”,
        “////REDACTED_FULL_NAME////”,
        “redacted_email@redacted.invalid”
      ]
    }
  }
]
]]></artwork>
<t>A redaction key MAY appear in more than one remark or notice to allow a server to describe
the cause of the redaction in more than one language.</t>
<t>The following is an example:</t>

<artwork><![CDATA["remarks": [
  {
    “lang”: “ja”,
    "description": [
      "この拡張機能は、複数の言語での編集理由をサポートします。"
    ],
    “simpleRedaction_keys”: {
      “keys”: [
        “////REDACTED_FULL_NAME////”
      ]
    },
    "links": [
      {
        "value": "https://example.com/value",
        "rel": "about",
        "href": "https://example.com/ja/some-policy.html",
        "type": "text/html"
      }
    ]
  },
  {
    “lang”: “en”,
    "description": [
      "This extension supports redaction reasons in multiple languages."
    ],
    “simpleRedaction_keys”: {
      “keys”: [
        “////REDACTED_FULL_NAME////”
      ]
    },
    "links": [
      {
        "value": "https://example.com/value",
        "rel": "about",
        "href": "https://example.com/en/some-policy.html",
        "type": "text/html"
      }
    ]
  }
]
]]></artwork>
<t>A client MUST NOT consider any key not found to be a &quot;simpleRedaction_keys&quot; structure as a valid
redaction (i.e. do not signal to the user that the information has been redacted).</t>
<t>The &quot;links&quot; array found in remarks and notices, as described by <xref target="RFC9083"></xref> may be used to link to a web page
describing the redaction policy. Clients may notify the user of the link, such as through hover-text or pop-ups.
The &quot;about&quot; relationship MUST be used for this purpose. The following is an example.</t>

<artwork><![CDATA["remarks": [
  {
    "description": [
      "This information has been redacted according to the linked policy.",
      "This extension supports associating redacted data links to redaction policies."
    ],
    “simpleRedaction_keys”: {
      “keys”: [
        “////REDACTED_HANDLE////”,
        “////REDACTED_FULL_NAME////”,
        “redacted_email@redacted.invalid”
      ]
    },
    "links": [
      {
        "value": "https://example.com/value",
        "rel": "about",
        "href": "https://example.com/some-policy.html",
        "type": "text/html"
      }
    ]
  }
]
]]></artwork>
<t>This specification allows the use of &quot;simpleRedaction_keys&quot; in both RDAP remarks and notices. In RDAP, remarks
are data pertaining to registered objects whereas notices are data pertaining to the response as a whole and
the service being provided. Therefore, specifying redaction of data pertaining to registered objects should
use RDAP remarks. And, unlikely as it would be, redaction of data pertaining service information should use
RDAP notices.</t>

<section anchor="keying-strategies"><name>Keying Strategies</name>

<section anchor="unclean-data"><name>Unclean Data</name>
<t>While it seems odd that some users would be allowed to give an email address with a host of
&quot;redacted.invalid&quot; or a string that begins and ends with four forward-slashes to an Internet
registration authority, some registries must deal with such data for various reasons.</t>
<t>One strategy servers may use would be to append a set of random characters to each key. For example,
if a registered resource was given as &quot;////I-fooled-you////&quot; then the server could thwart this
by appending the random characters &quot;1234-NO-YOU-DID-NOT&quot; to make the key &quot;////I-fooled-you_1234-NO-YOU-DID-NOT////&quot;.</t>
</section>

<section anchor="handles"><name>Handles</name>
<t>For servers operating under policies in which the &quot;handle&quot;, as defined by <xref target="RFC9083"></xref> must be
redacted, it would be beneficial to some clients to create unique redaction keys for each handle.
While clients SHOULD use &quot;self&quot; links, as described in <xref target="RFC9083"></xref>, to differentiate between
objects returned in a response, in the absence of &quot;self&quot; links they often use the &quot;handle&quot;.
Therefore, servers SHOULD create a unique redaction key for each handle that is redacted.</t>
</section>
</section>
</section>

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

<section anchor="unstructured-addresses"><name>Unstructured Addresses</name>
<t><xref target="RFC7095"></xref> allows for the representation of unstructured postal addresses. The following is a simple
example of an RDAP response with simple redactions where the postal address is given as
unstructured.</t>

<artwork><![CDATA[{
  "rdapConformance" : [ "Rdap_level_0", “simpleRedaction” ],
  "objectClassName" : "entity",
  "handle":"foo",
  "vcardArray":[
    "vcard",
    [
      ["version", {}, "text", "4.0"],
      ["fn", {}, "text", "Bob"],
      ["adr",
        {

          "type":"home",
          "label":"////REDACTED_STREET////\nVancouver\nBC\n////REDACTED_POSTAL_CODE////\n"
        },
        "text",
        [
          "", "", "", "", "", "", ""
        ]
      ],
    ]
  ],
  "remarks": [
    {
      "description": [
        "These values have been redacted according to policy."
      ],
      “simpleRedaction_keys”: {
        “keys”: [
          “////REDACTED_STREET////”,
          “////REDACTED_POSTAL_CODE////”
        ]
      }
    }
  ]
}
]]></artwork>
</section>

<section anchor="structured-addresses"><name>Structured Addresses</name>
<t><xref target="RFC7095"></xref> allows for the representation of structured postal addresses. The following is a simple
example of an RDAP response with simple redactions where the postal address is given as
structured.</t>

<artwork><![CDATA[{
  "rdapConformance" : [ "Rdap_level_0", “simpleRedaction” ],
  "objectClassName" : "entity",
  "handle":"foo",
  "vcardArray":[
    "vcard",
    [
      ["version", {}, "text", "4.0"],
      ["fn", {}, "text", "Bob"],
      ["adr",
        { "type":"work" },
        "text",
        [
          "",
          "////REDACTED_STREET////",
          "////REDACTED_STREET////",
          "Quebec",
          "QC",
          "////REDACTED_POSTAL_CODE////",
          "Canada"
        ]
      ]
    ]
  ],
  "remarks": [
    {
      "description": [
        "These values have been redacted according to policy."
      ],
      “simpleRedaction_keys”: {
        “keys”: [
          “////REDACTED_STREET////”,
          “////REDACTED_POSTAL_CODE////”
        ]
      }
    }
  ]
}
]]></artwork>
</section>

<section anchor="a-complete-example"><name>A Complete Example</name>
<t>The following is an example an RDAP response to a domain lookup in which the redactions
specified in
<eref target="https://www.icann.org/resources/pages/registration-data-policy-2024-02-21-en">ICANN Registration Data Policy</eref>,
have been applied.</t>

<artwork><![CDATA[{
  "rdapConformance": [
    "rdap_level_0", "simpleRedaction"
  ],
  "objectClassName": "domain",
  "handle": "////REGISTRY_DOMAIN_ID_REDACTION////",
  "ldhName": "example.com",
  "secureDNS": {
    "delegationSigned": false
  },
  "notices": [
    {
      "title": "Terms of Use",
      "description": [
        "Service subject to Terms of Use."
      ],
      "links": [
        {
          "rel": "self",
          "href": "https://www.example.com/terms-of-use",
          "type": "text/html",
          "value": "https://www.example.com/terms-of-use"
        }
      ]
    }
  ],
  "nameservers": [
    {
      "objectClassName": "nameserver",
      "ldhName": "ns1.example.com"
    },
    {
      "objectClassName": "nameserver",
      "ldhName": "ns2.example.com"
    }
  ],
  "entities": [
    {
      "objectClassName": "entity",
      "handle": "123",
      "roles": [
        "registrar"
      ],
      "publicIds": [
        {
          "type": "IANA Registrar ID",
          "identifier": "1"
        }
      ],
      "vcardArray": [
        "vcard",
        [
          [
            "version",
            {},
            "text",
            "4.0"
          ],
          [
            "fn",
            {},
            "text",
            "Example Registrar Inc."
          ],
          [
            "adr",
            {},
            "text",
            [
              "",
              "Suite 100",
              "123 Example Dr.",
              "Dulles",
              "VA",
              "20166-6503",
              "US"
            ]
          ],
          [
            "email",
            {},
            "text",
            "contact@organization.example"
          ],
          [
            "tel",
            {
              "type": "voice"
            },
            "uri",
            "tel:+1.7035555555;ext=1234"
          ],
          [
            "tel",
            {
              "type": "fax"
            },
            "uri",
            "tel:+1.7035555556"
          ]
        ]
      ],
      "entities": [
        {
          "objectClassName": "entity",
          "roles": [
            "abuse"
          ],
          "vcardArray": [
            "vcard",
            [
              [
                "version",
                {},
                "text",
                "4.0"
              ],
              [
                "fn",
                {},
                "text",
                "Abuse Contact"
              ],
              [
                "email",
                {},
                "text",
                "abuse@organization.example"
              ],
              [
                "tel",
                {
                  "type": "voice"
                },
                "uri",
                "tel:+1.7035555555;ext=1234"
              ]
            ]
          ]
        }
      ]
    },
    {
      "objectClassName": "entity",
      "handle": "////REGISTRY_REGISTRANT_ID_REDACTION////",
      "roles": [
        "registrant"
      ],
      "vcardArray": [
        "vcard",
        [
          [
            "version",
            {},
            "text",
            "4.0"
          ],
          [
            "fn",
            {},
            "text",
            "////REGISTRANT_NAME_REDACTION////"
          ],
          [
            "org",
            {},
            "text",
            "////REGISTRANT_ORG_REDACTION////"
          ],
          [
            "adr",
            {},
            "text",
            [
              "",
              "////REGISTRANT_STREET_REDACTION////",
              "////REGISTRANT_STREET_REDACTION////",
              "Quebec",
              "////REGISTRANT_CITY_REDACTION////",
              "////REGISTRANT_POSTAL_CODE_REDACTION////",
              "Canada"
            ]
          ],
          [
            "email",
            {},
            "text",
            "registrant-email-redaction@redacted.invalid"
          ],
          [
            "tel",
            {
              "type": "voice"
            },
            "text",
            "////0000000000////;ext=////1111111111////"
          ],
          [
            "tel",
            {
              "type": "fax"
            },
            "text",
            "////2222222222////"
          ]
        ]
      ]
    },
    {
      "objectClassName": "entity",
      "handle": "////REGISTRY_TECH_ID_REDACTION////",
      "roles": [
        "technical"
      ],
      "vcardArray": [
        "vcard",
        [
          [
            "version",
            {},
            "text",
            "4.0"
          ],
          [
            "fn",
            {},
            "text",
            "////TECH_NAME_REDACTION////"
          ],
          [
            "org",
            {},
            "text",
            "Example Inc."
          ],
          [
            "adr",
            {},
            "text",
            [
              "",
              "Suite 1234",
              "4321 Rue Somewhere",
              "Quebec",
              "QC",
              "G1V 2M2",
              "Canada"
            ]
          ],
          [
            "email",
            {},
            "text",
            "technical-email-redaction@redacted.invalid"
          ],
          [
            "tel",
            {
              "type": "voice"
            },
            "text",
            "////3333333333////;ext=321"
          ],
          [
            "tel",
            {
              "type": "fax"
            },
            "uri",
            "tel:+1-555-555-4321"
          ]
        ]
      ]
    }
  ],
  "events": [
    {
      "eventAction": "registration",
      "eventDate": "1997-06-03T00:00:00Z"
    },
    {
      "eventAction": "last changed",
      "eventDate": "2020-05-28T01:35:00Z"
    },
    {
      "eventAction": "expiration",
      "eventDate": "2021-06-03T04:00:00Z"
    }
  ],
  "status": [
    "server delete prohibited",
    "server update prohibited",
    "server transfer prohibited",
    "client transfer prohibited"
  ],
  "remarks": [
    {
      "description": [
        "These values have been redacted according to policy."
      ],
      “simpleRedaction_keys”: {
        “keys”: [
          “////REGISTRY_DOMAIN_ID_REDACTION////”,
          “////REGISTRY_REGISTRANT_ID_REDACTION////”,
          “////REGISTRANT_NAME_REDACTION////”,
          “////REGISTRANT_STREET_REDACTION////”,
          “////REGISTRANT_POSTAL_CODE_REDACTION////”,
          “////0000000000////”,
          “////1111111111////”,
          “////REGISTRY_TECH_ID_REDACTION////”,
          “////TECH_NAME_REDACTION////”,
          “////1111111111////”,
          “////2222222222////”,
          “registrant-email-redaction@redacted.invalid”,
          “tech-email-redaction@redacted.invalid”,
          “////REGISTRANT_ORG_REDACTION////”,
          “////REGISTRANT_CITY_REDACTION////”
        ]
      }
    }
  ]
}  
]]></artwork>
</section>
</section>

<section anchor="security-considerations"><name>Security Considerations</name>
<t>TBD.</t>
</section>

<section anchor="iana-considerations"><name>IANA Considerations</name>
<t>TBD: registration of &quot;simpleRedaction&quot;.</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.3339.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3966.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6761.xml"/>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9083.xml"/>
</references>
<references><name>Informative References</name>
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7095.xml"/>
</references>
</references>

</back>

</rfc>
