Re: [regext] RDAP Extensions Approach Analysis v2
Jasdip Singh <jasdips@arin.net> Fri, 10 June 2022 20:07 UTC
Return-Path: <jasdips@arin.net>
X-Original-To: regext@ietfa.amsl.com
Delivered-To: regext@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id EB123C15791C for <regext@ietfa.amsl.com>; Fri, 10 Jun 2022 13:07:19 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.809
X-Spam-Level:
X-Spam-Status: No, score=-1.809 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HTML_MESSAGE=0.001, HTML_TAG_BALANCE_BODY=0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([50.223.129.194]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3028SzqwrpR8 for <regext@ietfa.amsl.com>; Fri, 10 Jun 2022 13:07:17 -0700 (PDT)
Received: from smtp4.arin.net (smtp4.arin.net [199.43.0.54]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 307B5C13A2C3 for <regext@ietf.org>; Fri, 10 Jun 2022 13:07:09 -0700 (PDT)
Received: from CAS01CHA.corp.arin.net (cas01cha.corp.arin.net [10.1.30.62]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by smtp4.arin.net (Postfix) with ESMTPS id AC3ED1075764 for <regext@ietf.org>; Fri, 10 Jun 2022 16:07:07 -0400 (EDT)
Received: from CAS01CHA.corp.arin.net (10.1.30.62) by CAS01CHA.corp.arin.net (10.1.30.62) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 10 Jun 2022 16:07:06 -0400
Received: from CAS01CHA.corp.arin.net ([fe80::99af:898b:219f:401]) by CAS01CHA.corp.arin.net ([fe80::99af:898b:219f:401%17]) with mapi id 15.00.1497.000; Fri, 10 Jun 2022 16:07:06 -0400
From: Jasdip Singh <jasdips@arin.net>
To: "regext@ietf.org" <regext@ietf.org>
Thread-Topic: RDAP Extensions Approach Analysis v2
Thread-Index: AQHYehMOb+39gncj606qQP5zBqNDnq1JFymA
Date: Fri, 10 Jun 2022 20:07:05 +0000
Message-ID: <9D0DC567-0CD9-4B49-8E98-54166C8BDE56@arin.net>
References: <9DFC631E-8AD7-4CE2-8D13-9ABC342F4234@arin.net>
In-Reply-To: <9DFC631E-8AD7-4CE2-8D13-9ABC342F4234@arin.net>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach:
X-MS-TNEF-Correlator:
x-ms-exchange-messagesentrepresentingtype: 1
x-ms-exchange-transport-fromentityheader: Hosted
x-originating-ip: [192.136.136.37]
Content-Type: multipart/alternative; boundary="_000_9D0DC5670CD94B498E9854166C8BDE56arinnet_"
MIME-Version: 1.0
Archived-At: <https://mailarchive.ietf.org/arch/msg/regext/ZF8UNZQpa2lrJKU0fcTplQGOKVQ>
Subject: Re: [regext] RDAP Extensions Approach Analysis v2
X-BeenThere: regext@ietf.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: Registration Protocols Extensions <regext.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/regext>, <mailto:regext-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/regext/>
List-Post: <mailto:regext@ietf.org>
List-Help: <mailto:regext-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/regext>, <mailto:regext-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 10 Jun 2022 20:07:20 -0000
Hi. Based on some direct feedback from Mario (thanks Mario for the careful review), further revised this analysis [1]. TL;DR -- Approach B (Lack of tight coupling between extension identifier and rdapConformance) could also afford an upgrade path for quite a few of the listed scenarios, thereby raising its grade. :) Further, beside updating various aspects in the Aspect Analysis section for Approach B, added one more aspect: “On-the-wire efficiency”. Thanks, Jasdip [1] https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit?usp=sharing --- RDAP Extensions Analysis v2 Approaches<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.x3za3x81059e> Change Scenario Analysis<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.zi62z1sce607> Aspect Analysis<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.ogk4tkhrldq5> Approaches Approach A: Tight coupling between extension identifier and rdapConformance Extension identifier = <opaque identifier> No version semantics Registered in the IANA RDAP Extensions registry A new spec provided for each new iteration of the extension rdapConformance = <extension identifier> Extension identifier used to prefix data member names, and in URIs (path segment, segment parameter, and/or query parameters) Note: The phrase “new iteration” here simply connotes a new opaque identifier for an extension when it evolves. Approach B: Lack of tight coupling between extension identifier and rdapConformance Extension identifier = <prefix> Registered in the IANA RDAP Extensions registry rdapConformance = <prefix>[<version (suffix)>] [ ] means optional Needs version (suffix) semantics Registered in the IANA RDAP Extensions registry (or perhaps another registry for rdapConformance) A new spec provided for each new version of rdapConformance Extension identifier used to prefix data member names, and in URIs (path segment, segment parameter, and/or query parameters) Approach C: Decouple extension identifier from prefix(es) used for naming Extension identifier = <opaque identifier> Registered in the IANA RDAP Extensions registry A new spec provided for each new iteration of the extension; lists prefix(es) used for naming Version semantics not needed for listed prefix(es) rdapConformance = <extension identifier> Listed prefix(es) used to prefix data member names, and in URIs (path segment, segment parameter, and/or query parameters) Change Scenario Analysis Legend: ei - extension identifier rc - rdapConformance value p - prefix u - URI q - query parameter s - segment sp - segment parameter d - data member # Change Scenario Approach A - Tight coupling between extension identifier and rdapConformance Approach B - Lack of tight coupling between extension identifier and rdapConformance Approach C - Decouple extension identifier from prefix(es) used for naming 1 Add a URI path (no parameters yet) ei = ext0 (registered) rc = ext0 p = ext0 (new) u0 = …/ext0/… ei = ext (registered) rc = ext0 (registered) p = ext (new) u0 = …/ext/… ei = ext0 (registered) rc = ext0 p = p0 (new) u0 = …/p0/… 2 Add a path segment (s1) ei = ext1 (registered) rc = ext1 p = ext1 (new) u1 = …/ext1/s1/… Old URI u0 continues to exist during transition ei = ext rc = ext1 (registered) p = ext u1 = …/ext/s1/… Old URI u0 continues to exist during transition ei = ext1 (registered) rc = ext1 p = p1 (new) u1 = …/p1/s1/… Old URI u0 continues to exist during transition 3 Add a segment parameter (sp2) ei = ext2 (registered) rc = ext2 p = ext2 (new) u2 = …/ext2/s1;sp2=.../… Old URI u1 continues to exist during transition ei = ext rc = ext2 (registered) p = ext u2 = …/ext/s1;sp2=.../… Clients still on rc ext1 when calling u1 break if sp2 is required; otherwise not ei = ext2 (registered) rc = ext2 p = p1 u2 = …/p1/s1;sp2=.../… Clients still on rc ext1 when calling u1 break if sp2 is required; otherwise not The breakage scenario could be avoided by registering a new prefix for ext2 4 Rename a segment parameter (sp2 -> sp3) ei = ext3 (registered) rc = ext3 p = ext3 (new) u3 = …/ext3/s1;sp3=.../… Old URI u2 continues to exist during transition ei = ext rc = ext3 (registered) p = ext u3 = …/ext/s1;sp3=.../… Old URI u2 continues to exist during transition ei = ext3 (registered) rc = ext3 p = p3 (new) u3 = …/p3/s1;sp3=.../… Old URI u2 continues to exist during transition 5 Remove a path segment (s1) ei = ext4 (registered) rc = ext4 p = ext4 (new) u4 = …/ext4/… Old URI u3 continues to exist during transition ei = ext rc = ext4 (registered) p = ext u4 = …/ext/… Old URI u3 continues to exist during transition ei = ext4 (registered) rc = ext4 p = p4 (new) u4 = …/p4/… Old URI u3 continues to exist during transition 6 Add a required query parameter (q5) ei = ext5 (registered) rc = ext5 p = ext5 (new) u5 = …/ext5/…?q5=... Old URI u4 continues to exist during transition Note: The query parameters (e.g. q5) for a URI path containing the extension identifier need not be prefixed with that identifier, just like the sub-data (e.g. d0 in ext9_d object, row 10) need not for a data member prefixed with the extension identifier ei = ext rc = ext5 (registered) p = ext u5 = …/ext/…?q5=... Clients still on rc ext4 when calling u4 break ei = ext5 (registered) rc = ext5 p = p5 (new) u5 = …/p5/…?q5=... Old URI u4 continues to exist during transition 7 Add an optional query parameter (q6) ei = ext6 (registered) rc = ext6 p = ext6 (new) u6 = …/ext6/…?q5=...&q6=... Old URI u5 continues to exist during transition ei = ext rc = ext6 (registered) p = ext u6 = …/ext/…?q5=...&q6=... Clients still on rc ext5 when calling u5 do not break ei = ext6 (registered) rc = ext6 p = p5 u6 = …/p5/…?q5=...&q6=... Clients still on rc ext5 when calling u5 do not break 8 Rename a required query parameter (q5 -> q7) ei = ext7 (registered) rc = ext7 p = ext7 (new) u7 = …/ext7/…?q7=...&q6=... Old URI u6 continues to exist during transition ei = ext rc = ext7 (registered) p = ext u7 = …/ext/…?q7=...&q6=... Old URI u6 continues to exist during transition ei = ext7 (registered) rc = ext7 p = p7 (new) u7 = …/p7/…?q7=...&q6=... Old URI u6 continues to exist during transition 9 Rename an optional query parameter (q6 -> q8) ei = ext8 (registered) rc = ext8 p = ext8 (new) u8 = …/ext8/…?q7=...&q8=... Old URI u7 continues to exist during transition ei = ext rc = ext8 (registered) p = ext u8 = …/ext/…?q7=...&q8=... Old URI u7 continues to exist during transition ei = ext8 (registered) rc = ext8 p = p8 (new) u8 = …/p8/…?q7=...&q8=... Old URI u7 continues to exist during transition 10 Add a new data member (object class, array, number, string, and/or literal) (d object) for a new response ei = ext9 (registered) rc = ext9 p = ext9 (new) u9 = …/ext9/…?q7=...&q8=... Old URI u8 continues to exist during transition u9_d = …/ext9_d/… { “rdapConformance” : [ …, “ext9” ], “ext9_d” : { “d0” : “a” } } ei = ext rc = ext9 (registered) p = ext u8 = …/ext/…?q7=...&q8=... u9_d = …/ext_d/… { “rdapConformance” : [ …, “ext9” ], “ext_d” : { “d0” : “a” } } ei = ext9 (registered) rc = ext9 p = p8 u8 = …/p8/…?q7=...&q8=... u9_d = …/p8_d/… { “rdapConformance” : [ …, “ext9” ], “p8_d” : { “d0” : “a” } } 11 Add a required data member (d1) to an existing response ei = ext10 (registered) rc = ext10 p = ext10 (new) u10 = …/… { “rdapConformance” : [ …, “ext10” ], …, “ext10_d1” : 8 } ei = ext rc = ext10 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext10” ], …, “ext_d1” : 8 } ei = ext10 (registered) rc = ext10 p = p10 (new) u10 = …/… { “rdapConformance” : [ …, “ext10” ], …, “p10_d1” : 8 } 12 Add an optional data member (d2) to an existing response ei = ext11 (registered) rc = ext11 p = ext11 (new) u10 = …/… { “rdapConformance” : [ …, “ext10”, “ext11” ], …, “ext10_d1” : 8, “ext11_d1” : 8, “ext11_d2” : “abc” } Clients still on rc ext10 when calling u10 do not break, at the expense of sending duplicate data for ext10 ei = ext rc = ext11 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext11” ], …, “ext_d1” : 8, “ext_d2” : “abc” } Clients still on rc ext10 when calling u10 do not break ei = ext11 (registered) rc = ext11 p = p10 u10 = …/… { “rdapConformance” : [ …, “ext11” ], …, “p10_d1” : 8, “p10_d2” : “abc” } Clients still on rc ext10 when calling u10 do not break 13 Rename a required data member (d1 -> d3) ei = ext12 (registered) rc = ext12 p = ext12 (new) u10 = …/… { “rdapConformance” : [ …, “ext11”, “ext12” ], …, “ext11_d1” : 8, “ext11_d2” : “abc”, “ext12_d3” : 8, “ext12_d2” : “abc” } Clients still on rc ext11 when calling u10 do not break, at the expense of sending duplicate data for ext11 ei = ext rc = ext12 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext11”, “ext12” ], …, “ext_d1” : 8, “ext_d3” : 8, “ext_d2” : “abc” } Clients still on rc ext11 when calling u10 do not break, at the expense of sending duplicate data for ext11; albeit lesser cumulative data than other approaches ei = ext12 (registered) rc = ext12 p = p12 (new) u10 = …/… { “rdapConformance” : [ …, “ext11”, “ext12” ], …, “p10_d1” : 8, “p10_d2” : “abc”, “p12_d3” : 8, “p12_d2” : “abc” } Clients still on rc ext11 when calling u10 do not break, at the expense of sending duplicate data for ext11 14 Modify a required data member’s type (d3 number -> string) ei = ext13 (registered) rc = ext13 p = ext13 (new) u10 = …/… { “rdapConformance” : [ …, “ext12”, “ext13” ], …, “ext12_d3” : 8, “ext12_d2” : “abc”, “ext13_d3” : “def”, “ext13_d2” : “abc” } Clients still on rc ext12 when calling u10 do not break, at the expense of sending duplicate data for ext12 ei = ext rc = ext13 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext13” ], …, “ext_d3” : “def”, “ext_d2” : “abc” } Clients still on rc ext12 when calling u10 break ei = ext13 (registered) rc = ext13 p = p13 (new) u10 = …/… { “rdapConformance” : [ …, “ext12”, “ext13” ], …, “p12_d3” : 8, “p12_d2” : “abc”, “p13_d3” : “def”, “p13_d2” : “abc” } Clients still on rc ext12 when calling u10 do not break, at the expense of sending duplicate data for ext12 15 Rename an optional data member (d2 -> d4) ei = ext14 (registered) rc = ext14 p = ext14 (new) u10 = …/… { “rdapConformance” : [ …, “ext13”, “ext14” ], …, “ext13_d3” : “def”, “ext13_d2” : “abc”, “ext14_d3” : “def”, “ext14_d4” : “abc” } Clients still on rc ext13 when calling u10 do not break, at the expense of sending duplicate data for ext13 ei = ext rc = ext14 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext13”, “ext14” ], …, “ext_d2” : “abc” “ext_d3” : “def”, “ext_d4” : “abc” } Clients still on rc ext13 when calling u10 do not break, at the expense of sending duplicate data for ext13; albeit lesser cumulative data than other approaches ei = ext14 (registered) rc = ext14 p = p14 (new) u10 = …/… { “rdapConformance” : [ …, “ext13”, “ext14” ], …, “p13_d3” : “def”, “p13_d2” : “abc”, “p14_d3” : “def”, “p14_d4” : “abc” } Clients still on rc ext13 when calling u10 do not break, at the expense of sending duplicate data for ext13 16 Modify an optional data member’s type (d4 string -> number) ei = ext15 (registered) rc = ext15 p = ext15 (new) u10 = …/… { “rdapConformance” : [ …, “ext14”, “ext15” ], …, “ext14_d3” : “def”, “ext14_d4” : “abc”, “ext15_d3” : “def”, “ext15_d4” : 16 } Clients still on rc ext14 when calling u10 do not break, at the expense of sending duplicate data for ext14 ei = ext rc = ext15 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext15” ], …, “ext_d3” : “def”, “ext_d4” : 16 } Clients still on rc ext14 when calling u10 break if they were processing the optional data member ei = ext15 (registered) rc = ext15 p = p15 (new) u10 = …/… { “rdapConformance” : [ …, “ext14”, “ext15” ], …, “p14_d3” : “def”, “p14_d4” : “abc”, “p15_d3” : “def”, “p15_d4” : 16 } Clients still on rc ext14 when calling u10 do not break, at the expense of sending duplicate data for ext14 17 Remove a required data member (d3) ei = ext16 (registered) rc = ext16 p = ext16 (new) u10 = …/… { “rdapConformance” : [ …, “ext15”, “ext16” ], …, “ext15_d3” : “def”, “ext15_d4” : 16, “ext16_d4” : 16, } Clients still on rc ext15 when calling u10 do not break, at the expense of sending duplicate data for ext15 ei = ext rc = ext16 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext15”, “ext16” ], …, “ext_d3” : “def”, “ext_d4” : 16 } Clients still on rc ext15 when calling u10 do not break, at the expense of sending duplicate data for ext15; albeit lesser cumulative data than other approaches ei = ext16 (registered) rc = ext16 p = p16 (new) u10 = …/… { “rdapConformance” : [ …, “ext15”, “ext16” ], …, “p15_d3” : “def”, “p15_d4” : 16, “p16_d4” : 16, } Clients still on rc ext15 when calling u10 do not break, at the expense of sending duplicate data for ext15 18 Remove an optional data member (d4) ei = ext17 (registered) rc = ext17 p = ext16 u10 = …/… { “rdapConformance” : [ …, “ext16”, “ext17” ], …, “ext16_d4” : 16 } Clients still on rc ext16 when calling u10 do not break, at the expense of sending data for ext16 Note: This would be the case when phasing out jcard ei = ext rc = ext17 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext16”, “ext17” ], …, “ext_d4” : 16 } Clients still on rc ext16 when calling u10 do not break, at the expense of sending data for ext16 ei = ext17 (registered) rc = ext17 p = p16 u10 = …/… { “rdapConformance” : [ …, “ext16”, “ext17” ], …, “p16_d4” : 16 } Clients still on rc ext16 when calling u10 do not break, at the expense of sending data for ext16 19 Remove a required query parameter (q7) ei = ext18 (registered) rc = ext18 p = ext18 (new) u18 = …/ext18/…?q8=... Old URI u9 (row 10) continues to exist during transition ei = ext rc = ext18 (registered) p = ext u18 = …/ext/…?q8=... Old URI u8 (row 10) continues to exist during transition ei = ext18 (registered) rc = ext18 p = p18 (new) u18 = …/p18/…?q8=... Old URI u8 (row 10) continues to exist during transition 20 Remove an optional query parameter (q8) ei = ext19 (registered) rc = ext19 p = ext19 (new) u19 = …/ext19/… Old URI u18 continues to exist during transition ei = ext rc = ext19 (registered) p = ext u19 = …/ext/… Old URI u18 continues to exist during transition ei = ext19 (registered) rc = ext19 p = p19 (new) u19 = …/p19/… Old URI u18 continues to exist during transition 21 Remove a URI path (u19) ei = ext20 (registered) rc = ext20 p = ext19 u19 = …/ext19/… Old URI u19 continues to exist during transition, and not beyond ei = ext rc = ext20 (registered) p = ext u19 = …/ext/… Old URI u19 continues to exist during transition, and not beyond ei = ext20 (registered) rc = ext20 p = p19 u19 = …/p19/… Old URI u19 continues to exist during transition, and not beyond 22 Add a query parameter (q9) to an existing, non-extension URI ei = ext21 (registered) rc = ext21 p = ext21 (new) u21 = …?ext21_q9=... { “rdapConformance” : [ …, “ext21” ], … } ei = ext rc = ext21 (registered) p = ext u21 = …?ext_q9=... { “rdapConformance” : [ …, “ext21” ], … } ei = ext21 (registered) rc = ext21 p = p21 (new) u21 = …?p21_q9=... { “rdapConformance” : [ …, “ext21” ], … } 23 Remove a query parameter (q9) from an existing, non-extension URI, as well as add a query parameter (q10) to it ei = ext22 (registered) rc = ext22 p = ext22 (new) u22 = …?ext21_q9=...&ext22_q10=... { “rdapConformance” : [ …, “ext21”, “ext22” ], … } Clients still on rc ext21 when calling u22 do not break ei = ext rc = ext22 (registered) p = ext u22 = …?ext_q10=... { “rdapConformance” : [ …, “ext22” ], … } Clients still on rc ext21 when calling u22 break ei = ext22 (registered) rc = ext22 p = p22 (new) u22 = …?p21_q9=...&p22_q10=... { “rdapConformance” : [ …, “ext21”, “ext22” ], … } Clients still on rc ext21 when calling u22 do not break Aspect Analysis # Aspect Approach A - Tight coupling between extension identifier and rdapConformance Approach B - Lack of tight coupling between extension identifier and rdapConformance Approach C - Decouple extension identifier from prefix(es) used for naming 1 Providing a new spec to IANA for a new iteration of an extension Registry stays as-is Few non-compliant registrations need to be remedied Registry needs to evolve for: Versioned rdapConformance Tying spec to versioned rdapConformance Registry stays as-is Prefix(es) listed in the spec 2 Risk of breaking changes for RDAP clients Minimal since it would always be a controlled upgrade to the next iteration of an extension with sufficient transition time More risky since there is no controlled way to upgrade for few of the change scenarios<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.zi62z1sce607> Risk is minimal, like for approach A However, requires carefully identifying the need for a new prefix on scenario-by-scenario basis; otherwise inadvertent mistakes possible 3 Cost of reprogramming clients for the next iteration of an extension There is cost but not as high as it seems — replacing extension identifier in multiple places, and accounting for primarily query parameter and data member changes Longer grace period for clients to reprogram if the server supports multiple iterations of an extension during transition For few change scenarios, reprogramming could become exigent for clients when the server switches to the new iteration without a way to support the previous iteration For other change scenarios, longer grace period for clients to reprogram if the server supports multiple iterations of an extension during transition Cost slightly lower than that for Approach A — replacing prefixes for a majority (but not all) of the scenarios 4 Cost of reprogramming servers for the next iteration of an extension Highest cost — to simultaneously support multiple iterations during transition period, replicating code from the previous iteration and replacing extension identifier in multiple places, and accounting for primarily query parameter and data member changes Eventually retiring code for the previous iteration Cost is lower than that for other approaches but not that low — for a majority (but not all) of the scenarios, to simultaneously support multiple iterations during transition period, replicating code from the previous iteration, and accounting for primarily query parameter and data member changes Eventually retiring code for the previous iteration Cost is lower than for that for Approach A but not too low — for a majority (but not all) of the scenarios, to simultaneously support multiple iterations during transition period, replicating code from the previous iteration and replacing prefixes in multiple places, and accounting for primarily query parameter and data member changes Eventually retiring code for the previous iteration 5 Server-side signaling of the next iteration of an extension Add the new value of the rdapConformance in the help response and related responses Make the new URIs available, without affecting the old ones Add the new value of the rdapConformance in the help response and related responses Mostly the current URIs change for the new value of the rdapConformance, resulting in client breakages for few of the scenarios Add the new value of the rdapConformance in the help response and related responses To a lower extent than Approach A, make the new URIs available, without affecting the old ones 6 Collisions risk Zero since the new extension identifier is explicitly marked in data members and URIs Zero since the constant extension identifier is explicitly marked in data members and URIs However, client breakage possible for few change scenarios Zero since the new prefix is explicitly marked in data members and URIs, just like the new extension identifier in Approach A 7 On-the-wire efficiency Lower than Approach B since more duplicated data is sent back when supporting multiple iterations during transition period Highest since lesser duplicated data is sent back when supporting multiple iterations during transition period Lower than Approach B since more duplicated data is sent back when supporting multiple iterations during transition period From: Jasdip Singh <jasdips@arin.net> Date: Monday, June 6, 2022 at 10:05 PM To: "regext@ietf.org" <regext@ietf.org> Subject: RDAP Extensions Approach Analysis v2 Hi. Please find below the revised analysis of the current approach (A) and the 2 newly proposed approaches (B and C) for RDAP extensions [1]. Hopefully, the considered change scenarios are now granular enough ( @Mario :) ). My high-level observations: 1. Approach C is much better than Approach B. 2. That said, would still go with Approach A since it consistently prevents naming collisions for all change scenarios and affords sufficient transition time for clients to “upgrade” to the next iteration of an extension. The latter -- graceful upgrade -- could be quite important to most, if not all, customers of the RDAP service at an RIR or a DNR, to the point of being an operational requirement. The former – consistently preventing naming collisions – helps keep the model simple, albeit at the expense of occasionally sending more data in responses. 3. Approach C is closer to Approach A than to Approach B but requires a careful scenario-by-scenario analysis to determine the need for a new prefix(es), and that could be problematic at times. I think it’d come down to (sunk) cost versus benefit when choosing between sticking with Approach A or moving to Approach C. Please feel free to rectify this analysis. :) Hopefully, the discussion could converge for the considered change scenarios. Thanks, Jasdip [1] https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit?usp=sharing --- RDAP Extensions Analysis v2 Approaches<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.x3za3x81059e> Change Scenario Analysis<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.zi62z1sce607> Aspect Analysis<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.ogk4tkhrldq5> Approaches Approach A: Tight coupling between extension identifier and rdapConformance Extension identifier = <opaque identifier> No version semantics Registered in the IANA RDAP Extensions registry A new spec provided for each new iteration of the extension rdapConformance = <extension identifier> Extension identifier used to prefix data member names, and in URIs (path segment, segment parameter, and/or query parameters) Note: The phrase “new iteration” here simply connotes a new opaque identifier for an extension when it evolves. Approach B: Lack of tight coupling between extension identifier and rdapConformance Extension identifier = <prefix> Registered in the IANA RDAP Extensions registry rdapConformance = <prefix>[<version (suffix)>] [ ] means optional Needs version (suffix) semantics Registered in the IANA RDAP Extensions registry (or perhaps another registry for rdapConformance) A new spec provided for each new version of rdapConformance Extension identifier used to prefix data member names, and in URIs (path segment, segment parameter, and/or query parameters) Approach C: Decouple extension identifier from prefix(es) used for naming Extension identifier = <opaque identifier> Registered in the IANA RDAP Extensions registry A new spec provided for each new iteration of the extension; lists prefix(es) used for naming Version semantics not needed for listed prefix(es) rdapConformance = <extension identifier> Listed prefix(es) used to prefix data member names, and in URIs (path segment, segment parameter, and/or query parameters) Change Scenario Analysis Legend: ei - extension identifier rc - rdapConformance value p - prefix u - URI q - query parameter s - segment sp - segment parameter d - data member # Change Scenario Approach A - Tight coupling between extension identifier and rdapConformance Approach B - Lack of tight coupling between extension identifier and rdapConformance Approach C - Decouple extension identifier from prefix(es) used for naming 1 Add a URI path (no parameters yet) ei = ext0 (registered) rc = ext0 p = ext0 (new) u0 = …/ext0/… ei = ext (registered) rc = ext0 (registered) p = ext (new) u0 = …/ext/… ei = ext0 (registered) rc = ext0 p = p0 (new) u0 = …/p0/… 2 Add a path segment (s1) ei = ext1 (registered) rc = ext1 p = ext1 (new) u1 = …/ext1/s1/… Old URI u0 continues to exist during transition ei = ext rc = ext1 (registered) p = ext u1 = …/ext/s1/… Clients still on rc ext0 when calling u0 break ei = ext1 (registered) rc = ext1 p = p1 (new) u1 = …/p1/s1/… Old URI u0 continues to exist during transition 3 Add a segment parameter (sp2) ei = ext2 (registered) rc = ext2 p = ext2 (new) u2 = …/ext2/s1;sp2=.../… ei = ext rc = ext2 (registered) p = ext u2 = …/ext/s1;sp2=.../… ei = ext2 (registered) rc = ext2 p = p1 u2 = …/p1/s1;sp2=.../… 4 Rename a segment parameter (sp2 -> sp3) ei = ext3 (registered) rc = ext3 p = ext3 (new) u3 = …/ext3/s1;sp3=.../… Old URI u2 continues to exist during transition ei = ext rc = ext3 (registered) p = ext u3 = …/ext/s1;sp3=.../… Clients still on rc ext2 when calling u2 break ei = ext3 (registered) rc = ext3 p = p3 (new) u3 = …/p3/s1;sp3=.../… Old URI u2 continues to exist during transition 5 Remove a path segment (s1) ei = ext4 (registered) rc = ext4 p = ext4 (new) u4 = …/ext4/… Old URI u3 continues to exist during transition ei = ext rc = ext4 (registered) p = ext u4 = …/ext/… Clients still on rc ext3 when calling u3 break ei = ext4 (registered) rc = ext4 p = p4 (new) u4 = …/p4/… Old URI u3 continues to exist during transition 6 Add a required query parameter (q5) ei = ext5 (registered) rc = ext5 p = ext5 (new) u5 = …/ext5/…?q5=... Old URI u4 continues to exist during transition ei = ext rc = ext5 (registered) p = ext u5 = …/ext/…?q5=... Clients still on rc ext4 when calling u4 break ei = ext5 (registered) rc = ext5 p = p5 (new) u5 = …/p5/…?q5=... Old URI u4 continues to exist during transition 7 Add an optional query parameter (q6) ei = ext6 (registered) rc = ext6 p = ext6 (new) u6 = …/ext6/…?q5=...&q6=... Old URI u5 continues to exist during transition ei = ext rc = ext6 (registered) p = ext u6 = …/ext/…?q5=...&q6=... Clients still on rc ext5 when calling u5 do not break ei = ext6 (registered) rc = ext6 p = p5 u6 = …/p5/…?q5=...&q6=... Clients still on rc ext5 when calling u5 do not break 8 Rename a required query parameter (q5 -> q7) ei = ext7 (registered) rc = ext7 p = ext7 (new) u7 = …/ext7/…?q7=...&q6=... Old URI u6 continues to exist during transition ei = ext rc = ext7 (registered) p = ext u7 = …/ext/…?q7=...&q6=... Clients still on rc ext6 when calling u6 break ei = ext7 (registered) rc = ext7 p = p7 (new) u7 = …/p7/…?q7=...&q6=... Old URI u6 continues to exist during transition 9 Rename an optional query parameter (q6 -> q8) ei = ext8 (registered) rc = ext8 p = ext8 (new) u8 = …/ext8/…?q7=...&q8=... Old URI u7 continues to exist during transition ei = ext rc = ext8 (registered) p = ext u8 = …/ext/…?q7=...&q8=... Clients still on rc ext7 when calling u7 break ei = ext8 (registered) rc = ext8 p = p8 (new) u8 = …/p8/…?q7=...&q8=... Old URI u7 continues to exist during transition 10 Add a new data member (object class, array, number, string, and/or literal) (d object) for a new response ei = ext9 (registered) rc = ext9 p = ext9 (new) u9 = …/ext9/…?q7=...&q8=... Old URI u8 continues to exist during transition u9_d = …/ext9_d/… { “rdapConformance” : [ …, “ext9” ], “ext9_d” : { “d0” : “a” } } ei = ext rc = ext9 (registered) p = ext u8 = …/ext/…?q7=...&q8=... u9_d = …/ext_d/… { “rdapConformance” : [ …, “ext9” ], “ext_d” : { “d0” : “a” } } ei = ext9 (registered) rc = ext9 p = p8 u8 = …/p8/…?q7=...&q8=... u9_d = …/p8_d/… { “rdapConformance” : [ …, “ext9” ], “p8_d” : { “d0” : “a” } } 11 Add a required data member (d1) to an existing response ei = ext10 (registered) rc = ext10 p = ext10 (new) u10 = …/… { “rdapConformance” : [ …, “ext10” ], …, “ext10_d1” : 8 } ei = ext rc = ext10 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext10” ], …, “ext_d1” : 8 } ei = ext10 (registered) rc = ext10 p = p10 (new) u10 = …/… { “rdapConformance” : [ …, “ext10” ], …, “p10_d1” : 8 } 12 Add an optional data member (d2) to an existing response ei = ext11 (registered) rc = ext11 p = ext11 (new) u10 = …/… { “rdapConformance” : [ …, “ext10”, “ext11” ], …, “ext10_d1” : 8, “ext11_d1” : 8, “ext11_d2” : “abc” } Clients still on rc ext10 when calling u10 do not break, at the expense of sending duplicate data for ext10 ei = ext rc = ext11 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext11” ], …, “ext_d1” : 8, “ext_d2” : “abc” } Clients still on rc ext10 when calling u10 do not break ei = ext11 (registered) rc = ext11 p = p10 u10 = …/… { “rdapConformance” : [ …, “ext11” ], …, “p10_d1” : 8, “p10_d2” : “abc” } Clients still on rc ext10 when calling u10 do not break 13 Rename a required data member (d1 -> d3) ei = ext12 (registered) rc = ext12 p = ext12 (new) u10 = …/… { “rdapConformance” : [ …, “ext11”, “ext12” ], …, “ext11_d1” : 8, “ext11_d2” : “abc”, “ext12_d3” : 8, “ext12_d2” : “abc” } Clients still on rc ext11 when calling u10 do not break, at the expense of sending duplicate data for ext11 ei = ext rc = ext12 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext12” ], …, “ext_d3” : 8, “ext_d2” : “abc” } Clients still on rc ext11 when calling u10 break ei = ext12 (registered) rc = ext12 p = p12 (new) u10 = …/… { “rdapConformance” : [ …, “ext11”, “ext12” ], …, “p10_d1” : 8, “p10_d2” : “abc”, “p12_d3” : 8, “p12_d2” : “abc” } Clients still on rc ext11 when calling u10 do not break, at the expense of sending duplicate data for ext11 14 Modify a required data member’s type (d3 number -> string) ei = ext13 (registered) rc = ext13 p = ext13 (new) u10 = …/… { “rdapConformance” : [ …, “ext12”, “ext13” ], …, “ext12_d3” : 8, “ext12_d2” : “abc”, “ext13_d3” : “def”, “ext13_d2” : “abc” } Clients still on rc ext12 when calling u10 do not break, at the expense of sending duplicate data for ext12 ei = ext rc = ext13 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext13” ], …, “ext_d3” : “def”, “ext_d2” : “abc” } Clients still on rc ext12 when calling u10 break ei = ext13 (registered) rc = ext13 p = p13 (new) u10 = …/… { “rdapConformance” : [ …, “ext12”, “ext13” ], …, “p12_d3” : 8, “p12_d2” : “abc”, “p13_d3” : “def”, “p13_d2” : “abc” } Clients still on rc ext12 when calling u10 do not break, at the expense of sending duplicate data for ext12 15 Rename an optional data member (d2 -> d4) ei = ext14 (registered) rc = ext14 p = ext14 (new) u10 = …/… { “rdapConformance” : [ …, “ext13”, “ext14” ], …, “ext13_d3” : “def”, “ext13_d2” : “abc”, “ext14_d3” : “def”, “ext14_d4” : “abc” } Clients still on rc ext13 when calling u10 do not break, at the expense of sending duplicate data for ext13 ei = ext rc = ext14 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext14” ], …, “ext_d3” : “def”, “ext_d4” : “abc” } Clients still on rc ext13 when calling u10 break if they were processing the optional data member ei = ext14 (registered) rc = ext14 p = p14 (new) u10 = …/… { “rdapConformance” : [ …, “ext13”, “ext14” ], …, “p13_d3” : “def”, “p13_d2” : “abc”, “p14_d3” : “def”, “p14_d4” : “abc” } Clients still on rc ext13 when calling u10 do not break, at the expense of sending duplicate data for ext13 16 Modify an optional data member’s type (d4 string -> number) ei = ext15 (registered) rc = ext15 p = ext15 (new) u10 = …/… { “rdapConformance” : [ …, “ext14”, “ext15” ], …, “ext14_d3” : “def”, “ext14_d4” : “abc”, “ext15_d3” : “def”, “ext15_d4” : 16 } Clients still on rc ext14 when calling u10 do not break, at the expense of sending duplicate data for ext14 ei = ext rc = ext15 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext15” ], …, “ext_d3” : “def”, “ext_d4” : 16 } Clients still on rc ext14 when calling u10 break if they were processing the optional data member ei = ext15 (registered) rc = ext15 p = p15 (new) u10 = …/… { “rdapConformance” : [ …, “ext14”, “ext15” ], …, “p14_d3” : “def”, “p14_d4” : “abc”, “p15_d3” : “def”, “p15_d4” : 16 } Clients still on rc ext14 when calling u10 do not break, at the expense of sending duplicate data for ext14 17 Remove a required data member (d3) ei = ext16 (registered) rc = ext16 p = ext16 (new) u10 = …/… { “rdapConformance” : [ …, “ext15”, “ext16” ], …, “ext15_d3” : “def”, “ext15_d4” : 16, “ext16_d4” : 16, } Clients still on rc ext15 when calling u10 do not break, at the expense of sending duplicate data for ext15 ei = ext rc = ext16 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext16” ], …, “ext_d4” : 16 } Clients still on rc ext15 when calling u10 break ei = ext16 (registered) rc = ext16 p = p16 (new) u10 = …/… { “rdapConformance” : [ …, “ext15”, “ext16” ], …, “p15_d3” : “def”, “p15_d4” : 16, “p16_d4” : 16, } Clients still on rc ext15 when calling u10 do not break, at the expense of sending duplicate data for ext15 18 Remove an optional data member (d4) ei = ext17 (registered) rc = ext17 p = ext16 u10 = …/… { “rdapConformance” : [ …, “ext16”, “ext17” ], …, “ext16_d4” : 16 } Clients still on rc ext16 when calling u10 do not break, at the expense of sending data for ext16 Note: This would be the case when phasing out jcard ei = ext rc = ext17 (registered) p = ext u10 = …/… { “rdapConformance” : [ …, “ext17” ], … } Clients still on rc ext16 when calling u10 break if they were processing the optional data member ei = ext17 (registered) rc = ext17 p = p16 u10 = …/… { “rdapConformance” : [ …, “ext16”, “ext17” ], …, “p16_d4” : 16 } Clients still on rc ext16 when calling u10 do not break, at the expense of sending data for ext16 19 Remove a required query parameter (q7) ei = ext18 (registered) rc = ext18 p = ext18 (new) u18 = …/ext18/…?q8=... Old URI u9 continues to exist during transition ei = ext rc = ext18 (registered) p = ext u18 = …/ext/…?q8=... Clients still on rc ext9 when calling u8 break ei = ext18 (registered) rc = ext18 p = p18 (new) u18 = …/p18/…?q8=... Old URI u8 continues to exist during transition 20 Remove an optional query parameter (q8) ei = ext19 (registered) rc = ext19 p = ext19 (new) u19 = …/ext19/… Old URI u18 continues to exist during transition ei = ext rc = ext19 (registered) p = ext u19 = …/ext/… Clients still on rc ext18 when calling u18 break ei = ext19 (registered) rc = ext19 p = p19 (new) u19 = …/p19/… Old URI u18 continues to exist during transition 21 Remove a URI path (u19) ei = ext20 (registered) rc = ext20 p = ext19 u19 = …/ext19/… Old URI u19 continues to exist during transition, and not beyond ei = ext rc = ext20 (registered) p = ext u19 = …/ext/… Old URI u19 continues to exist during transition, and not beyond ei = ext20 (registered) rc = ext20 p = p19 u19 = …/p19/… Old URI u19 continues to exist during transition, and not beyond 22 Add a query parameter (q9) to an existing, non-extension URI ei = ext21 (registered) rc = ext21 p = ext21 (new) u21 = …?ext21_q9=... { “rdapConformance” : [ …, “ext21” ], … } ei = ext rc = ext21 (registered) p = ext u21 = …?ext_q9=... { “rdapConformance” : [ …, “ext21” ], … } ei = ext21 (registered) rc = ext21 p = p21 (new) u21 = …?p21_q9=... { “rdapConformance” : [ …, “ext21” ], … } 23 Remove a query parameter (q9) from an existing, non-extension URI, as well as add a query parameter (q10) to it ei = ext22 (registered) rc = ext22 p = ext22 (new) u22 = …?ext21_q9=...&ext22_q10=... { “rdapConformance” : [ …, “ext21”, “ext22” ], … } Clients still on rc ext21 when calling u22 do not break ei = ext rc = ext22 (registered) p = ext u22 = …?ext_q10=... { “rdapConformance” : [ …, “ext22” ], … } Clients still on rc ext21 when calling u22 break ei = ext22 (registered) rc = ext22 p = p22 (new) u22 = …?p21_q9=...&p22_q10=... { “rdapConformance” : [ …, “ext21”, “ext22” ], … } Clients still on rc ext21 when calling u22 do not break Aspect Analysis # Aspect Approach A - Tight coupling between extension identifier and rdapConformance Approach B - Lack of tight coupling between extension identifier and rdapConformance Approach C - Decouple extension identifier from prefix(es) used for naming 1 Providing a new spec to IANA for a new iteration of an extension Registry stays as-is Few non-compliant registrations need to be remedied Registry needs to evolve for: Versioned rdapConformance Tying spec to versioned rdapConformance Registry stays as-is Prefix(es) listed in the spec 2 Risk of breaking changes for RDAP clients Minimal since it would always be a controlled upgrade to the next iteration of an extension with sufficient transition time Most risky out of all the approaches since there is no controlled way to upgrade for quite a few change scenarios<https://docs.google.com/document/d/1e3QD8z01KpYRd5LwdLBWjHHDoFVAVEL8u7Y52zsDdx0/edit#heading=h.zi62z1sce607> Risk is minimal, like for approach A However, requires carefully identifying the need for a new prefix on scenario-by-scenario basis; otherwise inadvertent mistakes possible 3 Cost of reprogramming clients for the next iteration of an extension There is cost but not as high as it seems — replacing extension identifier in multiple places, and accounting for primarily query parameter and data member changes Longer grace period for clients to reprogram if the server supports multiple iterations of an extension during transition Reprogramming could become exigent for clients if the server switches to the new iteration without supporting the previous iteration Cost slightly lower than that for Approach A — replacing prefixes for a majority (but not all) of scenarios 4 Cost of reprogramming servers for the next iteration of an extension Highest cost — to simultaneously support multiple iterations during transition period, replicating code from the previous iteration and replacing extension identifier in multiple places, and accounting for primarily query parameter and data member changes Eventually retiring code for the previous iteration Lowest cost since only the latest iteration is supported Cost is lower than for that for Approach A but not too low — for a majority (but not all) of scenarios, to simultaneously support multiple iterations during transition period, replicating code from the previous iteration and replacing prefixes in multiple places, and accounting for primarily query parameter and data member changes Eventually retiring code for the previous iteration 5 Server-side signaling of the next iteration of an extension Add the new value of the rdapConformance in the help response and related responses Make new URIs available Add the new value of the rdapConformance in the help response and related responses No change in URIs for the new value of the rdapConformance Add the new value of the rdapConformance in the help response and related responses To a lower extent than Approach A, make new URIs available 6 Collisions risk Zero since the new extension identifier is explicitly marked in data members and URIs High since the new iteration of an extension is not marked in data members and URIs, and is only discoverable through the rdapConformance value in a response Zero since the new prefix is explicitly marked in data members and URIs, just like the new extension identifier in Approach A
- [regext] RDAP Extensions Approach Analysis v2 Jasdip Singh
- Re: [regext] RDAP Extensions Approach Analysis v2 Jasdip Singh
- Re: [regext] RDAP Extensions Approach Analysis v2 Hollenbeck, Scott
- Re: [regext] RDAP Extensions Approach Analysis v2 Andrew Newton
- Re: [regext] RDAP Extensions Approach Analysis v2 Jasdip Singh