Re: [netmod] Joint WGLC on "semver" and "module-versioning" drafts

Jürgen Schönwälder <jschoenwaelder@constructor.university> Tue, 30 May 2023 18:29 UTC

Return-Path: <jschoenwae@constructor.university>
X-Original-To: netmod@ietfa.amsl.com
Delivered-To: netmod@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 6323DC159A24 for <netmod@ietfa.amsl.com>; Tue, 30 May 2023 11:29:08 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.896
X-Spam-Level:
X-Spam-Status: No, score=-1.896 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_BLOCKED=0.001, RCVD_IN_ZEN_BLOCKED_OPENDNS=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001, URIBL_DBL_BLOCKED_OPENDNS=0.001, URIBL_ZEN_BLOCKED_OPENDNS=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=jacobsuniversity.onmicrosoft.com
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 aPfwOc-gXGtx for <netmod@ietfa.amsl.com>; Tue, 30 May 2023 11:29:04 -0700 (PDT)
Received: from EUR02-AM0-obe.outbound.protection.outlook.com (mail-am0eur02on20620.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe13::620]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 1CC43C152574 for <netmod@ietf.org>; Tue, 30 May 2023 11:28:57 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nw7BJ4ogaT9wAKtkKpUbEIAH+ld50PpKQpfr8I8a0MD6NZz/fUOOJJ2Yxk+8+VOh4Co3iojoJyMffr5Erwmx90RDTwgQs1jE5zi+KyG/VWP2X5gSOJlFrV2DhHX4vWt9lIAUZ99QDISx11x5BQfKOQ3Ez+3hqHXPH8jEEeeHPEtiGujUXmhiOjE3Jp8aWlJbVAJ7bGmOeltnTLs39BHC8FNl/BhlJKZhDYBcvdEU2UbPdM+xWCzlE+A5tZA+oxdTUm7usa/+7s46Hpc/b8LTVzOhlgEgHLu/aOGC0sOix6hXu7jm3gv+DXwUTA4xnvcBOtqx62uVvjdx0uRM5C9LVw==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yCibDL3PCZlRZf6xdQsUxkkYUS2MQDAc9ca+TL+2Rng=; b=Jsdj5d9Lg6HV+m9wbOR0gKmtGm3ThlfDchsRGykrvBpxz2jL1v3NvAPJTe12tl6sW7mLmisFQ87Tgh1akHScvo60MuzcLVqhhdlM1R8tBRHVephtB3nOq8PhXd7tPj02uTAduoB6wE+ev+sjtgDa4kXuKHEhSKwlPG2M2ATvf8FVzHTb9IqYEuXtXBKGF79AvpSO0f4RrEBf2Rc7n5jMkCaowuQ6UBHMs3EB0nlOxvLfkz3ThRaB47R+f0hfCZVcpMIg9WhfQdVjSgZs6/HEYpuWbulnEt8aN92nbCbFA8nt8Uv+b8zivHkUyoPg4YkHWHeHXi8XmJ6i4iHhXFy/EA==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=constructor.university; dmarc=pass action=none header.from=constructor.university; dkim=pass header.d=constructor.university; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jacobsuniversity.onmicrosoft.com; s=selector2-jacobsuniversity-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yCibDL3PCZlRZf6xdQsUxkkYUS2MQDAc9ca+TL+2Rng=; b=sp+qu7LD30jdlqzVPwPwIhAS+shhqvn/kF3rGNz459QwnmWgJR2kgja/1s1tHSzokxrO6uUjBIHzmMDjhLGrDpLhLqOP3EmjejACMgsC0CF+Tjk+64hF53p3TmTytfNmziphv3m71mR8Ds8wdp2TDRqbQP4wuJzjAtwkoXKD3Ng=
Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=constructor.university;
Received: from GVXP190MB1991.EURP190.PROD.OUTLOOK.COM (2603:10a6:150:3::6) by DB9P190MB1404.EURP190.PROD.OUTLOOK.COM (2603:10a6:10:243::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6433.23; Tue, 30 May 2023 18:28:52 +0000
Received: from GVXP190MB1991.EURP190.PROD.OUTLOOK.COM ([fe80::581b:1ec3:e89b:df50]) by GVXP190MB1991.EURP190.PROD.OUTLOOK.COM ([fe80::581b:1ec3:e89b:df50%6]) with mapi id 15.20.6433.022; Tue, 30 May 2023 18:28:51 +0000
Date: Tue, 30 May 2023 20:28:49 +0200
From: Jürgen Schönwälder <jschoenwaelder@constructor.university>
To: "netmod@ietf.org" <netmod@ietf.org>
Message-ID: <jr5nepvspm3kpoxbv6dpxwi234ggjuthvckeerj2hb3g3qdc6x@4o42ngfbw72f>
Reply-To: Jürgen Schönwälder <jschoenwaelder@constructor.university>
Mail-Followup-To: "netmod@ietf.org" <netmod@ietf.org>
References: <01000187fd8e0407-84bd7e7b-ede3-43d8-a9b3-5d4d0a915509-000000@email.amazonses.com>
Content-Type: text/plain; charset="utf-8"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
In-Reply-To: <01000187fd8e0407-84bd7e7b-ede3-43d8-a9b3-5d4d0a915509-000000@email.amazonses.com>
X-ClientProxiedBy: AM4PR05CA0005.eurprd05.prod.outlook.com (2603:10a6:205::18) To GVXP190MB1991.EURP190.PROD.OUTLOOK.COM (2603:10a6:150:3::6)
MIME-Version: 1.0
X-MS-PublicTrafficType: Email
X-MS-TrafficTypeDiagnostic: GVXP190MB1991:EE_|DB9P190MB1404:EE_
X-MS-Office365-Filtering-Correlation-Id: ce85f316-83ab-44da-0609-08db613bb781
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: YKFpgFswjqmz6EbsYXHS8K8nP/o07J/Cy744mkiLQMQAFuaXSR1iYeq3K31og+ahx3BpWDod3u3U1fXd9R3Fp7h98UO0iz035cJVQ/otfb1ih/pnHqM2/K8osUDqmyKzE4yTvvIQrJk3wS7L+MvCV+pw08YsMZV0DSvsmCO72QHcnPz5W681DwK+3FjJq4iqmw8F5Zl/2hC1lIRtm8kAwbGt105HH4ilqHBUQULfdCT9Qjg877TsUWII/wZNz7bUKoEOH+Q0z3Fb6bDiqf+MCqyGaTf5sPVwX9vOMxCpLImyZEBChfnD622IFUd+sFpJie2pSQNgs+Azd6xndvZOnTesFPT/OTUp9la/qozsziZ4IuLlUjCbLO9whyx9grEwXJY5SXcEhmYN1mmaFITvaacN/WgqgnBop2mxwf//3MpMID+AYzptemcw2cvkayUqMebWu+TSaxs8J4iy34MegTMWhJMdiD6c0rSieX7/aHD4FspVDDIImhaemWAXowHy9f4RtzEUdyRWS7uRIRI34YDHVrlfXlMa2wnNQShSkDxMNOR5C8b5LCwahJKQnqIRsSpV6fLQXVmCR7r/vRMleB6BAt0BzBKRm1FNHilg1EjBjZaTFaaoWdrKYJI3dZlK
X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:GVXP190MB1991.EURP190.PROD.OUTLOOK.COM; PTR:; CAT:NONE; SFS:(13230028)(7916004)(346002)(396003)(376002)(136003)(39860400002)(366004)(451199021)(5660300002)(8936002)(38350700002)(9686003)(38100700002)(26005)(6512007)(6506007)(83380400001)(3450700001)(2906002)(30864003)(8676002)(186003)(66574015)(40140700001)(316002)(6486002)(786003)(6916009)(41320700001)(33716001)(966005)(52116002)(41300700001)(66556008)(66946007)(85182001)(66476007)(85202003)(478600001)(66899021)(46492015); DIR:OUT; SFP:1101;
X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1
X-MS-Exchange-AntiSpam-MessageData-0: T2BTLASm/+ooqXysfu8q2UY5BuZLSHqCKbCJXCFQsuR2shJ1o7GmTmxAkz+WVCeulVOyFQA2faKp/n4dlg2cmSTrACoqlDF3Vcf72JgmVZWZXx7Cn6YaEPvXmSYkr/RtpiUqDBY27WqKLRWD+g2N78HZi+Ig+dkdml/bJhphLjasa8EqjxOH5YpPMUR/BF8F3q4n8zg4BJpTS0/05SKN3t3sknGnqVg4ShI35iul++zn63PWU6c5Q9LNFN2Fx/GynBnAw4GPa+tn3Zd6ych0dQQ3xqerCxdOBYy8o/NxPSwx9kt0QAogcZlUuKS4BkOwdGCsWCnRVW2AbkIsGzBjp3NpkV7GRA87OkHfZNE2lqx+bC/2sXpR4XkesMhUoYsaD9Hnl5hq8msR3kL/kx2bnaT2sBwsnsioMwoJe5O1z+ybm8+Z1EU+xitnAxXGkqs0CKIkoEJ5zghbPUYfgkaOXcFT2s+96Zj/+XBE3MRSz1TgOeY+MlEc191EzwNIjeyJZnLEqAJs+P6zl6euVMAMcWhDLVIwK63uc5Xinoh4oQ5/X3FlDfn/yYrhtv2r5tM9zufSD1WhD4rnHQE9rSH7eyXD2mPtsNpGr/QKEyI0a783fJ5tpJ4zw+q70oSqpiM8lIt/9Egv8KjMay1jDr5XqV0IFZprgGSOvgxzqEARgqjSTHvxUUF2GShVcx36Yl7hfAL4vdaKEY/Q3JDS67x0O+VrJuBm7uIu2pcDP63Lkm+1T/xBIaeJi5NPhNjVY9dPQh90Jv64jk83I9FOpvfVrOIcr1Swsk7IJJci3FiuPUGLbavfGnBQ+5Os43VhJmMoeb0KSDCJlPmnOuweouagwUTYFxh36O85oPEG/zTB1nHCftE0pnGYn3w6joRZVCzvWjiBNX605MNFk4CqOSaasKgZYtt7URXZGOS4XVG9ida2sS3nuPxTvJOmKxov89qQi7emHfAio5RvPOyYnd+pLTGI0SP4+xBtwn4kYgSWvl4v7HoJSkvt1WJOlX7sN9gJ5iQKxPZxEFTaj/fHvyoUNjwCzNF3oGml+5Kp//EvPRqRLrxiAQqJyWdrQflOLXegg42Hb4k/1ZbSqJCPC0uXA5SBEJnwCfsrYpbTTgCum7Y5A2F1bW5+MLeBD9LNsqkYkfjyoT8epez+6hyA9NA21p/ImANH9ONLDqYEoYYUztYH7pig5DjcBRiLHLzELpmFma1hTCtO6vo7A+FPYg1u/CLXxHoX7HGoxe6MtjSRzov8QYTqBGCQpPksxiAPgu/Vz6xRDfNLEop68AjzfPXcBf0i4vd9EkKrY7DIiIYq4ZhrmEcE7BV0cmxoGdPP8rRT30jCpjzF5JPxFvulH3MHhs5dMNeRRs6Q+LoQIwmfMr9bPjLuI+878SUkWVvQhpYOEDBhi0ji0iyd2cMVPqRdFe9QhRqSobAOTPxT7uJkcKo61wi37zYPJ01/EuAKMe102TbLNImI2kWIVNTp5H3TSSXdX066zIXz1+gOaoGU0+X8KGzC74wyhfiYypD8LsCWz6vWRAhtP+yw0QYO2XzxzfqkqHdluyhEuOj3WVEtIQB8I4/5kQvvvUKFW6xA0KYRoyZwUs6ofWsFvhyo61IFuwBAbYWJOsb7Ut0JE9TH0j8=
X-OriginatorOrg: constructor.university
X-MS-Exchange-CrossTenant-Network-Message-Id: ce85f316-83ab-44da-0609-08db613bb781
X-MS-Exchange-CrossTenant-AuthSource: GVXP190MB1991.EURP190.PROD.OUTLOOK.COM
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 May 2023 18:28:51.4566 (UTC)
X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
X-MS-Exchange-CrossTenant-Id: f78e973e-5c0b-4ab8-bbd7-9887c95a8ebd
X-MS-Exchange-CrossTenant-MailboxType: HOSTED
X-MS-Exchange-CrossTenant-UserPrincipalName: rjzeHrB4Y8vZLPzmm3x57Ab25UlG4ZkExshP54AF3FQ0riIC1u2Y2bSVXM4lG9Wg2qSqzb5DjjQu+1fjMjA8UBkalsHPmlCRohU15Mh3+1w=
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB9P190MB1404
Archived-At: <https://mailarchive.ietf.org/arch/msg/netmod/NZmnBBRUu_wIq0_NUQ2v8aXQ3p4>
Subject: Re: [netmod] Joint WGLC on "semver" and "module-versioning" drafts
X-BeenThere: netmod@ietf.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: NETMOD WG list <netmod.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/netmod>, <mailto:netmod-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/netmod/>
List-Post: <mailto:netmod@ietf.org>
List-Help: <mailto:netmod-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/netmod>, <mailto:netmod-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 30 May 2023 18:29:08 -0000

On Mon, May 08, 2023 at 10:49:15PM +0000, Kent Watsen wrote:
> Dear NETMOD WG,
> 
> This message begins a joint two-week WGLC for draft-ietf-netmod-yang-semver-11 and draft-ietf-netmod-yang-module-versioning-09
>  ending on Monday, May 22nd.  Neither draft has IPR declared.  Here are the direct links to the HTML version for these drafts:
> 
>    - https://datatracker.ietf.org/doc/html/draft-ietf-netmod-yang-semver-11
>    - https://datatracker.ietf.org/doc/html/draft-ietf-netmod-yang-module-versioning-09
> 
> Positive comments, e.g., "I've reviewed this document and believe it is ready for publication", are welcome!  This is useful and important, even from authors.  Objections, concerns, and suggestions are also welcomed at this time.
>

Comments on draft-ietf-netmod-yang-module-versioning-09.txt:

- My opinion about changing YANG 1.1 rules without bumping the YANG
  version number is likely clear to everyone so I won't repeat it
  here.

- YANG 1.1 does not have an import by minimum revision, which clearly
  is a bug in YANG 1.1. This document now introduces a "soft" version
  of an import by minimum revision but the sad story is that this
  remains again incomplete from the perspective of the new versioning
  scheme. If we allow NBC changes, then it is necessary to express
  revision ranges since the definitions a module depends on can appear
  at revision a.b.c and disappear at revision e.f.g (and perhaps even
  reappear in revision h.i.j). Hence, we again have an incomplete
  solution.

- Do we really need to support multiple 'revision label schemes'? If
  so, we have to work out more details. What kind of order properties
  do we expect from revision label schemes? And what is the
  relationship between a versioning scheme and a revision label
  scheme? Can you mix and match revision label schemes? What happens
  to revision labels encoded in file names, can there be collisions
  between different revision label schemes?  Perhaps we are
  over-engineering here and one 'revision label scheme' that people
  can agree on is sufficient and simplifies things?

- Instead of multiple 'revision label schemes' for the same
  'versioning scheme', I think it makes sense to consider support of
  multiple 'versioning schemes' (not just different label schemes, for
  me different labels expressing the same information are pointless).
  Can we design a solution where the original 'linear order always
  backwards compatible versioning scheme' of RFC 7950 becomes just one
  of several versioning schemes we have? This would essentially mean
  that the update rules become a property of a versioning scheme
  instead of being a hardwired property of the language. Perhaps there
  could even be space for a third 'null versioning scheme' that defers
  all versioning to a package solution where the package definitions
  define which modules work together, i.e., we focus on versioning
  packages instead of individual modules.

- I suggested (long time ago) to maintain versioning constraints
  outside of the modules. This allows to update import constraints
  without having to edit and republish modules. (And versioning
  packages of modules may be more practical than versioning each and
  every module once a data model reach a certain size.) I guess I
  rather have semantic version numbers on packages of modules than on
  each and every module itself. The beginning of section 4 seems to be
  spot on but then we fall back doing the wrong thing.

- The document seems to be silent about how different versions can be
  supported. In the old world, having foo and foo2 coexist was easy,
  clients could gradually be updated to use foo2 instead of foo. In
  the new versioning world, this becomes more complex and may require
  protocol work. It remains unclear to me where and when this protocol
  work will be done.

- More specific comments follow. Concerning this:

   *  Any change made to the "revision-date" or "recommended-min"
      substatements of an "import" statement, including adding new
      "revision-date" or "recommended-min" substatements, changing the
      argument of any "revision-date" or "recommended-min"
      substatetements, or removing any "revision-date" or "recommended-
      min" substatements, is classified as backwards-compatible.

  Why is that? If I add/change recommended-min to a module revision
  that has NBC changes affecting the current module, then how can this
  be considered backwards compatible?

- Why do we tag modules with rev:non-backwards-compatible? Why do we
  not tag the concrete definitions that have non-backwards-compatible
  changes and then the rev:non-backwards-compatible is implied?

- What are the order rules for revision labels? A statement like
  rev:recommended-min only makes sense if there is a certain order
  defined.

- Concerning this:

    A specific revision label identifies a specific revision of the
    module.  If two YANG modules contain the same module name and the
    same revision label (and hence also the same revision-date) in their
    latest revision statement, then the file contents of the two modules,
    including the revision history, MUST be identical.

  It is unclear what "identical" means here. If two people extract a
  module from an RFC, they may not end up with identical byte
  sequences. So does white space matter when we talk about MUST be
  identical? What about comments? The problem is that the IETF still
  publishes YANG modules in RFCs instead of files.

- I do not know why we allow for multiple revision label schemes but
  since we do, what happens if different revision label schemes clash
  in the module file names? To properly support multiple revision
  label schemes properly, one would have to scope the revision labels
  in the file names, no? Do we really need to support multiple
  revision label schemes?

- I do not understand what section 6 is trying to achieve. There is a
  SHOULD that points to "e.g., [I-D.ietf-netmod-yang-packages]". How
  is someone going to implement this SHOULD? And does RFC 9195 not
  make use of YANG library? Is that not sufficient? Do the YANG
  library extensions apply to RFC 9195 or are they recommended to be
  used with RFC 9195?

- As mentioned earlier, my view is that the update rules are a part of
  a versioning scheme. Hence, if there are two or more versioning
  schemes, we should spell out the different updated rules for each
  versioning scheme.

Comments on draft-ietf-netmod-yang-semver-11:

- Is the end of the introduction telling me that the SemVer 2.0.0
  rules change in non-backwards compatible ways without the version
  number changing?

- The term 'YANG artifact' is imported from the packages draft, which
  has expired. I pulled out the expired version 03, I could not find a
  definition in there either.

- SemVer and YANG Semver look very similar and perhaps too similar or
  not similar enough. I do not have a good proposal, just noting a
  possible writing issue that we will have with Semver and SemVer.
  Why does 'Semver' and  'YANG SemVer' not do the job?

- Section 3.1 starts with a statement that SemVer and YANG Semver are
  'completely compatible'. While I started wondering what the
  difference between 'compatible' and 'completely compatible' might
  be, I was more confused to read this statement upfront, i.e., before
  I even get told what YANG Semver is. Perhaps first define what YANG
  Semver is and then discuss its relationship to SemVer?

- As already mentioned above, my take is that a 'versioning scheme'
  should use exactly one 'revision label scheme' and it should have
  specific 'module update rules' supporting the "versioning scheme".
  This does not seem to be the model that the draft authors use and I
  am a bit confused what their model is. In other words, I see

  YANG Semantic Versioning consists of
       -> YANG Semantic	Version Module Update Rules
       -> YANG Semantic Version Revision Label Scheme
       -> YANG Semantic Version Import Rules
       -> NC/RC/... version selection protocol mechanisms needed

  YANG Traditional Versioning consists of
       -> YANG's Traditional Module Update Rules
       -> YANG's Traditional Module Label Scheme (revision dates)
       -> YANG's Traditional Module Import Rules (lacking import by min revision)
       -> no specific protocol mechanisms needed to support transitions

  It seems we have not factored out an interface for plugging
  additional versioning models into YANG and the protocols providing
  access to YANG-defined data.

- Why do we need the _COMPATIBLE extension of SemVer? It would be nice
  to explain this more clearly, the best bit of explanation I found
  seems to be in situations where the next major version number has
  already been taken. But then SemVer does not support branching in
  general, why do we need a bit of this via the _COMPATIBLE extension?
  Did anyone suggest this addition to the SemVer people and what was
  their reaction, something they would consider adding to SemVer or
  more reservation about this being a proper solution?

- I prefer to have non-backwards compatible changes marked and
  explained in the modules instead of relying on some schema
  comparison algorithm.

- Does it make sense to have an example Package Using YANG Semver in
  this document given that YANG packages is not moving along with this
  document? Should the examples move to the appendix to make it
  clearer that they are just examples and non-normative?

- The import discussion ignores what happens if future versions are
  not providing the symbols anymore expected by an import. See my
  previous comment that compatibility may require ranges of version
  numbers, revision-or-derived is a half-baked solution.

- If we really want to support multiple revision label schemes, then
  creating a typedef 'version' which is YANG Semver specific may be a
  bit to simplistic. We would likely need a type that is extensible
  and qualified by a yang-semver identity, no? I am not asking for
  this, I rather question whether we really need to have open ended
  label schemes.

- Reference [openconfigsemver] resolves to an empty page (tried two
  browsers). Do you mean <https://www.openconfig.net/docs/guides/semver/>?

/js

-- 
Jürgen Schönwälder              Constructor University Bremen gGmbH
Phone: +49 421 200 3587         Campus Ring 1 | 28759 Bremen | Germany
Fax:   +49 421 200 3103         <https://constructor.university/>