From a3f5dd82197f51573856f7840d9cf42dee83c170 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Fri, 18 Nov 2022 14:37:36 +0100
Subject: [PATCH 001/606] [skip-changelog] Fixed integration test (#1985)

---
 test/test_lib.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/test_lib.py b/test/test_lib.py
index 747572a2ad9..7bef2000548 100644
--- a/test/test_lib.py
+++ b/test/test_lib.py
@@ -500,7 +500,7 @@ def test_search(run_command):
     assert "Downloading index: library_index.tar.bz2 downloaded" in lines
     libs = [l[6:].strip('"') for l in lines if "Name:" in l]
 
-    expected = {"WiFi101", "WiFi101OTA", "Firebase Arduino based on WiFi101"}
+    expected = {"WiFi101", "WiFi101OTA", "Firebase Arduino based on WiFi101", "WiFi101_Generic"}
     assert expected == {lib for lib in libs if "WiFi101" in lib}
 
     result = run_command(["lib", "search", "--names", "--format", "json"])

From b1150e01c7645872847fd5f736102186196157cc Mon Sep 17 00:00:00 2001
From: Silvano Cerza <3314350+silvanocerza@users.noreply.github.com>
Date: Mon, 21 Nov 2022 11:44:32 +0100
Subject: [PATCH 002/606] [breaking] Fix board attach CLI command, and remove
 gRPC API (#1930)

* Remove board attach cli interface

* Move tr function in separate file

* Remove BoardAttach gRPC interface command

* Remove BoardAttach calls from client_example

* go mod tidy

* Update board CLI command help text

Co-authored-by: Cristian Maglie <c.maglie@bug.st>

* Update dependency license metadata cache

* Re-Implementation of 'board attach' command

* Fixed comment indentation (gofmt)

* Update UPGRADING.md

* Added 'default_fqbn' and 'default_port' fields to sketch.yaml

* Added functions to load and save sketch project files

* Use sketch project file to determine default fqbn and port

* Implement 'attach board' using sketch project file

* Remove support for sketch.json

* Updated documentation

* Do not fully rewrite sketch.yaml when a key is automatically updated

* Fixed 'board attach' command output

* Do not write empty entries in sketch.yaml

* Apply suggestions from code review

Co-authored-by: per1234 <accounts@perglass.com>

* Update docs/UPGRADING.md

Co-authored-by: per1234 <accounts@perglass.com>

* Other suggestions from code review

* Updated UPGRADING.md

This change is going into 0.30.0

Co-authored-by: Cristian Maglie <c.maglie@bug.st>
Co-authored-by: per1234 <accounts@perglass.com>
Co-authored-by: Cristian Maglie <c.maglie@arduino.cc>
---
 .../arduino/board-discovery.dep.yml           | 358 ----------
 .licenses/go/github.com/codeclysm/cc.dep.yml  |  32 -
 .../github.com/fluxio/iohelpers/line.dep.yml  | 194 -----
 .../go/github.com/fluxio/multierror.dep.yml   | 194 -----
 .licenses/go/github.com/miekg/dns.dep.yml     |  54 --
 .../go/github.com/oleksandr/bonjour.dep.yml   |  34 -
 .licenses/go/go.bug.st/serial.v1.dep.yml      |  49 --
 .../go/go.bug.st/serial.v1/enumerator.dep.yml |  50 --
 .../go/go.bug.st/serial.v1/unixutils.dep.yml  |  49 --
 .licenses/go/golang.org/x/net/bpf.dep.yml     |  63 --
 .../go/golang.org/x/net/internal/iana.dep.yml |  63 --
 .../golang.org/x/net/internal/socket.dep.yml  |  62 --
 .licenses/go/golang.org/x/net/ipv4.dep.yml    |  63 --
 .licenses/go/golang.org/x/net/ipv6.dep.yml    |  63 --
 .licenses/go/gopkg.in/yaml.v3.dep.yml         |  80 +++
 arduino/discovery/discovery_client/go.sum     |   8 -
 arduino/sketch/profiles.go                    |  18 +-
 arduino/sketch/profiles_test.go               |  25 +-
 arduino/sketch/sketch.go                      | 115 ++-
 .../SketchWithDefaultFQBNAndPort.ino          |   0
 .../SketchWithDefaultFQBNAndPort/sketch.yml   |  13 +
 arduino/sketch/yaml.go                        |  91 +++
 arduino/sketch/yaml_test.go                   |  78 ++
 cli/arguments/fqbn.go                         |  14 +-
 cli/arguments/port.go                         |  21 +-
 cli/board/attach.go                           | 108 ++-
 cli/board/board.go                            |   4 +-
 client_example/go.sum                         |   8 -
 client_example/main.go                        |  40 --
 commands/board/attach.go                      | 168 -----
 commands/board/board.go                       |  20 +
 commands/compile/compile.go                   |   4 +-
 commands/daemon/daemon.go                     |  11 -
 commands/debug/debug_info.go                  |   4 +-
 docs/UPGRADING.md                             |  14 +
 docs/sketch-project-file.md                   |  21 +
 docs/sketch-specification.md                  |  16 +-
 docsgen/go.mod                                |   8 +-
 docsgen/go.sum                                |  16 -
 go.mod                                        |   9 +-
 go.sum                                        |  16 -
 rpc/cc/arduino/cli/commands/v1/board.pb.go    | 485 ++++---------
 rpc/cc/arduino/cli/commands/v1/board.proto    |  18 -
 rpc/cc/arduino/cli/commands/v1/commands.pb.go | 675 +++++++++---------
 rpc/cc/arduino/cli/commands/v1/commands.proto |   4 -
 .../cli/commands/v1/commands_grpc.pb.go       | 101 +--
 46 files changed, 1003 insertions(+), 2538 deletions(-)
 delete mode 100644 .licenses/go/github.com/arduino/board-discovery.dep.yml
 delete mode 100644 .licenses/go/github.com/codeclysm/cc.dep.yml
 delete mode 100644 .licenses/go/github.com/fluxio/iohelpers/line.dep.yml
 delete mode 100644 .licenses/go/github.com/fluxio/multierror.dep.yml
 delete mode 100644 .licenses/go/github.com/miekg/dns.dep.yml
 delete mode 100644 .licenses/go/github.com/oleksandr/bonjour.dep.yml
 delete mode 100644 .licenses/go/go.bug.st/serial.v1.dep.yml
 delete mode 100644 .licenses/go/go.bug.st/serial.v1/enumerator.dep.yml
 delete mode 100644 .licenses/go/go.bug.st/serial.v1/unixutils.dep.yml
 delete mode 100644 .licenses/go/golang.org/x/net/bpf.dep.yml
 delete mode 100644 .licenses/go/golang.org/x/net/internal/iana.dep.yml
 delete mode 100644 .licenses/go/golang.org/x/net/internal/socket.dep.yml
 delete mode 100644 .licenses/go/golang.org/x/net/ipv4.dep.yml
 delete mode 100644 .licenses/go/golang.org/x/net/ipv6.dep.yml
 create mode 100644 .licenses/go/gopkg.in/yaml.v3.dep.yml
 create mode 100644 arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/SketchWithDefaultFQBNAndPort.ino
 create mode 100644 arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/sketch.yml
 create mode 100644 arduino/sketch/yaml.go
 create mode 100644 arduino/sketch/yaml_test.go
 delete mode 100644 commands/board/attach.go
 create mode 100644 commands/board/board.go

diff --git a/.licenses/go/github.com/arduino/board-discovery.dep.yml b/.licenses/go/github.com/arduino/board-discovery.dep.yml
deleted file mode 100644
index 37f496951d0..00000000000
--- a/.licenses/go/github.com/arduino/board-discovery.dep.yml
+++ /dev/null
@@ -1,358 +0,0 @@
----
-name: github.com/arduino/board-discovery
-version: v0.0.0-20180823133458-1ba29327fb0c
-type: go
-summary: 'Package discovery keeps an updated list of the devices connected to the
-  computer, via serial ports or found in the network Usage: monitor := discovery.New(time.Millisecond)
-  ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) monitor.Start(ctx)
-  time.Sleep(10 * time.Second) fmt.Println(monitor.Serial()) fmt.Println(monitor.Network())
-  Output: map[/dev/ttyACM0:0x2341/0x8036] map[192.168.1.107:YunShield] You may also
-  decide to subscribe to the Events channel of the Monitor: monitor := discovery.New(time.Millisecond)
-  ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) monitor.Start(ctx)
-  for ev := range monitor.Events { fmt.Println(ev) } Output: {add 0x2341/0x8036 <nil>}
-  {add <nil> YunShield}'
-homepage: https://pkg.go.dev/github.com/arduino/board-discovery
-license: gpl-2.0-or-later
-licenses:
-- sources: LICENSE
-  text: |2
-                        GNU GENERAL PUBLIC LICENSE
-                           Version 2, June 1991
-
-     Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
-     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-     Everyone is permitted to copy and distribute verbatim copies
-     of this license document, but changing it is not allowed.
-
-                                Preamble
-
-      The licenses for most software are designed to take away your
-    freedom to share and change it.  By contrast, the GNU General Public
-    License is intended to guarantee your freedom to share and change free
-    software--to make sure the software is free for all its users.  This
-    General Public License applies to most of the Free Software
-    Foundation's software and to any other program whose authors commit to
-    using it.  (Some other Free Software Foundation software is covered by
-    the GNU Lesser General Public License instead.)  You can apply it to
-    your programs, too.
-
-      When we speak of free software, we are referring to freedom, not
-    price.  Our General Public Licenses are designed to make sure that you
-    have the freedom to distribute copies of free software (and charge for
-    this service if you wish), that you receive source code or can get it
-    if you want it, that you can change the software or use pieces of it
-    in new free programs; and that you know you can do these things.
-
-      To protect your rights, we need to make restrictions that forbid
-    anyone to deny you these rights or to ask you to surrender the rights.
-    These restrictions translate to certain responsibilities for you if you
-    distribute copies of the software, or if you modify it.
-
-      For example, if you distribute copies of such a program, whether
-    gratis or for a fee, you must give the recipients all the rights that
-    you have.  You must make sure that they, too, receive or can get the
-    source code.  And you must show them these terms so they know their
-    rights.
-
-      We protect your rights with two steps: (1) copyright the software, and
-    (2) offer you this license which gives you legal permission to copy,
-    distribute and/or modify the software.
-
-      Also, for each author's protection and ours, we want to make certain
-    that everyone understands that there is no warranty for this free
-    software.  If the software is modified by someone else and passed on, we
-    want its recipients to know that what they have is not the original, so
-    that any problems introduced by others will not reflect on the original
-    authors' reputations.
-
-      Finally, any free program is threatened constantly by software
-    patents.  We wish to avoid the danger that redistributors of a free
-    program will individually obtain patent licenses, in effect making the
-    program proprietary.  To prevent this, we have made it clear that any
-    patent must be licensed for everyone's free use or not licensed at all.
-
-      The precise terms and conditions for copying, distribution and
-    modification follow.
-
-                        GNU GENERAL PUBLIC LICENSE
-       TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-      0. This License applies to any program or other work which contains
-    a notice placed by the copyright holder saying it may be distributed
-    under the terms of this General Public License.  The "Program", below,
-    refers to any such program or work, and a "work based on the Program"
-    means either the Program or any derivative work under copyright law:
-    that is to say, a work containing the Program or a portion of it,
-    either verbatim or with modifications and/or translated into another
-    language.  (Hereinafter, translation is included without limitation in
-    the term "modification".)  Each licensee is addressed as "you".
-
-    Activities other than copying, distribution and modification are not
-    covered by this License; they are outside its scope.  The act of
-    running the Program is not restricted, and the output from the Program
-    is covered only if its contents constitute a work based on the
-    Program (independent of having been made by running the Program).
-    Whether that is true depends on what the Program does.
-
-      1. You may copy and distribute verbatim copies of the Program's
-    source code as you receive it, in any medium, provided that you
-    conspicuously and appropriately publish on each copy an appropriate
-    copyright notice and disclaimer of warranty; keep intact all the
-    notices that refer to this License and to the absence of any warranty;
-    and give any other recipients of the Program a copy of this License
-    along with the Program.
-
-    You may charge a fee for the physical act of transferring a copy, and
-    you may at your option offer warranty protection in exchange for a fee.
-
-      2. You may modify your copy or copies of the Program or any portion
-    of it, thus forming a work based on the Program, and copy and
-    distribute such modifications or work under the terms of Section 1
-    above, provided that you also meet all of these conditions:
-
-        a) You must cause the modified files to carry prominent notices
-        stating that you changed the files and the date of any change.
-
-        b) You must cause any work that you distribute or publish, that in
-        whole or in part contains or is derived from the Program or any
-        part thereof, to be licensed as a whole at no charge to all third
-        parties under the terms of this License.
-
-        c) If the modified program normally reads commands interactively
-        when run, you must cause it, when started running for such
-        interactive use in the most ordinary way, to print or display an
-        announcement including an appropriate copyright notice and a
-        notice that there is no warranty (or else, saying that you provide
-        a warranty) and that users may redistribute the program under
-        these conditions, and telling the user how to view a copy of this
-        License.  (Exception: if the Program itself is interactive but
-        does not normally print such an announcement, your work based on
-        the Program is not required to print an announcement.)
-
-    These requirements apply to the modified work as a whole.  If
-    identifiable sections of that work are not derived from the Program,
-    and can be reasonably considered independent and separate works in
-    themselves, then this License, and its terms, do not apply to those
-    sections when you distribute them as separate works.  But when you
-    distribute the same sections as part of a whole which is a work based
-    on the Program, the distribution of the whole must be on the terms of
-    this License, whose permissions for other licensees extend to the
-    entire whole, and thus to each and every part regardless of who wrote it.
-
-    Thus, it is not the intent of this section to claim rights or contest
-    your rights to work written entirely by you; rather, the intent is to
-    exercise the right to control the distribution of derivative or
-    collective works based on the Program.
-
-    In addition, mere aggregation of another work not based on the Program
-    with the Program (or with a work based on the Program) on a volume of
-    a storage or distribution medium does not bring the other work under
-    the scope of this License.
-
-      3. You may copy and distribute the Program (or a work based on it,
-    under Section 2) in object code or executable form under the terms of
-    Sections 1 and 2 above provided that you also do one of the following:
-
-        a) Accompany it with the complete corresponding machine-readable
-        source code, which must be distributed under the terms of Sections
-        1 and 2 above on a medium customarily used for software interchange; or,
-
-        b) Accompany it with a written offer, valid for at least three
-        years, to give any third party, for a charge no more than your
-        cost of physically performing source distribution, a complete
-        machine-readable copy of the corresponding source code, to be
-        distributed under the terms of Sections 1 and 2 above on a medium
-        customarily used for software interchange; or,
-
-        c) Accompany it with the information you received as to the offer
-        to distribute corresponding source code.  (This alternative is
-        allowed only for noncommercial distribution and only if you
-        received the program in object code or executable form with such
-        an offer, in accord with Subsection b above.)
-
-    The source code for a work means the preferred form of the work for
-    making modifications to it.  For an executable work, complete source
-    code means all the source code for all modules it contains, plus any
-    associated interface definition files, plus the scripts used to
-    control compilation and installation of the executable.  However, as a
-    special exception, the source code distributed need not include
-    anything that is normally distributed (in either source or binary
-    form) with the major components (compiler, kernel, and so on) of the
-    operating system on which the executable runs, unless that component
-    itself accompanies the executable.
-
-    If distribution of executable or object code is made by offering
-    access to copy from a designated place, then offering equivalent
-    access to copy the source code from the same place counts as
-    distribution of the source code, even though third parties are not
-    compelled to copy the source along with the object code.
-
-      4. You may not copy, modify, sublicense, or distribute the Program
-    except as expressly provided under this License.  Any attempt
-    otherwise to copy, modify, sublicense or distribute the Program is
-    void, and will automatically terminate your rights under this License.
-    However, parties who have received copies, or rights, from you under
-    this License will not have their licenses terminated so long as such
-    parties remain in full compliance.
-
-      5. You are not required to accept this License, since you have not
-    signed it.  However, nothing else grants you permission to modify or
-    distribute the Program or its derivative works.  These actions are
-    prohibited by law if you do not accept this License.  Therefore, by
-    modifying or distributing the Program (or any work based on the
-    Program), you indicate your acceptance of this License to do so, and
-    all its terms and conditions for copying, distributing or modifying
-    the Program or works based on it.
-
-      6. Each time you redistribute the Program (or any work based on the
-    Program), the recipient automatically receives a license from the
-    original licensor to copy, distribute or modify the Program subject to
-    these terms and conditions.  You may not impose any further
-    restrictions on the recipients' exercise of the rights granted herein.
-    You are not responsible for enforcing compliance by third parties to
-    this License.
-
-      7. If, as a consequence of a court judgment or allegation of patent
-    infringement or for any other reason (not limited to patent issues),
-    conditions are imposed on you (whether by court order, agreement or
-    otherwise) that contradict the conditions of this License, they do not
-    excuse you from the conditions of this License.  If you cannot
-    distribute so as to satisfy simultaneously your obligations under this
-    License and any other pertinent obligations, then as a consequence you
-    may not distribute the Program at all.  For example, if a patent
-    license would not permit royalty-free redistribution of the Program by
-    all those who receive copies directly or indirectly through you, then
-    the only way you could satisfy both it and this License would be to
-    refrain entirely from distribution of the Program.
-
-    If any portion of this section is held invalid or unenforceable under
-    any particular circumstance, the balance of the section is intended to
-    apply and the section as a whole is intended to apply in other
-    circumstances.
-
-    It is not the purpose of this section to induce you to infringe any
-    patents or other property right claims or to contest validity of any
-    such claims; this section has the sole purpose of protecting the
-    integrity of the free software distribution system, which is
-    implemented by public license practices.  Many people have made
-    generous contributions to the wide range of software distributed
-    through that system in reliance on consistent application of that
-    system; it is up to the author/donor to decide if he or she is willing
-    to distribute software through any other system and a licensee cannot
-    impose that choice.
-
-    This section is intended to make thoroughly clear what is believed to
-    be a consequence of the rest of this License.
-
-      8. If the distribution and/or use of the Program is restricted in
-    certain countries either by patents or by copyrighted interfaces, the
-    original copyright holder who places the Program under this License
-    may add an explicit geographical distribution limitation excluding
-    those countries, so that distribution is permitted only in or among
-    countries not thus excluded.  In such case, this License incorporates
-    the limitation as if written in the body of this License.
-
-      9. The Free Software Foundation may publish revised and/or new versions
-    of the General Public License from time to time.  Such new versions will
-    be similar in spirit to the present version, but may differ in detail to
-    address new problems or concerns.
-
-    Each version is given a distinguishing version number.  If the Program
-    specifies a version number of this License which applies to it and "any
-    later version", you have the option of following the terms and conditions
-    either of that version or of any later version published by the Free
-    Software Foundation.  If the Program does not specify a version number of
-    this License, you may choose any version ever published by the Free Software
-    Foundation.
-
-      10. If you wish to incorporate parts of the Program into other free
-    programs whose distribution conditions are different, write to the author
-    to ask for permission.  For software which is copyrighted by the Free
-    Software Foundation, write to the Free Software Foundation; we sometimes
-    make exceptions for this.  Our decision will be guided by the two goals
-    of preserving the free status of all derivatives of our free software and
-    of promoting the sharing and reuse of software generally.
-
-                                NO WARRANTY
-
-      11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-    REPAIR OR CORRECTION.
-
-      12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-    POSSIBILITY OF SUCH DAMAGES.
-
-                         END OF TERMS AND CONDITIONS
-
-                How to Apply These Terms to Your New Programs
-
-      If you develop a new program, and you want it to be of the greatest
-    possible use to the public, the best way to achieve this is to make it
-    free software which everyone can redistribute and change under these terms.
-
-      To do so, attach the following notices to the program.  It is safest
-    to attach them to the start of each source file to most effectively
-    convey the exclusion of warranty; and each file should have at least
-    the "copyright" line and a pointer to where the full notice is found.
-
-        {description}
-        Copyright (C) {year}  {fullname}
-
-        This program is free software; you can redistribute it and/or modify
-        it under the terms of the GNU General Public License as published by
-        the Free Software Foundation; either version 2 of the License, or
-        (at your option) any later version.
-
-        This program is distributed in the hope that it will be useful,
-        but WITHOUT ANY WARRANTY; without even the implied warranty of
-        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-        GNU General Public License for more details.
-
-        You should have received a copy of the GNU General Public License along
-        with this program; if not, write to the Free Software Foundation, Inc.,
-        51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-    Also add information on how to contact you by electronic and paper mail.
-
-    If the program is interactive, make it output a short notice like this
-    when it starts in an interactive mode:
-
-        Gnomovision version 69, Copyright (C) year name of author
-        Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-        This is free software, and you are welcome to redistribute it
-        under certain conditions; type `show c' for details.
-
-    The hypothetical commands `show w' and `show c' should show the appropriate
-    parts of the General Public License.  Of course, the commands you use may
-    be called something other than `show w' and `show c'; they could even be
-    mouse-clicks or menu items--whatever suits your program.
-
-    You should also get your employer (if you work as a programmer) or your
-    school, if any, to sign a "copyright disclaimer" for the program, if
-    necessary.  Here is a sample; alter the names:
-
-      Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-      `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-      {signature of Ty Coon}, 1 April 1989
-      Ty Coon, President of Vice
-
-    This General Public License does not permit incorporating your program into
-    proprietary programs.  If your program is a subroutine library, you may
-    consider it more useful to permit linking proprietary applications with the
-    library.  If this is what you want to do, use the GNU Lesser General
-    Public License instead of this License.
-notices: []
diff --git a/.licenses/go/github.com/codeclysm/cc.dep.yml b/.licenses/go/github.com/codeclysm/cc.dep.yml
deleted file mode 100644
index 166f837c05a..00000000000
--- a/.licenses/go/github.com/codeclysm/cc.dep.yml
+++ /dev/null
@@ -1,32 +0,0 @@
----
-name: github.com/codeclysm/cc
-version: v1.2.2
-type: go
-summary: 
-homepage: https://pkg.go.dev/github.com/codeclysm/cc
-license: mit
-licenses:
-- sources: LICENSE
-  text: |
-    MIT License
-
-    Copyright (c) 2017 codeclysm
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy
-    of this software and associated documentation files (the "Software"), to deal
-    in the Software without restriction, including without limitation the rights
-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-    copies of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in all
-    copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-    SOFTWARE.
-notices: []
diff --git a/.licenses/go/github.com/fluxio/iohelpers/line.dep.yml b/.licenses/go/github.com/fluxio/iohelpers/line.dep.yml
deleted file mode 100644
index 1d12c9b5a8b..00000000000
--- a/.licenses/go/github.com/fluxio/iohelpers/line.dep.yml
+++ /dev/null
@@ -1,194 +0,0 @@
----
-name: github.com/fluxio/iohelpers/line
-version: v0.0.0-20160419043813-3a4dd67a94d2
-type: go
-summary: 
-homepage: https://pkg.go.dev/github.com/fluxio/iohelpers/line
-license: apache-2.0
-licenses:
-- sources: iohelpers@v0.0.0-20160419043813-3a4dd67a94d2/LICENSE
-  text: |2
-                                  Apache License
-                            Version 2.0, January 2004
-                         http://www.apache.org/licenses/
-
-    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-    1. Definitions.
-
-       "License" shall mean the terms and conditions for use, reproduction,
-       and distribution as defined by Sections 1 through 9 of this document.
-
-       "Licensor" shall mean the copyright owner or entity authorized by
-       the copyright owner that is granting the License.
-
-       "Legal Entity" shall mean the union of the acting entity and all
-       other entities that control, are controlled by, or are under common
-       control with that entity. For the purposes of this definition,
-       "control" means (i) the power, direct or indirect, to cause the
-       direction or management of such entity, whether by contract or
-       otherwise, or (ii) ownership of fifty percent (50%) or more of the
-       outstanding shares, or (iii) beneficial ownership of such entity.
-
-       "You" (or "Your") shall mean an individual or Legal Entity
-       exercising permissions granted by this License.
-
-       "Source" form shall mean the preferred form for making modifications,
-       including but not limited to software source code, documentation
-       source, and configuration files.
-
-       "Object" form shall mean any form resulting from mechanical
-       transformation or translation of a Source form, including but
-       not limited to compiled object code, generated documentation,
-       and conversions to other media types.
-
-       "Work" shall mean the work of authorship, whether in Source or
-       Object form, made available under the License, as indicated by a
-       copyright notice that is included in or attached to the work
-       (an example is provided in the Appendix below).
-
-       "Derivative Works" shall mean any work, whether in Source or Object
-       form, that is based on (or derived from) the Work and for which the
-       editorial revisions, annotations, elaborations, or other modifications
-       represent, as a whole, an original work of authorship. For the purposes
-       of this License, Derivative Works shall not include works that remain
-       separable from, or merely link (or bind by name) to the interfaces of,
-       the Work and Derivative Works thereof.
-
-       "Contribution" shall mean any work of authorship, including
-       the original version of the Work and any modifications or additions
-       to that Work or Derivative Works thereof, that is intentionally
-       submitted to Licensor for inclusion in the Work by the copyright owner
-       or by an individual or Legal Entity authorized to submit on behalf of
-       the copyright owner. For the purposes of this definition, "submitted"
-       means any form of electronic, verbal, or written communication sent
-       to the Licensor or its representatives, including but not limited to
-       communication on electronic mailing lists, source code control systems,
-       and issue tracking systems that are managed by, or on behalf of, the
-       Licensor for the purpose of discussing and improving the Work, but
-       excluding communication that is conspicuously marked or otherwise
-       designated in writing by the copyright owner as "Not a Contribution."
-
-       "Contributor" shall mean Licensor and any individual or Legal Entity
-       on behalf of whom a Contribution has been received by Licensor and
-       subsequently incorporated within the Work.
-
-    2. Grant of Copyright License. Subject to the terms and conditions of
-       this License, each Contributor hereby grants to You a perpetual,
-       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-       copyright license to reproduce, prepare Derivative Works of,
-       publicly display, publicly perform, sublicense, and distribute the
-       Work and such Derivative Works in Source or Object form.
-
-    3. Grant of Patent License. Subject to the terms and conditions of
-       this License, each Contributor hereby grants to You a perpetual,
-       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-       (except as stated in this section) patent license to make, have made,
-       use, offer to sell, sell, import, and otherwise transfer the Work,
-       where such license applies only to those patent claims licensable
-       by such Contributor that are necessarily infringed by their
-       Contribution(s) alone or by combination of their Contribution(s)
-       with the Work to which such Contribution(s) was submitted. If You
-       institute patent litigation against any entity (including a
-       cross-claim or counterclaim in a lawsuit) alleging that the Work
-       or a Contribution incorporated within the Work constitutes direct
-       or contributory patent infringement, then any patent licenses
-       granted to You under this License for that Work shall terminate
-       as of the date such litigation is filed.
-
-    4. Redistribution. You may reproduce and distribute copies of the
-       Work or Derivative Works thereof in any medium, with or without
-       modifications, and in Source or Object form, provided that You
-       meet the following conditions:
-
-       (a) You must give any other recipients of the Work or
-           Derivative Works a copy of this License; and
-
-       (b) You must cause any modified files to carry prominent notices
-           stating that You changed the files; and
-
-       (c) You must retain, in the Source form of any Derivative Works
-           that You distribute, all copyright, patent, trademark, and
-           attribution notices from the Source form of the Work,
-           excluding those notices that do not pertain to any part of
-           the Derivative Works; and
-
-       (d) If the Work includes a "NOTICE" text file as part of its
-           distribution, then any Derivative Works that You distribute must
-           include a readable copy of the attribution notices contained
-           within such NOTICE file, excluding those notices that do not
-           pertain to any part of the Derivative Works, in at least one
-           of the following places: within a NOTICE text file distributed
-           as part of the Derivative Works; within the Source form or
-           documentation, if provided along with the Derivative Works; or,
-           within a display generated by the Derivative Works, if and
-           wherever such third-party notices normally appear. The contents
-           of the NOTICE file are for informational purposes only and
-           do not modify the License. You may add Your own attribution
-           notices within Derivative Works that You distribute, alongside
-           or as an addendum to the NOTICE text from the Work, provided
-           that such additional attribution notices cannot be construed
-           as modifying the License.
-
-       You may add Your own copyright statement to Your modifications and
-       may provide additional or different license terms and conditions
-       for use, reproduction, or distribution of Your modifications, or
-       for any such Derivative Works as a whole, provided Your use,
-       reproduction, and distribution of the Work otherwise complies with
-       the conditions stated in this License.
-
-    5. Submission of Contributions. Unless You explicitly state otherwise,
-       any Contribution intentionally submitted for inclusion in the Work
-       by You to the Licensor shall be under the terms and conditions of
-       this License, without any additional terms or conditions.
-       Notwithstanding the above, nothing herein shall supersede or modify
-       the terms of any separate license agreement you may have executed
-       with Licensor regarding such Contributions.
-
-    6. Trademarks. This License does not grant permission to use the trade
-       names, trademarks, service marks, or product names of the Licensor,
-       except as required for reasonable and customary use in describing the
-       origin of the Work and reproducing the content of the NOTICE file.
-
-    7. Disclaimer of Warranty. Unless required by applicable law or
-       agreed to in writing, Licensor provides the Work (and each
-       Contributor provides its Contributions) on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied, including, without limitation, any warranties or conditions
-       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-       PARTICULAR PURPOSE. You are solely responsible for determining the
-       appropriateness of using or redistributing the Work and assume any
-       risks associated with Your exercise of permissions under this License.
-
-    8. Limitation of Liability. In no event and under no legal theory,
-       whether in tort (including negligence), contract, or otherwise,
-       unless required by applicable law (such as deliberate and grossly
-       negligent acts) or agreed to in writing, shall any Contributor be
-       liable to You for damages, including any direct, indirect, special,
-       incidental, or consequential damages of any character arising as a
-       result of this License or out of the use or inability to use the
-       Work (including but not limited to damages for loss of goodwill,
-       work stoppage, computer failure or malfunction, or any and all
-       other commercial damages or losses), even if such Contributor
-       has been advised of the possibility of such damages.
-
-    9. Accepting Warranty or Additional Liability. While redistributing
-       the Work or Derivative Works thereof, You may choose to offer,
-       and charge a fee for, acceptance of support, warranty, indemnity,
-       or other liability obligations and/or rights consistent with this
-       License. However, in accepting such obligations, You may act only
-       on Your own behalf and on Your sole responsibility, not on behalf
-       of any other Contributor, and only if You agree to indemnify,
-       defend, and hold each Contributor harmless for any liability
-       incurred by, or claims asserted against, such Contributor by reason
-       of your accepting any such warranty or additional liability.
-
-    END OF TERMS AND CONDITIONS
-- sources: iohelpers@v0.0.0-20160419043813-3a4dd67a94d2/README.md
-  text: |-
-    This software is licensed under Apache License, Version 2.0. Please see
-    [LICENSE](https://raw.githubusercontent.com/fluxio/iohelpers/master/LICENSE)
-    for more information.
-
-    Copyright© 2016, Flux Factory Inc.
-notices: []
diff --git a/.licenses/go/github.com/fluxio/multierror.dep.yml b/.licenses/go/github.com/fluxio/multierror.dep.yml
deleted file mode 100644
index efc9cff804a..00000000000
--- a/.licenses/go/github.com/fluxio/multierror.dep.yml
+++ /dev/null
@@ -1,194 +0,0 @@
----
-name: github.com/fluxio/multierror
-version: v0.0.0-20160419044231-9c68d39025e5
-type: go
-summary: Package multierror defines an error Accumulator to contain multiple errors.
-homepage: https://pkg.go.dev/github.com/fluxio/multierror
-license: apache-2.0
-licenses:
-- sources: LICENSE
-  text: |2
-                                  Apache License
-                            Version 2.0, January 2004
-                         http://www.apache.org/licenses/
-
-    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-    1. Definitions.
-
-       "License" shall mean the terms and conditions for use, reproduction,
-       and distribution as defined by Sections 1 through 9 of this document.
-
-       "Licensor" shall mean the copyright owner or entity authorized by
-       the copyright owner that is granting the License.
-
-       "Legal Entity" shall mean the union of the acting entity and all
-       other entities that control, are controlled by, or are under common
-       control with that entity. For the purposes of this definition,
-       "control" means (i) the power, direct or indirect, to cause the
-       direction or management of such entity, whether by contract or
-       otherwise, or (ii) ownership of fifty percent (50%) or more of the
-       outstanding shares, or (iii) beneficial ownership of such entity.
-
-       "You" (or "Your") shall mean an individual or Legal Entity
-       exercising permissions granted by this License.
-
-       "Source" form shall mean the preferred form for making modifications,
-       including but not limited to software source code, documentation
-       source, and configuration files.
-
-       "Object" form shall mean any form resulting from mechanical
-       transformation or translation of a Source form, including but
-       not limited to compiled object code, generated documentation,
-       and conversions to other media types.
-
-       "Work" shall mean the work of authorship, whether in Source or
-       Object form, made available under the License, as indicated by a
-       copyright notice that is included in or attached to the work
-       (an example is provided in the Appendix below).
-
-       "Derivative Works" shall mean any work, whether in Source or Object
-       form, that is based on (or derived from) the Work and for which the
-       editorial revisions, annotations, elaborations, or other modifications
-       represent, as a whole, an original work of authorship. For the purposes
-       of this License, Derivative Works shall not include works that remain
-       separable from, or merely link (or bind by name) to the interfaces of,
-       the Work and Derivative Works thereof.
-
-       "Contribution" shall mean any work of authorship, including
-       the original version of the Work and any modifications or additions
-       to that Work or Derivative Works thereof, that is intentionally
-       submitted to Licensor for inclusion in the Work by the copyright owner
-       or by an individual or Legal Entity authorized to submit on behalf of
-       the copyright owner. For the purposes of this definition, "submitted"
-       means any form of electronic, verbal, or written communication sent
-       to the Licensor or its representatives, including but not limited to
-       communication on electronic mailing lists, source code control systems,
-       and issue tracking systems that are managed by, or on behalf of, the
-       Licensor for the purpose of discussing and improving the Work, but
-       excluding communication that is conspicuously marked or otherwise
-       designated in writing by the copyright owner as "Not a Contribution."
-
-       "Contributor" shall mean Licensor and any individual or Legal Entity
-       on behalf of whom a Contribution has been received by Licensor and
-       subsequently incorporated within the Work.
-
-    2. Grant of Copyright License. Subject to the terms and conditions of
-       this License, each Contributor hereby grants to You a perpetual,
-       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-       copyright license to reproduce, prepare Derivative Works of,
-       publicly display, publicly perform, sublicense, and distribute the
-       Work and such Derivative Works in Source or Object form.
-
-    3. Grant of Patent License. Subject to the terms and conditions of
-       this License, each Contributor hereby grants to You a perpetual,
-       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-       (except as stated in this section) patent license to make, have made,
-       use, offer to sell, sell, import, and otherwise transfer the Work,
-       where such license applies only to those patent claims licensable
-       by such Contributor that are necessarily infringed by their
-       Contribution(s) alone or by combination of their Contribution(s)
-       with the Work to which such Contribution(s) was submitted. If You
-       institute patent litigation against any entity (including a
-       cross-claim or counterclaim in a lawsuit) alleging that the Work
-       or a Contribution incorporated within the Work constitutes direct
-       or contributory patent infringement, then any patent licenses
-       granted to You under this License for that Work shall terminate
-       as of the date such litigation is filed.
-
-    4. Redistribution. You may reproduce and distribute copies of the
-       Work or Derivative Works thereof in any medium, with or without
-       modifications, and in Source or Object form, provided that You
-       meet the following conditions:
-
-       (a) You must give any other recipients of the Work or
-           Derivative Works a copy of this License; and
-
-       (b) You must cause any modified files to carry prominent notices
-           stating that You changed the files; and
-
-       (c) You must retain, in the Source form of any Derivative Works
-           that You distribute, all copyright, patent, trademark, and
-           attribution notices from the Source form of the Work,
-           excluding those notices that do not pertain to any part of
-           the Derivative Works; and
-
-       (d) If the Work includes a "NOTICE" text file as part of its
-           distribution, then any Derivative Works that You distribute must
-           include a readable copy of the attribution notices contained
-           within such NOTICE file, excluding those notices that do not
-           pertain to any part of the Derivative Works, in at least one
-           of the following places: within a NOTICE text file distributed
-           as part of the Derivative Works; within the Source form or
-           documentation, if provided along with the Derivative Works; or,
-           within a display generated by the Derivative Works, if and
-           wherever such third-party notices normally appear. The contents
-           of the NOTICE file are for informational purposes only and
-           do not modify the License. You may add Your own attribution
-           notices within Derivative Works that You distribute, alongside
-           or as an addendum to the NOTICE text from the Work, provided
-           that such additional attribution notices cannot be construed
-           as modifying the License.
-
-       You may add Your own copyright statement to Your modifications and
-       may provide additional or different license terms and conditions
-       for use, reproduction, or distribution of Your modifications, or
-       for any such Derivative Works as a whole, provided Your use,
-       reproduction, and distribution of the Work otherwise complies with
-       the conditions stated in this License.
-
-    5. Submission of Contributions. Unless You explicitly state otherwise,
-       any Contribution intentionally submitted for inclusion in the Work
-       by You to the Licensor shall be under the terms and conditions of
-       this License, without any additional terms or conditions.
-       Notwithstanding the above, nothing herein shall supersede or modify
-       the terms of any separate license agreement you may have executed
-       with Licensor regarding such Contributions.
-
-    6. Trademarks. This License does not grant permission to use the trade
-       names, trademarks, service marks, or product names of the Licensor,
-       except as required for reasonable and customary use in describing the
-       origin of the Work and reproducing the content of the NOTICE file.
-
-    7. Disclaimer of Warranty. Unless required by applicable law or
-       agreed to in writing, Licensor provides the Work (and each
-       Contributor provides its Contributions) on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied, including, without limitation, any warranties or conditions
-       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-       PARTICULAR PURPOSE. You are solely responsible for determining the
-       appropriateness of using or redistributing the Work and assume any
-       risks associated with Your exercise of permissions under this License.
-
-    8. Limitation of Liability. In no event and under no legal theory,
-       whether in tort (including negligence), contract, or otherwise,
-       unless required by applicable law (such as deliberate and grossly
-       negligent acts) or agreed to in writing, shall any Contributor be
-       liable to You for damages, including any direct, indirect, special,
-       incidental, or consequential damages of any character arising as a
-       result of this License or out of the use or inability to use the
-       Work (including but not limited to damages for loss of goodwill,
-       work stoppage, computer failure or malfunction, or any and all
-       other commercial damages or losses), even if such Contributor
-       has been advised of the possibility of such damages.
-
-    9. Accepting Warranty or Additional Liability. While redistributing
-       the Work or Derivative Works thereof, You may choose to offer,
-       and charge a fee for, acceptance of support, warranty, indemnity,
-       or other liability obligations and/or rights consistent with this
-       License. However, in accepting such obligations, You may act only
-       on Your own behalf and on Your sole responsibility, not on behalf
-       of any other Contributor, and only if You agree to indemnify,
-       defend, and hold each Contributor harmless for any liability
-       incurred by, or claims asserted against, such Contributor by reason
-       of your accepting any such warranty or additional liability.
-
-    END OF TERMS AND CONDITIONS
-- sources: README.md
-  text: |-
-    This software is licensed under Apache License, Version 2.0. Please see
-    [LICENSE](https://raw.githubusercontent.com/fluxio/multierror/master/LICENSE)
-    for more information.
-
-    Copyright© 2016, Flux Factory Inc.
-notices: []
diff --git a/.licenses/go/github.com/miekg/dns.dep.yml b/.licenses/go/github.com/miekg/dns.dep.yml
deleted file mode 100644
index b1400dedfbf..00000000000
--- a/.licenses/go/github.com/miekg/dns.dep.yml
+++ /dev/null
@@ -1,54 +0,0 @@
----
-name: github.com/miekg/dns
-version: v1.1.43
-type: go
-summary: Package dns implements a full featured interface to the Domain Name System.
-homepage: https://pkg.go.dev/github.com/miekg/dns
-license: bsd-3-clause
-licenses:
-- sources: LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-    As this is fork of the official Go code the same license applies.
-    Extensions of the original work are copyright (c) 2011 Miek Gieben
-- sources: COPYRIGHT
-  text: |
-    Copyright 2009 The Go Authors. All rights reserved. Use of this source code
-    is governed by a BSD-style license that can be found in the LICENSE file.
-    Extensions of the original work are copyright (c) 2011 Miek Gieben
-
-    Copyright 2011 Miek Gieben. All rights reserved. Use of this source code is
-    governed by a BSD-style license that can be found in the LICENSE file.
-
-    Copyright 2014 CloudFlare. All rights reserved. Use of this source code is
-    governed by a BSD-style license that can be found in the LICENSE file.
-notices:
-- sources: AUTHORS
-  text: Miek Gieben <miek@miek.nl>
diff --git a/.licenses/go/github.com/oleksandr/bonjour.dep.yml b/.licenses/go/github.com/oleksandr/bonjour.dep.yml
deleted file mode 100644
index c79e98fe034..00000000000
--- a/.licenses/go/github.com/oleksandr/bonjour.dep.yml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-name: github.com/oleksandr/bonjour
-version: v0.0.0-20160508152359-5dcf00d8b228
-type: go
-summary: bonjour This is a simple Multicast DNS-SD (Apple Bonjour) library written
-  in Golang.
-homepage: https://pkg.go.dev/github.com/oleksandr/bonjour
-license: mit
-licenses:
-- sources: LICENSE
-  text: |+
-    The MIT License (MIT)
-
-    Copyright (c) 2014 Oleksandr Lobunets
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy
-    of this software and associated documentation files (the "Software"), to deal
-    in the Software without restriction, including without limitation the rights
-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-    copies of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in all
-    copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-    SOFTWARE.
-
-notices: []
diff --git a/.licenses/go/go.bug.st/serial.v1.dep.yml b/.licenses/go/go.bug.st/serial.v1.dep.yml
deleted file mode 100644
index 001536e60c6..00000000000
--- a/.licenses/go/go.bug.st/serial.v1.dep.yml
+++ /dev/null
@@ -1,49 +0,0 @@
----
-name: go.bug.st/serial.v1
-version: v0.0.0-20180827123349-5f7892a7bb45
-type: go
-summary: Package serial is a cross-platform serial library for the go language.
-homepage: https://pkg.go.dev/go.bug.st/serial.v1
-license: bsd-3-clause
-licenses:
-- sources: LICENSE
-  text: |2+
-
-    Copyright (c) 2014-2016, Cristian Maglie.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in
-       the documentation and/or other materials provided with the
-       distribution.
-
-    3. Neither the name of the copyright holder nor the names of its
-       contributors may be used to endorse or promote products derived
-       from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-    COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-    POSSIBILITY OF SUCH DAMAGE.
-
-- sources: README.md
-  text: |-
-    The software is release under a BSD 3-clause license
-
-    https://github.com/bugst/go-serial/blob/v1/LICENSE
-notices: []
diff --git a/.licenses/go/go.bug.st/serial.v1/enumerator.dep.yml b/.licenses/go/go.bug.st/serial.v1/enumerator.dep.yml
deleted file mode 100644
index 34d70cf72a2..00000000000
--- a/.licenses/go/go.bug.st/serial.v1/enumerator.dep.yml
+++ /dev/null
@@ -1,50 +0,0 @@
----
-name: go.bug.st/serial.v1/enumerator
-version: v0.0.0-20180827123349-5f7892a7bb45
-type: go
-summary: Package enumerator is a golang cross-platform library for USB serial port
-  discovery.
-homepage: https://pkg.go.dev/go.bug.st/serial.v1/enumerator
-license: bsd-3-clause
-licenses:
-- sources: serial.v1@v0.0.0-20180827123349-5f7892a7bb45/LICENSE
-  text: |2+
-
-    Copyright (c) 2014-2016, Cristian Maglie.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in
-       the documentation and/or other materials provided with the
-       distribution.
-
-    3. Neither the name of the copyright holder nor the names of its
-       contributors may be used to endorse or promote products derived
-       from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-    COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-    POSSIBILITY OF SUCH DAMAGE.
-
-- sources: serial.v1@v0.0.0-20180827123349-5f7892a7bb45/README.md
-  text: |-
-    The software is release under a BSD 3-clause license
-
-    https://github.com/bugst/go-serial/blob/v1/LICENSE
-notices: []
diff --git a/.licenses/go/go.bug.st/serial.v1/unixutils.dep.yml b/.licenses/go/go.bug.st/serial.v1/unixutils.dep.yml
deleted file mode 100644
index f78d76a55fc..00000000000
--- a/.licenses/go/go.bug.st/serial.v1/unixutils.dep.yml
+++ /dev/null
@@ -1,49 +0,0 @@
----
-name: go.bug.st/serial.v1/unixutils
-version: v0.0.0-20180827123349-5f7892a7bb45
-type: go
-summary: 
-homepage: https://pkg.go.dev/go.bug.st/serial.v1/unixutils
-license: bsd-3-clause
-licenses:
-- sources: serial.v1@v0.0.0-20180827123349-5f7892a7bb45/LICENSE
-  text: |2+
-
-    Copyright (c) 2014-2016, Cristian Maglie.
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    1. Redistributions of source code must retain the above copyright
-       notice, this list of conditions and the following disclaimer.
-
-    2. Redistributions in binary form must reproduce the above copyright
-       notice, this list of conditions and the following disclaimer in
-       the documentation and/or other materials provided with the
-       distribution.
-
-    3. Neither the name of the copyright holder nor the names of its
-       contributors may be used to endorse or promote products derived
-       from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-    COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-    POSSIBILITY OF SUCH DAMAGE.
-
-- sources: serial.v1@v0.0.0-20180827123349-5f7892a7bb45/README.md
-  text: |-
-    The software is release under a BSD 3-clause license
-
-    https://github.com/bugst/go-serial/blob/v1/LICENSE
-notices: []
diff --git a/.licenses/go/golang.org/x/net/bpf.dep.yml b/.licenses/go/golang.org/x/net/bpf.dep.yml
deleted file mode 100644
index 930d81c9106..00000000000
--- a/.licenses/go/golang.org/x/net/bpf.dep.yml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-name: golang.org/x/net/bpf
-version: v0.0.0-20210505024714-0287a6fb4125
-type: go
-summary: Package bpf implements marshaling and unmarshaling of programs for the Berkeley
-  Packet Filter virtual machine, and provides a Go implementation of the virtual machine.
-homepage: https://pkg.go.dev/golang.org/x/net/bpf
-license: bsd-3-clause
-licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
-  text: |
-    Additional IP Rights Grant (Patents)
-
-    "This implementation" means the copyrightable works distributed by
-    Google as part of the Go project.
-
-    Google hereby grants to You a perpetual, worldwide, non-exclusive,
-    no-charge, royalty-free, irrevocable (except as stated in this section)
-    patent license to make, have made, use, offer to sell, sell, import,
-    transfer and otherwise run, modify and propagate the contents of this
-    implementation of Go, where such license applies only to those patent
-    claims, both currently owned or controlled by Google and acquired in
-    the future, licensable by Google that are necessarily infringed by this
-    implementation of Go.  This grant does not include claims that would be
-    infringed only as a consequence of further modification of this
-    implementation.  If you or your agent or exclusive licensee institute or
-    order or agree to the institution of patent litigation against any
-    entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that this implementation of Go or any code incorporated within this
-    implementation of Go constitutes direct or contributory patent
-    infringement, or inducement of patent infringement, then any patent
-    rights granted to you under this License for this implementation of Go
-    shall terminate as of the date such litigation is filed.
-notices: []
diff --git a/.licenses/go/golang.org/x/net/internal/iana.dep.yml b/.licenses/go/golang.org/x/net/internal/iana.dep.yml
deleted file mode 100644
index c12c484e19c..00000000000
--- a/.licenses/go/golang.org/x/net/internal/iana.dep.yml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-name: golang.org/x/net/internal/iana
-version: v0.0.0-20210505024714-0287a6fb4125
-type: go
-summary: Package iana provides protocol number resources managed by the Internet Assigned
-  Numbers Authority (IANA).
-homepage: https://pkg.go.dev/golang.org/x/net/internal/iana
-license: bsd-3-clause
-licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
-  text: |
-    Additional IP Rights Grant (Patents)
-
-    "This implementation" means the copyrightable works distributed by
-    Google as part of the Go project.
-
-    Google hereby grants to You a perpetual, worldwide, non-exclusive,
-    no-charge, royalty-free, irrevocable (except as stated in this section)
-    patent license to make, have made, use, offer to sell, sell, import,
-    transfer and otherwise run, modify and propagate the contents of this
-    implementation of Go, where such license applies only to those patent
-    claims, both currently owned or controlled by Google and acquired in
-    the future, licensable by Google that are necessarily infringed by this
-    implementation of Go.  This grant does not include claims that would be
-    infringed only as a consequence of further modification of this
-    implementation.  If you or your agent or exclusive licensee institute or
-    order or agree to the institution of patent litigation against any
-    entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that this implementation of Go or any code incorporated within this
-    implementation of Go constitutes direct or contributory patent
-    infringement, or inducement of patent infringement, then any patent
-    rights granted to you under this License for this implementation of Go
-    shall terminate as of the date such litigation is filed.
-notices: []
diff --git a/.licenses/go/golang.org/x/net/internal/socket.dep.yml b/.licenses/go/golang.org/x/net/internal/socket.dep.yml
deleted file mode 100644
index ec167bc67d3..00000000000
--- a/.licenses/go/golang.org/x/net/internal/socket.dep.yml
+++ /dev/null
@@ -1,62 +0,0 @@
----
-name: golang.org/x/net/internal/socket
-version: v0.0.0-20210505024714-0287a6fb4125
-type: go
-summary: Package socket provides a portable interface for socket system calls.
-homepage: https://pkg.go.dev/golang.org/x/net/internal/socket
-license: bsd-3-clause
-licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
-  text: |
-    Additional IP Rights Grant (Patents)
-
-    "This implementation" means the copyrightable works distributed by
-    Google as part of the Go project.
-
-    Google hereby grants to You a perpetual, worldwide, non-exclusive,
-    no-charge, royalty-free, irrevocable (except as stated in this section)
-    patent license to make, have made, use, offer to sell, sell, import,
-    transfer and otherwise run, modify and propagate the contents of this
-    implementation of Go, where such license applies only to those patent
-    claims, both currently owned or controlled by Google and acquired in
-    the future, licensable by Google that are necessarily infringed by this
-    implementation of Go.  This grant does not include claims that would be
-    infringed only as a consequence of further modification of this
-    implementation.  If you or your agent or exclusive licensee institute or
-    order or agree to the institution of patent litigation against any
-    entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that this implementation of Go or any code incorporated within this
-    implementation of Go constitutes direct or contributory patent
-    infringement, or inducement of patent infringement, then any patent
-    rights granted to you under this License for this implementation of Go
-    shall terminate as of the date such litigation is filed.
-notices: []
diff --git a/.licenses/go/golang.org/x/net/ipv4.dep.yml b/.licenses/go/golang.org/x/net/ipv4.dep.yml
deleted file mode 100644
index 4cbec101167..00000000000
--- a/.licenses/go/golang.org/x/net/ipv4.dep.yml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-name: golang.org/x/net/ipv4
-version: v0.0.0-20210505024714-0287a6fb4125
-type: go
-summary: Package ipv4 implements IP-level socket options for the Internet Protocol
-  version 4.
-homepage: https://pkg.go.dev/golang.org/x/net/ipv4
-license: bsd-3-clause
-licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
-  text: |
-    Additional IP Rights Grant (Patents)
-
-    "This implementation" means the copyrightable works distributed by
-    Google as part of the Go project.
-
-    Google hereby grants to You a perpetual, worldwide, non-exclusive,
-    no-charge, royalty-free, irrevocable (except as stated in this section)
-    patent license to make, have made, use, offer to sell, sell, import,
-    transfer and otherwise run, modify and propagate the contents of this
-    implementation of Go, where such license applies only to those patent
-    claims, both currently owned or controlled by Google and acquired in
-    the future, licensable by Google that are necessarily infringed by this
-    implementation of Go.  This grant does not include claims that would be
-    infringed only as a consequence of further modification of this
-    implementation.  If you or your agent or exclusive licensee institute or
-    order or agree to the institution of patent litigation against any
-    entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that this implementation of Go or any code incorporated within this
-    implementation of Go constitutes direct or contributory patent
-    infringement, or inducement of patent infringement, then any patent
-    rights granted to you under this License for this implementation of Go
-    shall terminate as of the date such litigation is filed.
-notices: []
diff --git a/.licenses/go/golang.org/x/net/ipv6.dep.yml b/.licenses/go/golang.org/x/net/ipv6.dep.yml
deleted file mode 100644
index ee73515956f..00000000000
--- a/.licenses/go/golang.org/x/net/ipv6.dep.yml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-name: golang.org/x/net/ipv6
-version: v0.0.0-20210505024714-0287a6fb4125
-type: go
-summary: Package ipv6 implements IP-level socket options for the Internet Protocol
-  version 6.
-homepage: https://pkg.go.dev/golang.org/x/net/ipv6
-license: bsd-3-clause
-licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
-  text: |
-    Additional IP Rights Grant (Patents)
-
-    "This implementation" means the copyrightable works distributed by
-    Google as part of the Go project.
-
-    Google hereby grants to You a perpetual, worldwide, non-exclusive,
-    no-charge, royalty-free, irrevocable (except as stated in this section)
-    patent license to make, have made, use, offer to sell, sell, import,
-    transfer and otherwise run, modify and propagate the contents of this
-    implementation of Go, where such license applies only to those patent
-    claims, both currently owned or controlled by Google and acquired in
-    the future, licensable by Google that are necessarily infringed by this
-    implementation of Go.  This grant does not include claims that would be
-    infringed only as a consequence of further modification of this
-    implementation.  If you or your agent or exclusive licensee institute or
-    order or agree to the institution of patent litigation against any
-    entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that this implementation of Go or any code incorporated within this
-    implementation of Go constitutes direct or contributory patent
-    infringement, or inducement of patent infringement, then any patent
-    rights granted to you under this License for this implementation of Go
-    shall terminate as of the date such litigation is filed.
-notices: []
diff --git a/.licenses/go/gopkg.in/yaml.v3.dep.yml b/.licenses/go/gopkg.in/yaml.v3.dep.yml
new file mode 100644
index 00000000000..e77248e581f
--- /dev/null
+++ b/.licenses/go/gopkg.in/yaml.v3.dep.yml
@@ -0,0 +1,80 @@
+---
+name: gopkg.in/yaml.v3
+version: v3.0.1
+type: go
+summary: Package yaml implements YAML support for the Go language.
+homepage: https://pkg.go.dev/gopkg.in/yaml.v3
+license: other
+licenses:
+- sources: LICENSE
+  text: |2
+
+    This project is covered by two different licenses: MIT and Apache.
+
+    #### MIT License ####
+
+    The following files were ported to Go from C files of libyaml, and thus
+    are still covered by their original MIT license, with the additional
+    copyright staring in 2011 when the project was ported over:
+
+        apic.go emitterc.go parserc.go readerc.go scannerc.go
+        writerc.go yamlh.go yamlprivateh.go
+
+    Copyright (c) 2006-2010 Kirill Simonov
+    Copyright (c) 2006-2011 Kirill Simonov
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy of
+    this software and associated documentation files (the "Software"), to deal in
+    the Software without restriction, including without limitation the rights to
+    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is furnished to do
+    so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+    SOFTWARE.
+
+    ### Apache License ###
+
+    All the remaining project files are covered by the Apache license:
+
+    Copyright (c) 2011-2019 Canonical Ltd
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+- sources: README.md
+  text: |-
+    The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+    Please see the LICENSE file for details.
+notices:
+- sources: NOTICE
+  text: |-
+    Copyright 2011-2016 Canonical Ltd.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
diff --git a/arduino/discovery/discovery_client/go.sum b/arduino/discovery/discovery_client/go.sum
index c0cef421c67..ee95d54ba27 100644
--- a/arduino/discovery/discovery_client/go.sum
+++ b/arduino/discovery/discovery_client/go.sum
@@ -42,7 +42,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
 github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c/go.mod h1:HK7SpkEax/3P+0w78iRQx1sz1vCDYYw9RXwHjQTB5i8=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.7.0 h1:S9l5BP2aogz1CgyqqnncXt0PLpK4yvwOW/wu/LaR3tc=
@@ -66,7 +65,6 @@ github.com/cmaglie/pb v1.0.27/go.mod h1:GilkKZMXYjBA4NxItWFfO+lwkp59PLHQ+IOW/b/k
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/codeclysm/cc v1.2.2/go.mod h1:XtW4ArCNgQwFphcRGG9+sPX5WM1J6/u0gMy5ZdV3obA=
 github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -88,8 +86,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2/go.mod h1:c7sGIpDbBo0JZZ1tKyC1p5smWf8QcUjK4bFtZjHAecg=
-github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5/go.mod h1:BEUDl7FG1cc76sM0J0x8dqr6RhiL4uqvk6oFkwuNyuM=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -235,7 +231,6 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
 github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -253,7 +248,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
 github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
-github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228/go.mod h1:MGuVJ1+5TX1SCoO2Sx0eAnjpdRytYla2uC1YIZfkC9c=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -313,7 +307,6 @@ go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
 go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII=
 go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
 go.bug.st/serial v1.3.2/go.mod h1:jDkjqASf/qSjmaOxHSHljwUQ6eHo/ZX/bxJLQqSlvZg=
-go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45/go.mod h1:dRSl/CVCTf56CkXgJMDOdSwNfo2g1orOGE/gBGdvjZw=
 go.bug.st/testifyjson v1.1.1/go.mod h1:nZyy2icFbv3OE3zW3mGVOnC/GhWgb93LRu+29n2tJlI=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
@@ -473,7 +466,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/arduino/sketch/profiles.go b/arduino/sketch/profiles.go
index 6a651f923fd..ccf8813b304 100644
--- a/arduino/sketch/profiles.go
+++ b/arduino/sketch/profiles.go
@@ -29,10 +29,13 @@ import (
 	"gopkg.in/yaml.v2"
 )
 
-// Project represents all the profiles defined for the sketch
+// Project represents the sketch project file
 type Project struct {
-	Profiles       Profiles `yaml:"profiles"`
-	DefaultProfile string   `yaml:"default_profile"`
+	Profiles        Profiles `yaml:"profiles"`
+	DefaultProfile  string   `yaml:"default_profile"`
+	DefaultFqbn     string   `yaml:"default_fqbn"`
+	DefaultPort     string   `yaml:"default_port,omitempty"`
+	DefaultProtocol string   `yaml:"default_protocol,omitempty"`
 }
 
 // AsYaml outputs the sketch project file as YAML
@@ -46,6 +49,15 @@ func (p *Project) AsYaml() string {
 	if p.DefaultProfile != "" {
 		res += fmt.Sprintf("default_profile: %s\n", p.DefaultProfile)
 	}
+	if p.DefaultFqbn != "" {
+		res += fmt.Sprintf("default_fqbn: %s\n", p.DefaultFqbn)
+	}
+	if p.DefaultPort != "" {
+		res += fmt.Sprintf("default_port: %s\n", p.DefaultPort)
+	}
+	if p.DefaultProtocol != "" {
+		res += fmt.Sprintf("default_protocol: %s\n", p.DefaultProtocol)
+	}
 	return res
 }
 
diff --git a/arduino/sketch/profiles_test.go b/arduino/sketch/profiles_test.go
index 133389fcd7c..e2595ed06f9 100644
--- a/arduino/sketch/profiles_test.go
+++ b/arduino/sketch/profiles_test.go
@@ -24,11 +24,22 @@ import (
 )
 
 func TestProjectFileLoading(t *testing.T) {
-	sketchProj := paths.New("testdata", "SketchWithProfiles", "sketch.yml")
-	proj, err := LoadProjectFile(sketchProj)
-	require.NoError(t, err)
-	fmt.Println(proj)
-	golden, err := sketchProj.ReadFile()
-	require.NoError(t, err)
-	require.Equal(t, proj.AsYaml(), string(golden))
+	{
+		sketchProj := paths.New("testdata", "SketchWithProfiles", "sketch.yml")
+		proj, err := LoadProjectFile(sketchProj)
+		require.NoError(t, err)
+		fmt.Println(proj)
+		golden, err := sketchProj.ReadFile()
+		require.NoError(t, err)
+		require.Equal(t, proj.AsYaml(), string(golden))
+	}
+	{
+		sketchProj := paths.New("testdata", "SketchWithDefaultFQBNAndPort", "sketch.yml")
+		proj, err := LoadProjectFile(sketchProj)
+		require.NoError(t, err)
+		fmt.Println(proj)
+		golden, err := sketchProj.ReadFile()
+		require.NoError(t, err)
+		require.Equal(t, proj.AsYaml(), string(golden))
+	}
 }
diff --git a/arduino/sketch/sketch.go b/arduino/sketch/sketch.go
index 6ad67a2daed..28aed70d861 100644
--- a/arduino/sketch/sketch.go
+++ b/arduino/sketch/sketch.go
@@ -18,7 +18,6 @@ package sketch
 import (
 	"crypto/md5"
 	"encoding/hex"
-	"encoding/json"
 	"fmt"
 	"sort"
 	"strings"
@@ -38,22 +37,9 @@ type Sketch struct {
 	OtherSketchFiles paths.PathList // Sketch files that end in .ino other than main file
 	AdditionalFiles  paths.PathList
 	RootFolderFiles  paths.PathList // All files that are in the Sketch root
-	Metadata         *Metadata
 	Project          *Project
 }
 
-// Metadata is the kind of data associated to a project such as the connected board
-type Metadata struct {
-	CPU BoardMetadata `json:"cpu,omitempty"`
-}
-
-// BoardMetadata represents the board metadata for the sketch
-type BoardMetadata struct {
-	Fqbn string `json:"fqbn"`
-	Name string `json:"name,omitempty"`
-	Port string `json:"port,omitempty"`
-}
-
 var tr = i18n.Tr
 
 // New creates an Sketch instance by reading all the files composing a sketch and grouping them
@@ -99,14 +85,10 @@ func New(path *paths.Path) (*Sketch, error) {
 		OtherSketchFiles: paths.PathList{},
 		AdditionalFiles:  paths.PathList{},
 		RootFolderFiles:  paths.PathList{},
-		Metadata:         new(Metadata),
+		Project:          &Project{},
 	}
 
-	projectFile := path.Join("sketch.yaml")
-	if !projectFile.Exist() {
-		projectFile = path.Join("sketch.yml")
-	}
-	if projectFile.Exist() {
+	if projectFile := sketch.GetProjectPath(); projectFile.Exist() {
 		prj, err := LoadProjectFile(projectFile)
 		if err != nil {
 			return nil, fmt.Errorf("%s %w", tr("error loading sketch project file:"), err)
@@ -172,9 +154,6 @@ func New(path *paths.Path) (*Sketch, error) {
 	sort.Sort(&sketch.OtherSketchFiles)
 	sort.Sort(&sketch.RootFolderFiles)
 
-	if err := sketch.importMetadata(); err != nil {
-		return nil, fmt.Errorf(tr("importing sketch metadata: %s"), err)
-	}
 	return sketch, nil
 }
 
@@ -199,46 +178,6 @@ func (s *Sketch) supportedFiles() (*paths.PathList, error) {
 
 }
 
-// ImportMetadata imports metadata into the sketch from a sketch.json file in the root
-// path of the sketch.
-func (s *Sketch) importMetadata() error {
-	sketchJSON := s.FullPath.Join("sketch.json")
-	if sketchJSON.NotExist() {
-		// File doesn't exist, nothing to import
-		return nil
-	}
-
-	content, err := sketchJSON.ReadFile()
-	if err != nil {
-		return fmt.Errorf(tr("reading sketch metadata %[1]s: %[2]s"), sketchJSON, err)
-	}
-	var meta Metadata
-	err = json.Unmarshal(content, &meta)
-	if err != nil {
-		if s.Metadata == nil {
-			s.Metadata = new(Metadata)
-		}
-		return fmt.Errorf(tr("encoding sketch metadata: %s"), err)
-	}
-	s.Metadata = &meta
-	return nil
-}
-
-// ExportMetadata writes sketch metadata into a sketch.json file in the root path of
-// the sketch
-func (s *Sketch) ExportMetadata() error {
-	d, err := json.MarshalIndent(&s.Metadata, "", "  ")
-	if err != nil {
-		return fmt.Errorf(tr("decoding sketch metadata: %s"), err)
-	}
-
-	sketchJSON := s.FullPath.Join("sketch.json")
-	if err := sketchJSON.WriteFile(d); err != nil {
-		return fmt.Errorf(tr("writing sketch metadata %[1]s: %[2]s"), sketchJSON, err)
-	}
-	return nil
-}
-
 // GetProfile returns the requested profile or nil if the profile
 // is not found.
 func (s *Sketch) GetProfile(profileName string) *Profile {
@@ -252,10 +191,13 @@ func (s *Sketch) GetProfile(profileName string) *Profile {
 
 // checkSketchCasing returns an error if the casing of the sketch folder and the main file are different.
 // Correct:
-//    MySketch/MySketch.ino
+//
+//	MySketch/MySketch.ino
+//
 // Wrong:
-//    MySketch/mysketch.ino
-//    mysketch/MySketch.ino
+//
+//	MySketch/mysketch.ino
+//	mysketch/MySketch.ino
 //
 // This is mostly necessary to avoid errors on Mac OS X.
 // For more info see: https://github.com/arduino/arduino-cli/issues/1174
@@ -283,6 +225,47 @@ func (s *Sketch) checkSketchCasing() error {
 	return nil
 }
 
+// GetProjectPath returns the path to the sketch project file (sketch.yaml or sketch.yml)
+func (s *Sketch) GetProjectPath() *paths.Path {
+	projectFile := s.FullPath.Join("sketch.yaml")
+	if !projectFile.Exist() {
+		alternateProjectFile := s.FullPath.Join("sketch.yml")
+		if alternateProjectFile.Exist() {
+			return alternateProjectFile
+		}
+	}
+	return projectFile
+}
+
+// GetDefaultFQBN returns the default FQBN for the sketch (from the sketch.yaml project file), or the
+// empty string if not set.
+func (s *Sketch) GetDefaultFQBN() string {
+	return s.Project.DefaultFqbn
+}
+
+// GetDefaultPortAddressAndProtocol returns the default port address and port protocol for the sketch
+// (from the sketch.yaml project file), or empty strings if not set.
+func (s *Sketch) GetDefaultPortAddressAndProtocol() (string, string) {
+	return s.Project.DefaultPort, s.Project.DefaultProtocol
+}
+
+// SetDefaultFQBN sets the default FQBN for the sketch and saves it in the sketch.yaml project file.
+func (s *Sketch) SetDefaultFQBN(fqbn string) error {
+	s.Project.DefaultFqbn = fqbn
+	return updateOrAddYamlRootEntry(s.GetProjectPath(), "default_fqbn", fqbn)
+}
+
+// SetDefaultPort sets the default port address and port protocol for the sketch and saves it in the
+// sketch.yaml project file.
+func (s *Sketch) SetDefaultPort(address, protocol string) error {
+	s.Project.DefaultPort = address
+	s.Project.DefaultProtocol = protocol
+	if err := updateOrAddYamlRootEntry(s.GetProjectPath(), "default_port", address); err != nil {
+		return err
+	}
+	return updateOrAddYamlRootEntry(s.GetProjectPath(), "default_protocol", protocol)
+}
+
 // InvalidSketchFolderNameError is returned when the sketch directory doesn't match the sketch name
 type InvalidSketchFolderNameError struct {
 	SketchFolder *paths.Path
diff --git a/arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/SketchWithDefaultFQBNAndPort.ino b/arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/SketchWithDefaultFQBNAndPort.ino
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/sketch.yml b/arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/sketch.yml
new file mode 100644
index 00000000000..84a79cf4ac2
--- /dev/null
+++ b/arduino/sketch/testdata/SketchWithDefaultFQBNAndPort/sketch.yml
@@ -0,0 +1,13 @@
+profiles:
+  nanorp:
+    fqbn: arduino:mbed_nano:nanorp2040connect
+    platforms:
+      - platform: arduino:mbed_nano (2.1.0)
+    libraries:
+      - ArduinoIoTCloud (1.0.2)
+      - Arduino_ConnectionHandler (0.6.4)
+      - TinyDHT sensor library (1.1.0)
+
+default_fqbn: arduino:avr:uno
+default_port: /dev/ttyACM0
+default_protocol: serial
diff --git a/arduino/sketch/yaml.go b/arduino/sketch/yaml.go
new file mode 100644
index 00000000000..952b200c225
--- /dev/null
+++ b/arduino/sketch/yaml.go
@@ -0,0 +1,91 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2020-2022 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package sketch
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/arduino/go-paths-helper"
+	"gopkg.in/yaml.v3"
+)
+
+// updateOrAddYamlRootEntry updates or adds a new entry to the root of the yaml file.
+// If the value is empty the entry is removed.
+func updateOrAddYamlRootEntry(path *paths.Path, key, newValue string) error {
+	var srcYaml []string
+	if path.Exist() {
+		src, err := path.ReadFileAsLines()
+		if err != nil {
+			return err
+		}
+		lastLine := len(src) - 1
+		if lastLine > 0 && src[lastLine] == "" {
+			srcYaml = src[:lastLine]
+		} else {
+			srcYaml = src
+		}
+	}
+
+	// Generate the new yaml key/value pair
+	v, err := yaml.Marshal(newValue)
+	if err != nil {
+		return err
+	}
+	updatedLine := key + ": " + strings.TrimSpace(string(v))
+
+	// Update or add the key/value pair into the original yaml
+	addMissing := (newValue != "")
+	for i, line := range srcYaml {
+		if strings.HasPrefix(line, key+": ") {
+			if newValue == "" {
+				// Remove the key/value pair
+				srcYaml = append(srcYaml[:i], srcYaml[i+1:]...)
+			} else {
+				// Update the key/value pair
+				srcYaml[i] = updatedLine
+			}
+			addMissing = false
+			break
+		}
+	}
+	if addMissing {
+		lastLine := len(srcYaml) - 1
+		if lastLine >= 0 && srcYaml[lastLine] == "" {
+			srcYaml[lastLine] = updatedLine
+		} else {
+			srcYaml = append(srcYaml, updatedLine)
+		}
+	}
+
+	// Validate the new yaml
+	dstYaml := []byte(strings.Join(srcYaml, fmt.Sprintln()) + fmt.Sprintln())
+	var dst interface{}
+	if err := yaml.Unmarshal(dstYaml, &dst); err != nil {
+		return fmt.Errorf("%s: %w", tr("could not update sketch project file"), err)
+	}
+	dstMap, ok := dst.(map[string]interface{})
+	if !ok {
+		return fmt.Errorf(tr("could not update sketch project file"))
+	}
+	writtenValue, notRemoved := dstMap[key]
+	if (newValue == "" && notRemoved) || (newValue != "" && newValue != writtenValue) {
+		return fmt.Errorf(tr("could not update sketch project file"))
+	}
+
+	// Write back the updated YAML
+	return path.WriteFile(dstYaml)
+}
diff --git a/arduino/sketch/yaml_test.go b/arduino/sketch/yaml_test.go
new file mode 100644
index 00000000000..e9eac6e6175
--- /dev/null
+++ b/arduino/sketch/yaml_test.go
@@ -0,0 +1,78 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2020-2022 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package sketch
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+
+	"github.com/arduino/go-paths-helper"
+	"github.com/stretchr/testify/require"
+)
+
+func TestYamlUpdate(t *testing.T) {
+	{
+		sample, err := paths.New("testdata", "SketchWithProfiles", "sketch.yml").ReadFile()
+		require.NoError(t, err)
+		tmp, err := paths.WriteToTempFile(sample, nil, "")
+		require.NoError(t, err)
+		defer tmp.Remove()
+
+		err = updateOrAddYamlRootEntry(tmp, "default_fqbn", "arduino:avr:uno")
+		require.NoError(t, err)
+		err = updateOrAddYamlRootEntry(tmp, "default_port", "/dev/ttyACM0")
+		require.NoError(t, err)
+
+		updated, err := tmp.ReadFile()
+		require.NoError(t, err)
+		expected := string(sample)
+		expected += fmt.Sprintln("default_fqbn: arduino:avr:uno")
+		expected += fmt.Sprintln("default_port: /dev/ttyACM0")
+		require.Equal(t, expected, string(updated))
+	}
+	{
+		sample, err := paths.New("testdata", "SketchWithDefaultFQBNAndPort", "sketch.yml").ReadFile()
+		require.NoError(t, err)
+		tmp, err := paths.WriteToTempFile(sample, nil, "")
+		require.NoError(t, err)
+		defer tmp.Remove()
+
+		err = updateOrAddYamlRootEntry(tmp, "default_fqbn", "TEST1")
+		require.NoError(t, err)
+		err = updateOrAddYamlRootEntry(tmp, "default_port", "TEST2")
+		require.NoError(t, err)
+
+		updated, err := tmp.ReadFile()
+		fmt.Print(string(updated))
+		require.NoError(t, err)
+		expected := strings.Replace(string(sample), "arduino:avr:uno", "TEST1", 1)
+		expected = strings.Replace(expected, "/dev/ttyACM0", "TEST2", 1)
+		require.Equal(t, expected, string(updated))
+	}
+	{
+		tmp, err := paths.WriteToTempFile([]byte{}, nil, "")
+		require.NoError(t, err)
+		require.NoError(t, tmp.Remove())
+		err = updateOrAddYamlRootEntry(tmp, "default_fqbn", "TEST1")
+		require.NoError(t, err)
+
+		updated, err := tmp.ReadFile()
+		require.NoError(t, err)
+		expected := "default_fqbn: TEST1\n"
+		require.Equal(t, expected, string(updated))
+	}
+}
diff --git a/cli/arguments/fqbn.go b/cli/arguments/fqbn.go
index 509a79bb396..8520994d2fb 100644
--- a/cli/arguments/fqbn.go
+++ b/cli/arguments/fqbn.go
@@ -65,21 +65,19 @@ func (f *Fqbn) Set(fqbn string) {
 // parameters provided by the user.
 // This determine the FQBN based on:
 // - the value of the FQBN flag if explicitly specified, otherwise
-// - the FQBN value in sketch.json if available, otherwise
+// - the default FQBN value in sketch.yaml (`default_fqbn` key) if available, otherwise
 // - it tries to autodetect the board connected to the given port flags
 // If all above methods fails, it returns the empty string.
 // The Port metadata are always returned except if:
-// - the port is not found, in this case nil is returned
-// - the FQBN autodetection fail, in this case the function prints an error and
-//   terminates the execution
+//   - the port is not found, in this case nil is returned
+//   - the FQBN autodetection fail, in this case the function prints an error and
+//     terminates the execution
 func CalculateFQBNAndPort(portArgs *Port, fqbnArg *Fqbn, instance *rpc.Instance, sk *sketch.Sketch) (string, *rpc.Port) {
 	// TODO: REMOVE sketch.Sketch from here
 
 	fqbn := fqbnArg.String()
-	if fqbn == "" && sk != nil && sk.Metadata != nil {
-		// If the user didn't specify an FQBN and a sketch.json file is present
-		// read it from there.
-		fqbn = sk.Metadata.CPU.Fqbn
+	if fqbn == "" && sk != nil {
+		fqbn = sk.GetDefaultFQBN()
 	}
 	if fqbn == "" {
 		if portArgs == nil || portArgs.address == "" {
diff --git a/cli/arguments/port.go b/cli/arguments/port.go
index 1f065fde2f2..54162f98eab 100644
--- a/cli/arguments/port.go
+++ b/cli/arguments/port.go
@@ -17,7 +17,6 @@ package arguments
 
 import (
 	"fmt"
-	"net/url"
 	"os"
 	"time"
 
@@ -29,7 +28,6 @@ import (
 	"github.com/arduino/arduino-cli/commands"
 	"github.com/arduino/arduino-cli/commands/board"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
-	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
@@ -57,11 +55,12 @@ func (p *Port) AddToCommand(cmd *cobra.Command) {
 }
 
 // GetPortAddressAndProtocol returns only the port address and the port protocol
-// without any other port metadata obtained from the discoveries. This method allows
-// to bypass the discoveries unless the protocol is not specified: in this
-// case the discoveries are needed to autodetect the protocol.
+// without any other port metadata obtained from the discoveries.
+// This method allows will bypass the discoveries if:
+// - a nil instance is passed: in this case the plain port and protocol arguments are returned (even if empty)
+// - a protocol is specified: in this case the discoveries are not needed to autodetect the protocol.
 func (p *Port) GetPortAddressAndProtocol(instance *rpc.Instance, sk *sketch.Sketch) (string, string, error) {
-	if p.protocol != "" {
+	if p.protocol != "" || instance == nil {
 		return p.address, p.protocol, nil
 	}
 	port, err := p.GetPort(instance, sk)
@@ -80,14 +79,8 @@ func (p *Port) GetPort(instance *rpc.Instance, sk *sketch.Sketch) (*discovery.Po
 	address := p.address
 	protocol := p.protocol
 
-	if address == "" && sk != nil && sk.Metadata != nil {
-		deviceURI, err := url.Parse(sk.Metadata.CPU.Port)
-		if err != nil {
-			return nil, errors.Errorf("invalid Device URL format: %s", err)
-		}
-		if deviceURI.Scheme == "serial" {
-			address = deviceURI.Host + deviceURI.Path
-		}
+	if address == "" && sk != nil {
+		address, protocol = sk.GetDefaultPortAddressAndProtocol()
 	}
 	if address == "" {
 		// If no address is provided we assume the user is trying to upload
diff --git a/cli/board/attach.go b/cli/board/attach.go
index cc715e52142..14751a7bcee 100644
--- a/cli/board/attach.go
+++ b/cli/board/attach.go
@@ -16,35 +16,32 @@
 package board
 
 import (
-	"context"
 	"fmt"
 	"os"
 
 	"github.com/arduino/arduino-cli/cli/arguments"
 	"github.com/arduino/arduino-cli/cli/errorcodes"
 	"github.com/arduino/arduino-cli/cli/feedback"
-	"github.com/arduino/arduino-cli/cli/instance"
-	"github.com/arduino/arduino-cli/cli/output"
-	"github.com/arduino/arduino-cli/commands/board"
-	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
-	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
 
-var (
-	port arguments.Port
-)
-
 func initAttachCommand() *cobra.Command {
+	var port arguments.Port
 	attachCommand := &cobra.Command{
-		Use:   fmt.Sprintf("attach -p <%s>|-b <%s> [%s]", tr("port"), tr("FQBN"), tr("sketchPath")),
+		Use:   fmt.Sprintf("attach [-p <%s>] [-b <%s>] [%s]", tr("port"), tr("FQBN"), tr("sketchPath")),
 		Short: tr("Attaches a sketch to a board."),
-		Long:  tr("Attaches a sketch to a board."),
+		Long:  tr("Sets the default values for port and FQBN. If no port or FQBN are specified, the current default port and FQBN are displayed."),
 		Example: "  " + os.Args[0] + " board attach -p /dev/ttyACM0\n" +
 			"  " + os.Args[0] + " board attach -p /dev/ttyACM0 HelloWorld\n" +
 			"  " + os.Args[0] + " board attach -b arduino:samd:mkr1000",
 		Args: cobra.MaximumNArgs(1),
-		Run:  runAttachCommand,
+		Run: func(cmd *cobra.Command, args []string) {
+			sketchPath := ""
+			if len(args) > 0 {
+				sketchPath = args[0]
+			}
+			runAttachCommand(sketchPath, &port, fqbn.String())
+		},
 	}
 	fqbn.AddToCommand(attachCommand)
 	port.AddToCommand(attachCommand)
@@ -52,33 +49,70 @@ func initAttachCommand() *cobra.Command {
 	return attachCommand
 }
 
-func runAttachCommand(cmd *cobra.Command, args []string) {
-	instance := instance.CreateAndInit()
-
-	logrus.Info("Executing `arduino-cli board attach`")
+func runAttachCommand(path string, port *arguments.Port, fqbn string) {
+	sketchPath := arguments.InitSketchPath(path)
+	sk := arguments.NewSketch(sketchPath)
 
-	path := ""
-	if len(args) > 0 {
-		path = args[0]
+	var currentPort *boardAttachPortResult
+	if currentAddress, currentProtocol := sk.GetDefaultPortAddressAndProtocol(); currentAddress != "" {
+		currentPort = &boardAttachPortResult{
+			Address:  currentAddress,
+			Protocol: currentProtocol,
+		}
 	}
-	sketchPath := arguments.InitSketchPath(path)
+	current := &boardAttachResult{
+		Port: currentPort,
+		Fqbn: sk.GetDefaultFQBN(),
+	}
+	address, protocol, _ := port.GetPortAddressAndProtocol(nil, sk)
+	if address != "" {
+		if err := sk.SetDefaultPort(address, protocol); err != nil {
+			feedback.Errorf("%s: %s", tr("Error saving sketch metadata"), err)
+			os.Exit(errorcodes.ErrGeneric)
+		}
+		current.Port = &boardAttachPortResult{
+			Address:  address,
+			Protocol: protocol,
+		}
+	}
+	if fqbn != "" {
+		if err := sk.SetDefaultFQBN(fqbn); err != nil {
+			feedback.Errorf("%s: %s", tr("Error saving sketch metadata"), err)
+			os.Exit(errorcodes.ErrGeneric)
+		}
+		current.Fqbn = fqbn
+	}
+
+	feedback.PrintResult(current)
+}
+
+type boardAttachPortResult struct {
+	Address  string `json:"address,omitempty"`
+	Protocol string `json:"protocol,omitempty"`
+}
 
-	// ugly hack to allow user to specify fqbn and port as flags (consistency)
-	// a more meaningful fix would be to fix board.Attach
-	var boardURI string
-	discoveryPort, _ := port.GetPort(instance, nil)
-	if fqbn.String() != "" {
-		boardURI = fqbn.String()
-	} else if discoveryPort != nil {
-		boardURI = discoveryPort.Address
+func (b *boardAttachPortResult) String() string {
+	port := b.Address
+	if b.Protocol != "" {
+		port += " (" + b.Protocol + ")"
 	}
-	if _, err := board.Attach(context.Background(), &rpc.BoardAttachRequest{
-		Instance:      instance,
-		BoardUri:      boardURI,
-		SketchPath:    sketchPath.String(),
-		SearchTimeout: port.GetSearchTimeout().String(),
-	}, output.TaskProgress()); err != nil {
-		feedback.Errorf(tr("Attach board error: %v"), err)
-		os.Exit(errorcodes.ErrGeneric)
+	return port
+}
+
+type boardAttachResult struct {
+	Fqbn string                 `json:"fqbn,omitempty"`
+	Port *boardAttachPortResult `json:"port,omitempty"`
+}
+
+func (b *boardAttachResult) Data() interface{} {
+	return b
+}
+
+func (b *boardAttachResult) String() string {
+	if b.Port == nil && b.Fqbn == "" {
+		return tr("No default port or FQBN set")
 	}
+	res := fmt.Sprintf("%s: %s\n", tr("Default port set to"), b.Port)
+	res += fmt.Sprintf("%s: %s\n", tr("Default FQBN set to"), b.Fqbn)
+	return res
 }
diff --git a/cli/board/board.go b/cli/board/board.go
index 8ed5531f150..762d502f645 100644
--- a/cli/board/board.go
+++ b/cli/board/board.go
@@ -31,9 +31,7 @@ func NewCommand() *cobra.Command {
 		Short: tr("Arduino board commands."),
 		Long:  tr("Arduino board commands."),
 		Example: "  # " + tr("Lists all connected boards.") + "\n" +
-			"  " + os.Args[0] + " board list\n\n" +
-			"  # " + tr("Attaches a sketch to a board.") + "\n" +
-			"  " + os.Args[0] + " board attach serial:///dev/ttyACM0 mySketch",
+			"  " + os.Args[0] + " board list",
 	}
 
 	boardCommand.AddCommand(initAttachCommand())
diff --git a/client_example/go.sum b/client_example/go.sum
index 79b5d874b7d..3a56561f90d 100644
--- a/client_example/go.sum
+++ b/client_example/go.sum
@@ -42,7 +42,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
 github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c/go.mod h1:HK7SpkEax/3P+0w78iRQx1sz1vCDYYw9RXwHjQTB5i8=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.7.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
@@ -64,7 +63,6 @@ github.com/cmaglie/pb v1.0.27/go.mod h1:GilkKZMXYjBA4NxItWFfO+lwkp59PLHQ+IOW/b/k
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/codeclysm/cc v1.2.2/go.mod h1:XtW4ArCNgQwFphcRGG9+sPX5WM1J6/u0gMy5ZdV3obA=
 github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -85,8 +83,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2/go.mod h1:c7sGIpDbBo0JZZ1tKyC1p5smWf8QcUjK4bFtZjHAecg=
-github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5/go.mod h1:BEUDl7FG1cc76sM0J0x8dqr6RhiL4uqvk6oFkwuNyuM=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -226,7 +222,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -240,7 +235,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228/go.mod h1:MGuVJ1+5TX1SCoO2Sx0eAnjpdRytYla2uC1YIZfkC9c=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@@ -295,7 +289,6 @@ go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
 go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII=
 go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
 go.bug.st/serial v1.3.2/go.mod h1:jDkjqASf/qSjmaOxHSHljwUQ6eHo/ZX/bxJLQqSlvZg=
-go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45/go.mod h1:dRSl/CVCTf56CkXgJMDOdSwNfo2g1orOGE/gBGdvjZw=
 go.bug.st/testifyjson v1.1.1/go.mod h1:nZyy2icFbv3OE3zW3mGVOnC/GhWgb93LRu+29n2tJlI=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
@@ -455,7 +448,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/client_example/main.go b/client_example/main.go
index 6d24d32ba55..f0fcceffa57 100644
--- a/client_example/main.go
+++ b/client_example/main.go
@@ -161,11 +161,6 @@ func main() {
 	log.Println("calling BoardSearch()")
 	callBoardSearch(client, instance)
 
-	// Attach a board to a sketch.
-	// Uncomment if you do have an actual board connected.
-	// log.Println("calling BoardAttach(serial:///dev/ttyACM0)")
-	// callBoardAttach(client, instance)
-
 	// Compile a sketch
 	log.Println("calling Compile(arduino:samd:mkr1000, VERBOSE, hello.ino)")
 	callCompile(client, instance)
@@ -555,41 +550,6 @@ func callBoardSearch(client rpc.ArduinoCoreServiceClient, instance *rpc.Instance
 	}
 }
 
-func callBoardAttach(client rpc.ArduinoCoreServiceClient, instance *rpc.Instance) {
-	currDir, _ := os.Getwd()
-	boardattachresp, err := client.BoardAttach(context.Background(),
-		&rpc.BoardAttachRequest{
-			Instance:   instance,
-			BoardUri:   "/dev/ttyACM0",
-			SketchPath: filepath.Join(currDir, "hello"),
-		})
-
-	if err != nil {
-		log.Fatalf("Attach error: %s", err)
-	}
-
-	// Loop and consume the server stream until all the operations are done.
-	for {
-		attachResp, err := boardattachresp.Recv()
-
-		// The server is done.
-		if err == io.EOF {
-			log.Print("Attach done")
-			break
-		}
-
-		// There was an error.
-		if err != nil {
-			log.Fatalf("Attach error: %s\n", err)
-		}
-
-		// When an overall task is ongoing, log the progress
-		if attachResp.GetTaskProgress() != nil {
-			log.Printf("TASK: %s", attachResp.GetTaskProgress())
-		}
-	}
-}
-
 func callCompile(client rpc.ArduinoCoreServiceClient, instance *rpc.Instance) {
 	currDir, _ := os.Getwd()
 	compRespStream, err := client.Compile(context.Background(),
diff --git a/commands/board/attach.go b/commands/board/attach.go
deleted file mode 100644
index 33ca154d1a2..00000000000
--- a/commands/board/attach.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// This file is part of arduino-cli.
-//
-// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-//
-// This software is released under the GNU General Public License version 3,
-// which covers the main part of arduino-cli.
-// The terms of this license can be found at:
-// https://www.gnu.org/licenses/gpl-3.0.en.html
-//
-// You can be released from the requirements of the above licenses by purchasing
-// a commercial license. Buying such a license is mandatory if you want to
-// modify or otherwise use the software for commercial activities involving the
-// Arduino software without disclosing the source code of your own applications.
-// To purchase a commercial license, send an email to license@arduino.cc.
-
-package board
-
-import (
-	"context"
-	"fmt"
-	"net/url"
-	"strings"
-	"time"
-
-	"github.com/arduino/arduino-cli/arduino"
-	"github.com/arduino/arduino-cli/arduino/cores"
-	"github.com/arduino/arduino-cli/arduino/cores/packagemanager"
-	"github.com/arduino/arduino-cli/arduino/sketch"
-	"github.com/arduino/arduino-cli/commands"
-	"github.com/arduino/arduino-cli/i18n"
-	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
-	discovery "github.com/arduino/board-discovery"
-	"github.com/arduino/go-paths-helper"
-)
-
-var tr = i18n.Tr
-
-// Attach FIXMEDOC
-func Attach(ctx context.Context, req *rpc.BoardAttachRequest, taskCB rpc.TaskProgressCB) (*rpc.BoardAttachResponse, error) {
-	pme, release := commands.GetPackageManagerExplorer(req)
-	if pme == nil {
-		return nil, &arduino.InvalidInstanceError{}
-	}
-	defer release()
-	var sketchPath *paths.Path
-	if req.GetSketchPath() != "" {
-		sketchPath = paths.New(req.GetSketchPath())
-	}
-	sk, err := sketch.New(sketchPath)
-	if err != nil {
-		return nil, &arduino.CantOpenSketchError{Cause: err}
-	}
-
-	boardURI := req.GetBoardUri()
-	fqbn, err := cores.ParseFQBN(boardURI)
-	if err != nil && !strings.HasPrefix(boardURI, "serial") {
-		boardURI = "serial://" + boardURI
-	}
-
-	if fqbn != nil {
-		sk.Metadata.CPU = sketch.BoardMetadata{
-			Fqbn: fqbn.String(),
-		}
-	} else {
-		deviceURI, err := url.Parse(boardURI)
-		if err != nil {
-			return nil, &arduino.InvalidArgumentError{Message: tr("Invalid Device URL format"), Cause: err}
-		}
-
-		var findBoardFunc func(*packagemanager.Explorer, *discovery.Monitor, *url.URL) *cores.Board
-		switch deviceURI.Scheme {
-		case "serial", "tty":
-			findBoardFunc = findSerialConnectedBoard
-		case "http", "https", "tcp", "udp":
-			findBoardFunc = findNetworkConnectedBoard
-		default:
-			return nil, &arduino.InvalidArgumentError{Message: tr("Invalid device port type provided")}
-		}
-
-		duration, err := time.ParseDuration(req.GetSearchTimeout())
-		if err != nil {
-			duration = time.Second * 5
-		}
-
-		monitor := discovery.New(time.Second)
-		monitor.Start()
-
-		time.Sleep(duration)
-
-		// TODO: Handle the case when no board is found.
-		board := findBoardFunc(pme, monitor, deviceURI)
-		if board == nil {
-			return nil, &arduino.InvalidArgumentError{Message: tr("No supported board found at %s", deviceURI)}
-		}
-		taskCB(&rpc.TaskProgress{Name: tr("Board found: %s", board.Name())})
-
-		// TODO: should be stoped the monitor: when running as a pure CLI  is released
-		// by the OS, when run as daemon the resource's state is unknown and could be leaked.
-		sk.Metadata.CPU = sketch.BoardMetadata{
-			Fqbn: board.FQBN(),
-			Name: board.Name(),
-			Port: deviceURI.String(),
-		}
-	}
-
-	err = sk.ExportMetadata()
-	if err != nil {
-		return nil, &arduino.PermissionDeniedError{Message: tr("Cannot export sketch metadata"), Cause: err}
-	}
-	taskCB(&rpc.TaskProgress{Name: tr("Selected fqbn: %s", sk.Metadata.CPU.Fqbn), Completed: true})
-	return &rpc.BoardAttachResponse{}, nil
-}
-
-// FIXME: Those should probably go in a "BoardManager" pkg or something
-// findSerialConnectedBoard find the board which is connected to the specified URI via serial port, using a monitor and a set of Boards
-// for the matching.
-func findSerialConnectedBoard(pme *packagemanager.Explorer, monitor *discovery.Monitor, deviceURI *url.URL) *cores.Board {
-	found := false
-	// to support both cases:
-	// serial:///dev/ttyACM2 parsing gives: deviceURI.Host = ""      and deviceURI.Path = /dev/ttyACM2
-	// serial://COM3 parsing gives:         deviceURI.Host = "COM3"  and deviceURI.Path = ""
-	location := deviceURI.Host + deviceURI.Path
-	var serialDevice discovery.SerialDevice
-	for _, device := range monitor.Serial() {
-		if device.Port == location {
-			// Found the device !
-			found = true
-			serialDevice = *device
-		}
-	}
-	if !found {
-		return nil
-	}
-
-	boards := pme.FindBoardsWithVidPid(serialDevice.VendorID, serialDevice.ProductID)
-	if len(boards) == 0 {
-		return nil
-	}
-
-	return boards[0]
-}
-
-// findNetworkConnectedBoard find the board which is connected to the specified URI on the network, using a monitor and a set of Boards
-// for the matching.
-func findNetworkConnectedBoard(pme *packagemanager.Explorer, monitor *discovery.Monitor, deviceURI *url.URL) *cores.Board {
-	found := false
-
-	var networkDevice discovery.NetworkDevice
-
-	for _, device := range monitor.Network() {
-		if device.Address == deviceURI.Host &&
-			fmt.Sprint(device.Port) == deviceURI.Port() {
-			// Found the device !
-			found = true
-			networkDevice = *device
-		}
-	}
-	if !found {
-		return nil
-	}
-
-	boards := pme.FindBoardsWithID(networkDevice.Name)
-	if len(boards) == 0 {
-		return nil
-	}
-
-	return boards[0]
-}
diff --git a/commands/board/board.go b/commands/board/board.go
new file mode 100644
index 00000000000..f4da2ff6ae4
--- /dev/null
+++ b/commands/board/board.go
@@ -0,0 +1,20 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package board
+
+import "github.com/arduino/arduino-cli/i18n"
+
+var tr = i18n.Tr
diff --git a/commands/compile/compile.go b/commands/compile/compile.go
index 75278662f52..be605746b93 100644
--- a/commands/compile/compile.go
+++ b/commands/compile/compile.go
@@ -76,8 +76,8 @@ func Compile(ctx context.Context, req *rpc.CompileRequest, outStream, errStream
 	}
 
 	fqbnIn := req.GetFqbn()
-	if fqbnIn == "" && sk != nil && sk.Metadata != nil {
-		fqbnIn = sk.Metadata.CPU.Fqbn
+	if fqbnIn == "" && sk != nil {
+		fqbnIn = sk.GetDefaultFQBN()
 	}
 	if fqbnIn == "" {
 		return nil, &arduino.MissingFQBNError{}
diff --git a/commands/daemon/daemon.go b/commands/daemon/daemon.go
index 8fbd9448e31..534fc29a2d3 100644
--- a/commands/daemon/daemon.go
+++ b/commands/daemon/daemon.go
@@ -140,17 +140,6 @@ func (s *ArduinoCoreServerImpl) BoardListWatch(stream rpc.ArduinoCoreService_Boa
 	return nil
 }
 
-// BoardAttach FIXMEDOC
-func (s *ArduinoCoreServerImpl) BoardAttach(req *rpc.BoardAttachRequest, stream rpc.ArduinoCoreService_BoardAttachServer) error {
-	resp, err := board.Attach(stream.Context(), req,
-		func(p *rpc.TaskProgress) { stream.Send(&rpc.BoardAttachResponse{TaskProgress: p}) },
-	)
-	if err != nil {
-		return convertErrorToRPCStatus(err)
-	}
-	return stream.Send(resp)
-}
-
 // Destroy FIXMEDOC
 func (s *ArduinoCoreServerImpl) Destroy(ctx context.Context, req *rpc.DestroyRequest) (*rpc.DestroyResponse, error) {
 	resp, err := commands.Destroy(ctx, req)
diff --git a/commands/debug/debug_info.go b/commands/debug/debug_info.go
index c09a6776636..4e3d931636f 100644
--- a/commands/debug/debug_info.go
+++ b/commands/debug/debug_info.go
@@ -54,8 +54,8 @@ func getDebugProperties(req *debug.DebugConfigRequest, pme *packagemanager.Explo
 
 	// XXX Remove this code duplication!!
 	fqbnIn := req.GetFqbn()
-	if fqbnIn == "" && sk != nil && sk.Metadata != nil {
-		fqbnIn = sk.Metadata.CPU.Fqbn
+	if fqbnIn == "" && sk != nil {
+		fqbnIn = sk.GetDefaultFQBN()
 	}
 	if fqbnIn == "" {
 		return nil, &arduino.MissingFQBNError{}
diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md
index 91e8e6940e2..cd8bb72d709 100644
--- a/docs/UPGRADING.md
+++ b/docs/UPGRADING.md
@@ -2,6 +2,20 @@
 
 Here you can find a list of migration guides to handle breaking changes between releases of the CLI.
 
+## 0.30.0
+
+### `board attach` CLI command changed behaviour
+
+The `board attach` CLI command has changed behaviour: now it just pick whatever port and FQBN is passed as parameter and
+saves it in the `sketch.yaml` file, without any validity check or board autodetection.
+
+The `sketch.json` file is now completely ignored.
+
+### `cc.arduino.cli.commands.v1.BoardAttach` gRPC interface command removal
+
+The `cc.arduino.cli.commands.v1.BoardAttach` gRPC command has been removed. This feature is no longer available through
+gRPC.
+
 ## 0.29.0
 
 ### Removed gRPC API: `cc.arduino.cli.commands.v1.UpdateCoreLibrariesIndex`, `Outdated`, and `Upgrade`
diff --git a/docs/sketch-project-file.md b/docs/sketch-project-file.md
index 9e8af0a8819..01a5607c8db 100644
--- a/docs/sketch-project-file.md
+++ b/docs/sketch-project-file.md
@@ -115,3 +115,24 @@ When using the profile-based build, the globally installed platforms and librari
 not be used in any way. In other words, the build is isolated from the system and will rely only on the resources
 specified in the profile: this will ensure that the build is portable and reproducible independently from the platforms
 and libraries installed in the system.
+
+## Default flags for Arduino CLI usage
+
+The sketch project file may be used to set the default value for some command line flags of the Arduino CLI, in
+particular:
+
+- The `default_fqbn` key sets the default value for the `--fqbn` flag
+- The `default_port` key sets the default value for the `--port` flag
+- The `default_protocol` key sets the default value for the `--protocol` flag
+
+For example:
+
+```
+default_fqbn: arduino:avr:uno
+default_port: /dev/ttyACM0
+default_protocol: serial
+```
+
+With this configuration set, it is not necessary to specify the `--fqbn`, `--port`, or `--protocol` flags to the
+[`arduino-cli compile`](commands/arduino-cli_compile.md) or [`arduino-cli upload`](commands/arduino-cli_upload.md)
+commands when compiling or uploading the sketch.
diff --git a/docs/sketch-specification.md b/docs/sketch-specification.md
index 5c7266eaf09..6dddad5d028 100644
--- a/docs/sketch-specification.md
+++ b/docs/sketch-specification.md
@@ -68,14 +68,11 @@ the `data` folder, so any non-code files outside the `data` folder are stripped.
 
 #### `sketch.json`
 
-Arduino CLI and Arduino Web Editor use a file named sketch.json, located in the sketch root folder, to store sketch
-metadata.
+Arduino Web Editor uses a file named `sketch.json`, located in the sketch root folder, to store sketch metadata. This
+file is not used by Arduino CLI or Arduino IDE, if you're not an Arduino Web Editor user you can safely ignore the file.
 
-The `cpu` key contains the board configuration information. This can be set via
-[`arduino-cli board attach`](commands/arduino-cli_board_attach.md) or by selecting a board in the Arduino Web Editor
-while the sketch is open. With this configuration set, it is not necessary to specify the `--fqbn` or `--port` flags to
-the [`arduino-cli compile`](commands/arduino-cli_compile.md) or [`arduino-cli upload`](commands/arduino-cli_upload.md)
-commands when compiling or uploading the sketch.
+The `cpu` key contains the board configuration information. This can be set by selecting a board in the Arduino Web
+Editor while the sketch is open.
 
 The `included_libs` key defines the library versions the Arduino Web Editor uses when the sketch is compiled. This is
 Arduino Web Editor specific because all versions of all the Library Manager libraries are pre-installed in Arduino Web
@@ -88,6 +85,9 @@ This is an optional file named `sketch.yaml`, located in the root folder of the
 Inside the sketch project file the user can define one or more "profiles": each profile is a description of all the
 resources needed to build the sketch (platform and libraries each pinned to a specific version).
 
+The sketch project file is also used in the [`arduino-cli board attach`](commands/arduino-cli_board_attach.md) command
+to store the currently selected board and port.
+
 For more information see the [sketch project file](sketch-project-file.md) documentation.
 
 ### Secrets
@@ -120,7 +120,7 @@ Foo
 |_ Ghi.h
 |_ Jkl.h
 |_ Jkl.S
-|_ sketch.json
+|_ sketch.yaml
 |_ data
 |  |_ Schematic.pdf
 |_ src
diff --git a/docsgen/go.mod b/docsgen/go.mod
index da770a84078..c30cbbe4f23 100644
--- a/docsgen/go.mod
+++ b/docsgen/go.mod
@@ -11,13 +11,11 @@ require (
 )
 
 require (
-	github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c // indirect
 	github.com/arduino/go-paths-helper v1.7.0 // indirect
 	github.com/arduino/go-properties-orderedmap v1.7.1 // indirect
 	github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b // indirect
 	github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b // indirect
 	github.com/cmaglie/pb v1.0.27 // indirect
-	github.com/codeclysm/cc v1.2.2 // indirect
 	github.com/codeclysm/extract/v3 v3.0.2 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
 	github.com/creack/goselect v0.1.2 // indirect
@@ -25,8 +23,6 @@ require (
 	github.com/djherbis/nio/v3 v3.0.1 // indirect
 	github.com/emirpasic/gods v1.12.0 // indirect
 	github.com/fatih/color v1.7.0 // indirect
-	github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2 // indirect
-	github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5 // indirect
 	github.com/fsnotify/fsnotify v1.4.9 // indirect
 	github.com/gofrs/uuid v3.2.0+incompatible // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
@@ -45,10 +41,8 @@ require (
 	github.com/mattn/go-colorable v0.1.8 // indirect
 	github.com/mattn/go-isatty v0.0.14 // indirect
 	github.com/mattn/go-runewidth v0.0.13 // indirect
-	github.com/miekg/dns v1.1.43 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/mapstructure v1.4.1 // indirect
-	github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228 // indirect
 	github.com/pelletier/go-toml v1.9.3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmylund/sortutil v0.0.0-20120526081524-abeda66eb583 // indirect
@@ -71,7 +65,6 @@ require (
 	go.bug.st/downloader/v2 v2.1.1 // indirect
 	go.bug.st/relaxed-semver v0.9.0 // indirect
 	go.bug.st/serial v1.3.2 // indirect
-	go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 // indirect
 	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
 	golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect
 	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
@@ -84,4 +77,5 @@ require (
 	gopkg.in/src-d/go-git.v4 v4.13.1 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/docsgen/go.sum b/docsgen/go.sum
index 417366b0cf6..7e2e1e0cdf7 100644
--- a/docsgen/go.sum
+++ b/docsgen/go.sum
@@ -44,8 +44,6 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/g
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c h1:agh2JT96G8egU7FEb13L4dq3fnCN7lxXhJ86t69+W7s=
-github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c/go.mod h1:HK7SpkEax/3P+0w78iRQx1sz1vCDYYw9RXwHjQTB5i8=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.7.0 h1:S9l5BP2aogz1CgyqqnncXt0PLpK4yvwOW/wu/LaR3tc=
@@ -73,8 +71,6 @@ github.com/cmaglie/pb v1.0.27/go.mod h1:GilkKZMXYjBA4NxItWFfO+lwkp59PLHQ+IOW/b/k
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/codeclysm/cc v1.2.2 h1:1ChS4EvWTjw6bH2sd6QiMcmih0itVVrWdh9MmOliX/I=
-github.com/codeclysm/cc v1.2.2/go.mod h1:XtW4ArCNgQwFphcRGG9+sPX5WM1J6/u0gMy5ZdV3obA=
 github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc=
 github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -103,10 +99,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2 h1:C6sOwknxwWfLBEQ91zhmptlfxf7pVEs5s6wOnDxNpS4=
-github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2/go.mod h1:c7sGIpDbBo0JZZ1tKyC1p5smWf8QcUjK4bFtZjHAecg=
-github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5 h1:R8jFW6G/bjoXjWPFrEfw9G5YQDlYhwV4AC+Eonu6wmk=
-github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5/go.mod h1:BEUDl7FG1cc76sM0J0x8dqr6RhiL4uqvk6oFkwuNyuM=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -269,8 +261,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
 github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
-github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@@ -287,8 +277,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228 h1:Cvfd2dOlXIPTeEkOT/h8PyK4phBngOM4at9/jlgy7d4=
-github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228/go.mod h1:MGuVJ1+5TX1SCoO2Sx0eAnjpdRytYla2uC1YIZfkC9c=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
 github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
@@ -370,8 +358,6 @@ go.bug.st/relaxed-semver v0.9.0 h1:qt0T8W70VCurvsbxRK25fQwiTOFjkzwC/fDOpyPnchQ=
 go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
 go.bug.st/serial v1.3.2 h1:6BFZZd/wngoL5PPYYTrFUounF54SIkykHpT98eq6zvk=
 go.bug.st/serial v1.3.2/go.mod h1:jDkjqASf/qSjmaOxHSHljwUQ6eHo/ZX/bxJLQqSlvZg=
-go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 h1:mACY1anK6HNCZtm/DK2Rf2ZPHggVqeB0+7rY9Gl6wyI=
-go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45/go.mod h1:dRSl/CVCTf56CkXgJMDOdSwNfo2g1orOGE/gBGdvjZw=
 go.bug.st/testifyjson v1.1.1/go.mod h1:nZyy2icFbv3OE3zW3mGVOnC/GhWgb93LRu+29n2tJlI=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
@@ -493,7 +479,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -533,7 +518,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/go.mod b/go.mod
index 6116f2e4fbd..c812dd60b11 100644
--- a/go.mod
+++ b/go.mod
@@ -6,19 +6,15 @@ go 1.17
 replace github.com/mailru/easyjson => github.com/cmaglie/easyjson v0.8.1
 
 require (
-	github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c
 	github.com/arduino/go-paths-helper v1.7.0
 	github.com/arduino/go-properties-orderedmap v1.7.1
 	github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b
 	github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b
 	github.com/cmaglie/pb v1.0.27
-	github.com/codeclysm/cc v1.2.2 // indirect
 	github.com/codeclysm/extract/v3 v3.0.2
 	github.com/djherbis/buffer v1.1.0
 	github.com/djherbis/nio/v3 v3.0.1
 	github.com/fatih/color v1.7.0
-	github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2 // indirect
-	github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5 // indirect
 	github.com/gofrs/uuid v3.2.0+incompatible
 	github.com/h2non/filetype v1.0.8 // indirect
 	github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
@@ -29,8 +25,6 @@ require (
 	github.com/mattn/go-colorable v0.1.8
 	github.com/mattn/go-isatty v0.0.14
 	github.com/mattn/go-runewidth v0.0.13 // indirect
-	github.com/miekg/dns v1.1.43 // indirect
-	github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228 // indirect
 	github.com/pkg/errors v0.9.1
 	github.com/pmylund/sortutil v0.0.0-20120526081524-abeda66eb583
 	github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
@@ -45,7 +39,6 @@ require (
 	go.bug.st/downloader/v2 v2.1.1
 	go.bug.st/relaxed-semver v0.9.0
 	go.bug.st/serial v1.3.2
-	go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 // indirect
 	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
 	golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect
 	golang.org/x/text v0.3.6
@@ -60,6 +53,7 @@ require (
 require (
 	github.com/rogpeppe/go-internal v1.3.0
 	go.bug.st/testifyjson v1.1.1
+	gopkg.in/yaml.v3 v3.0.1
 )
 
 require (
@@ -96,5 +90,4 @@ require (
 	gopkg.in/ini.v1 v1.62.0 // indirect
 	gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
-	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
diff --git a/go.sum b/go.sum
index aa7ee2bce12..62309295405 100644
--- a/go.sum
+++ b/go.sum
@@ -44,8 +44,6 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/g
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c h1:agh2JT96G8egU7FEb13L4dq3fnCN7lxXhJ86t69+W7s=
-github.com/arduino/board-discovery v0.0.0-20180823133458-1ba29327fb0c/go.mod h1:HK7SpkEax/3P+0w78iRQx1sz1vCDYYw9RXwHjQTB5i8=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.7.0 h1:S9l5BP2aogz1CgyqqnncXt0PLpK4yvwOW/wu/LaR3tc=
@@ -75,8 +73,6 @@ github.com/cmaglie/pb v1.0.27/go.mod h1:GilkKZMXYjBA4NxItWFfO+lwkp59PLHQ+IOW/b/k
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/codeclysm/cc v1.2.2 h1:1ChS4EvWTjw6bH2sd6QiMcmih0itVVrWdh9MmOliX/I=
-github.com/codeclysm/cc v1.2.2/go.mod h1:XtW4ArCNgQwFphcRGG9+sPX5WM1J6/u0gMy5ZdV3obA=
 github.com/codeclysm/extract/v3 v3.0.2 h1:sB4LcE3Php7LkhZwN0n2p8GCwZe92PEQutdbGURf5xc=
 github.com/codeclysm/extract/v3 v3.0.2/go.mod h1:NKsw+hqua9H+Rlwy/w/3Qgt9jDonYEgB6wJu+25eOKw=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -105,10 +101,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2 h1:C6sOwknxwWfLBEQ91zhmptlfxf7pVEs5s6wOnDxNpS4=
-github.com/fluxio/iohelpers v0.0.0-20160419043813-3a4dd67a94d2/go.mod h1:c7sGIpDbBo0JZZ1tKyC1p5smWf8QcUjK4bFtZjHAecg=
-github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5 h1:R8jFW6G/bjoXjWPFrEfw9G5YQDlYhwV4AC+Eonu6wmk=
-github.com/fluxio/multierror v0.0.0-20160419044231-9c68d39025e5/go.mod h1:BEUDl7FG1cc76sM0J0x8dqr6RhiL4uqvk6oFkwuNyuM=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -271,8 +263,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
 github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
-github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@@ -289,8 +279,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228 h1:Cvfd2dOlXIPTeEkOT/h8PyK4phBngOM4at9/jlgy7d4=
-github.com/oleksandr/bonjour v0.0.0-20160508152359-5dcf00d8b228/go.mod h1:MGuVJ1+5TX1SCoO2Sx0eAnjpdRytYla2uC1YIZfkC9c=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
 github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
@@ -373,8 +361,6 @@ go.bug.st/relaxed-semver v0.9.0 h1:qt0T8W70VCurvsbxRK25fQwiTOFjkzwC/fDOpyPnchQ=
 go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
 go.bug.st/serial v1.3.2 h1:6BFZZd/wngoL5PPYYTrFUounF54SIkykHpT98eq6zvk=
 go.bug.st/serial v1.3.2/go.mod h1:jDkjqASf/qSjmaOxHSHljwUQ6eHo/ZX/bxJLQqSlvZg=
-go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45 h1:mACY1anK6HNCZtm/DK2Rf2ZPHggVqeB0+7rY9Gl6wyI=
-go.bug.st/serial.v1 v0.0.0-20180827123349-5f7892a7bb45/go.mod h1:dRSl/CVCTf56CkXgJMDOdSwNfo2g1orOGE/gBGdvjZw=
 go.bug.st/testifyjson v1.1.1 h1:nHotIMK151LF3vYsU/b2RaoVaWCgrf2kvQeGNoZkGaA=
 go.bug.st/testifyjson v1.1.1/go.mod h1:nZyy2icFbv3OE3zW3mGVOnC/GhWgb93LRu+29n2tJlI=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
@@ -497,7 +483,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -537,7 +522,6 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/rpc/cc/arduino/cli/commands/v1/board.pb.go b/rpc/cc/arduino/cli/commands/v1/board.pb.go
index cba8bc07f75..cc131f0740e 100644
--- a/rpc/cc/arduino/cli/commands/v1/board.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/board.pb.go
@@ -842,131 +842,6 @@ func (x *ConfigValue) GetSelected() bool {
 	return false
 }
 
-type BoardAttachRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Arduino Core Service instance from the `Init` response.
-	Instance *Instance `protobuf:"bytes,1,opt,name=instance,proto3" json:"instance,omitempty"`
-	// The board's URI (e.g., /dev/ttyACM0).
-	BoardUri string `protobuf:"bytes,2,opt,name=board_uri,json=boardUri,proto3" json:"board_uri,omitempty"`
-	// Path of the sketch to attach the board to. The board attachment
-	// metadata will be saved to `{sketch_path}/sketch.json`.
-	SketchPath string `protobuf:"bytes,3,opt,name=sketch_path,json=sketchPath,proto3" json:"sketch_path,omitempty"`
-	// Duration in seconds to search the given URI for a connected board before
-	// timing out. The default value is 5 seconds.
-	SearchTimeout string `protobuf:"bytes,4,opt,name=search_timeout,json=searchTimeout,proto3" json:"search_timeout,omitempty"`
-}
-
-func (x *BoardAttachRequest) Reset() {
-	*x = BoardAttachRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[10]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *BoardAttachRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*BoardAttachRequest) ProtoMessage() {}
-
-func (x *BoardAttachRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[10]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use BoardAttachRequest.ProtoReflect.Descriptor instead.
-func (*BoardAttachRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{10}
-}
-
-func (x *BoardAttachRequest) GetInstance() *Instance {
-	if x != nil {
-		return x.Instance
-	}
-	return nil
-}
-
-func (x *BoardAttachRequest) GetBoardUri() string {
-	if x != nil {
-		return x.BoardUri
-	}
-	return ""
-}
-
-func (x *BoardAttachRequest) GetSketchPath() string {
-	if x != nil {
-		return x.SketchPath
-	}
-	return ""
-}
-
-func (x *BoardAttachRequest) GetSearchTimeout() string {
-	if x != nil {
-		return x.SearchTimeout
-	}
-	return ""
-}
-
-type BoardAttachResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Description of the current stage of the board attachment.
-	TaskProgress *TaskProgress `protobuf:"bytes,1,opt,name=task_progress,json=taskProgress,proto3" json:"task_progress,omitempty"`
-}
-
-func (x *BoardAttachResponse) Reset() {
-	*x = BoardAttachResponse{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[11]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *BoardAttachResponse) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*BoardAttachResponse) ProtoMessage() {}
-
-func (x *BoardAttachResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[11]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use BoardAttachResponse.ProtoReflect.Descriptor instead.
-func (*BoardAttachResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{11}
-}
-
-func (x *BoardAttachResponse) GetTaskProgress() *TaskProgress {
-	if x != nil {
-		return x.TaskProgress
-	}
-	return nil
-}
-
 type BoardListRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -981,7 +856,7 @@ type BoardListRequest struct {
 func (x *BoardListRequest) Reset() {
 	*x = BoardListRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[12]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[10]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -994,7 +869,7 @@ func (x *BoardListRequest) String() string {
 func (*BoardListRequest) ProtoMessage() {}
 
 func (x *BoardListRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[12]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[10]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1007,7 +882,7 @@ func (x *BoardListRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListRequest.ProtoReflect.Descriptor instead.
 func (*BoardListRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{12}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{10}
 }
 
 func (x *BoardListRequest) GetInstance() *Instance {
@@ -1036,7 +911,7 @@ type BoardListResponse struct {
 func (x *BoardListResponse) Reset() {
 	*x = BoardListResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[13]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[11]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1049,7 +924,7 @@ func (x *BoardListResponse) String() string {
 func (*BoardListResponse) ProtoMessage() {}
 
 func (x *BoardListResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[13]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[11]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1062,7 +937,7 @@ func (x *BoardListResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListResponse.ProtoReflect.Descriptor instead.
 func (*BoardListResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{13}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{11}
 }
 
 func (x *BoardListResponse) GetPorts() []*DetectedPort {
@@ -1086,7 +961,7 @@ type DetectedPort struct {
 func (x *DetectedPort) Reset() {
 	*x = DetectedPort{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[14]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[12]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1099,7 +974,7 @@ func (x *DetectedPort) String() string {
 func (*DetectedPort) ProtoMessage() {}
 
 func (x *DetectedPort) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[14]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[12]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1112,7 +987,7 @@ func (x *DetectedPort) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use DetectedPort.ProtoReflect.Descriptor instead.
 func (*DetectedPort) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{14}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *DetectedPort) GetMatchingBoards() []*BoardListItem {
@@ -1145,7 +1020,7 @@ type BoardListAllRequest struct {
 func (x *BoardListAllRequest) Reset() {
 	*x = BoardListAllRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[15]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[13]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1158,7 +1033,7 @@ func (x *BoardListAllRequest) String() string {
 func (*BoardListAllRequest) ProtoMessage() {}
 
 func (x *BoardListAllRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[15]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[13]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1171,7 +1046,7 @@ func (x *BoardListAllRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListAllRequest.ProtoReflect.Descriptor instead.
 func (*BoardListAllRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{15}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{13}
 }
 
 func (x *BoardListAllRequest) GetInstance() *Instance {
@@ -1207,7 +1082,7 @@ type BoardListAllResponse struct {
 func (x *BoardListAllResponse) Reset() {
 	*x = BoardListAllResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[16]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[14]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1220,7 +1095,7 @@ func (x *BoardListAllResponse) String() string {
 func (*BoardListAllResponse) ProtoMessage() {}
 
 func (x *BoardListAllResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[16]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[14]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1233,7 +1108,7 @@ func (x *BoardListAllResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListAllResponse.ProtoReflect.Descriptor instead.
 func (*BoardListAllResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{16}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{14}
 }
 
 func (x *BoardListAllResponse) GetBoards() []*BoardListItem {
@@ -1257,7 +1132,7 @@ type BoardListWatchRequest struct {
 func (x *BoardListWatchRequest) Reset() {
 	*x = BoardListWatchRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[17]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1270,7 +1145,7 @@ func (x *BoardListWatchRequest) String() string {
 func (*BoardListWatchRequest) ProtoMessage() {}
 
 func (x *BoardListWatchRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[17]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1283,7 +1158,7 @@ func (x *BoardListWatchRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListWatchRequest.ProtoReflect.Descriptor instead.
 func (*BoardListWatchRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{17}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{15}
 }
 
 func (x *BoardListWatchRequest) GetInstance() *Instance {
@@ -1316,7 +1191,7 @@ type BoardListWatchResponse struct {
 func (x *BoardListWatchResponse) Reset() {
 	*x = BoardListWatchResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[18]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[16]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1329,7 +1204,7 @@ func (x *BoardListWatchResponse) String() string {
 func (*BoardListWatchResponse) ProtoMessage() {}
 
 func (x *BoardListWatchResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[18]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[16]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1342,7 +1217,7 @@ func (x *BoardListWatchResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListWatchResponse.ProtoReflect.Descriptor instead.
 func (*BoardListWatchResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{18}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{16}
 }
 
 func (x *BoardListWatchResponse) GetEventType() string {
@@ -1384,7 +1259,7 @@ type BoardListItem struct {
 func (x *BoardListItem) Reset() {
 	*x = BoardListItem{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[19]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[17]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1397,7 +1272,7 @@ func (x *BoardListItem) String() string {
 func (*BoardListItem) ProtoMessage() {}
 
 func (x *BoardListItem) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[19]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[17]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1410,7 +1285,7 @@ func (x *BoardListItem) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardListItem.ProtoReflect.Descriptor instead.
 func (*BoardListItem) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{19}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{17}
 }
 
 func (x *BoardListItem) GetName() string {
@@ -1458,7 +1333,7 @@ type BoardSearchRequest struct {
 func (x *BoardSearchRequest) Reset() {
 	*x = BoardSearchRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[20]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[18]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1471,7 +1346,7 @@ func (x *BoardSearchRequest) String() string {
 func (*BoardSearchRequest) ProtoMessage() {}
 
 func (x *BoardSearchRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[20]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[18]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1484,7 +1359,7 @@ func (x *BoardSearchRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardSearchRequest.ProtoReflect.Descriptor instead.
 func (*BoardSearchRequest) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{20}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{18}
 }
 
 func (x *BoardSearchRequest) GetInstance() *Instance {
@@ -1520,7 +1395,7 @@ type BoardSearchResponse struct {
 func (x *BoardSearchResponse) Reset() {
 	*x = BoardSearchResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[21]
+		mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[19]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1533,7 +1408,7 @@ func (x *BoardSearchResponse) String() string {
 func (*BoardSearchResponse) ProtoMessage() {}
 
 func (x *BoardSearchResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[21]
+	mi := &file_cc_arduino_cli_commands_v1_board_proto_msgTypes[19]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1546,7 +1421,7 @@ func (x *BoardSearchResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BoardSearchResponse.ProtoReflect.Descriptor instead.
 func (*BoardSearchResponse) Descriptor() ([]byte, []int) {
-	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{21}
+	return file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP(), []int{19}
 }
 
 func (x *BoardSearchResponse) GetBoards() []*BoardListItem {
@@ -1695,112 +1570,93 @@ var file_cc_arduino_cli_commands_v1_board_proto_rawDesc = []byte{
 	0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02,
 	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x61, 0x62, 0x65, 0x6c,
 	0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x22, 0xbb, 0x01, 0x0a,
-	0x12, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73,
-	0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x75,
-	0x72, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55,
-	0x72, 0x69, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x74,
-	0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50,
-	0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x74, 0x69,
-	0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x64, 0x0a, 0x13, 0x42, 0x6f,
-	0x61, 0x72, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x4d, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65,
-	0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65,
-	0x73, 0x73, 0x52, 0x0c, 0x74, 0x61, 0x73, 0x6b, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73,
-	0x22, 0x6e, 0x0a, 0x10, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
+	0x28, 0x08, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x10,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e,
+	0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x53, 0x0a, 0x11,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x3e, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65,
+	0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x70, 0x6f, 0x72, 0x74,
+	0x73, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x6f,
+	0x72, 0x74, 0x12, 0x52, 0x0a, 0x0f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x62,
+	0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69,
+	0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0xac, 0x01, 0x0a,
+	0x13, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71,
 	0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
 	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
 	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
 	0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e,
-	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
-	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
-	0x22, 0x53, 0x0a, 0x11, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x05, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x01,
-	0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x05,
-	0x70, 0x6f, 0x72, 0x74, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74,
-	0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x52, 0x0a, 0x0f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69,
-	0x6e, 0x67, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61,
-	0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0e, 0x6d, 0x61, 0x74, 0x63,
-	0x68, 0x69, 0x6e, 0x67, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x04, 0x70, 0x6f,
-	0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74,
-	0x22, 0xac, 0x01, 0x0a, 0x13, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c,
-	0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74,
-	0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
-	0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65,
-	0x61, 0x72, 0x63, 0x68, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
-	0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x72, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x69,
-	0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5f, 0x62, 0x6f,
-	0x61, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c,
-	0x75, 0x64, 0x65, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x22,
-	0x59, 0x0a, 0x14, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x62, 0x6f, 0x61, 0x72, 0x64,
-	0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
+	0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61,
+	0x72, 0x63, 0x68, 0x41, 0x72, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x69, 0x6e, 0x63, 0x6c, 0x75,
+	0x64, 0x65, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x48,
+	0x69, 0x64, 0x64, 0x65, 0x6e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x22, 0x59, 0x0a, 0x14, 0x42,
+	0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20,
+	0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06,
+	0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x22, 0x77, 0x0a, 0x15, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c,
+	0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
+	0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49,
+	0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
+	0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, 0x70, 0x74, 0x22,
+	0x8b, 0x01, 0x0a, 0x16, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74,
+	0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76,
+	0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x70, 0x6f, 0x72,
+	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74,
-	0x65, 0x6d, 0x52, 0x06, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x22, 0x77, 0x0a, 0x15, 0x42, 0x6f,
-	0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73,
-	0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
-	0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72,
-	0x75, 0x70, 0x74, 0x22, 0x8b, 0x01, 0x0a, 0x16, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73,
-	0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d,
-	0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a,
-	0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x63,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x6f, 0x72,
+	0x74, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
+	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x96, 0x01,
+	0x0a, 0x0d, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12,
+	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+	0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x68, 0x69,
+	0x64, 0x64, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x48, 0x69,
+	0x64, 0x64, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+	0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c,
+	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xab, 0x01, 0x0a, 0x12, 0x42, 0x6f, 0x61, 0x72, 0x64,
+	0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a,
+	0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73,
+	0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12,
+	0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x41, 0x72, 0x67, 0x73,
+	0x12, 0x32, 0x0a, 0x15, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x68, 0x69, 0x64, 0x64,
+	0x65, 0x6e, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x42, 0x6f,
+	0x61, 0x72, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x13, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61,
+	0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x62,
+	0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x63,
 	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65,
-	0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65,
-	0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f,
-	0x72, 0x22, 0x96, 0x01, 0x0a, 0x0d, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49,
-	0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x71, 0x62, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69,
-	0x73, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
-	0x69, 0x73, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x12, 0x40, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
-	0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xab, 0x01, 0x0a, 0x12, 0x42,
-	0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x61, 0x72,
-	0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x41, 0x72, 0x67, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f,
-	0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x48, 0x69, 0x64, 0x64,
-	0x65, 0x6e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x22, 0x58, 0x0a, 0x13, 0x42, 0x6f, 0x61, 0x72,
-	0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x41, 0x0a, 0x06, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61,
-	0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x62, 0x6f, 0x61, 0x72,
-	0x64, 0x73, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69,
+	0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x06, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x73, 0x42, 0x48,
+	0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69,
+	0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f,
+	0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1815,7 +1671,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_rawDescGZIP() []byte {
 	return file_cc_arduino_cli_commands_v1_board_proto_rawDescData
 }
 
-var file_cc_arduino_cli_commands_v1_board_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
+var file_cc_arduino_cli_commands_v1_board_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
 var file_cc_arduino_cli_commands_v1_board_proto_goTypes = []interface{}{
 	(*BoardDetailsRequest)(nil),           // 0: cc.arduino.cli.commands.v1.BoardDetailsRequest
 	(*BoardDetailsResponse)(nil),          // 1: cc.arduino.cli.commands.v1.BoardDetailsResponse
@@ -1827,55 +1683,50 @@ var file_cc_arduino_cli_commands_v1_board_proto_goTypes = []interface{}{
 	(*Systems)(nil),                       // 7: cc.arduino.cli.commands.v1.Systems
 	(*ConfigOption)(nil),                  // 8: cc.arduino.cli.commands.v1.ConfigOption
 	(*ConfigValue)(nil),                   // 9: cc.arduino.cli.commands.v1.ConfigValue
-	(*BoardAttachRequest)(nil),            // 10: cc.arduino.cli.commands.v1.BoardAttachRequest
-	(*BoardAttachResponse)(nil),           // 11: cc.arduino.cli.commands.v1.BoardAttachResponse
-	(*BoardListRequest)(nil),              // 12: cc.arduino.cli.commands.v1.BoardListRequest
-	(*BoardListResponse)(nil),             // 13: cc.arduino.cli.commands.v1.BoardListResponse
-	(*DetectedPort)(nil),                  // 14: cc.arduino.cli.commands.v1.DetectedPort
-	(*BoardListAllRequest)(nil),           // 15: cc.arduino.cli.commands.v1.BoardListAllRequest
-	(*BoardListAllResponse)(nil),          // 16: cc.arduino.cli.commands.v1.BoardListAllResponse
-	(*BoardListWatchRequest)(nil),         // 17: cc.arduino.cli.commands.v1.BoardListWatchRequest
-	(*BoardListWatchResponse)(nil),        // 18: cc.arduino.cli.commands.v1.BoardListWatchResponse
-	(*BoardListItem)(nil),                 // 19: cc.arduino.cli.commands.v1.BoardListItem
-	(*BoardSearchRequest)(nil),            // 20: cc.arduino.cli.commands.v1.BoardSearchRequest
-	(*BoardSearchResponse)(nil),           // 21: cc.arduino.cli.commands.v1.BoardSearchResponse
-	nil,                                   // 22: cc.arduino.cli.commands.v1.BoardIdentificationProperties.PropertiesEntry
-	(*Instance)(nil),                      // 23: cc.arduino.cli.commands.v1.Instance
-	(*Programmer)(nil),                    // 24: cc.arduino.cli.commands.v1.Programmer
-	(*TaskProgress)(nil),                  // 25: cc.arduino.cli.commands.v1.TaskProgress
-	(*Port)(nil),                          // 26: cc.arduino.cli.commands.v1.Port
-	(*Platform)(nil),                      // 27: cc.arduino.cli.commands.v1.Platform
+	(*BoardListRequest)(nil),              // 10: cc.arduino.cli.commands.v1.BoardListRequest
+	(*BoardListResponse)(nil),             // 11: cc.arduino.cli.commands.v1.BoardListResponse
+	(*DetectedPort)(nil),                  // 12: cc.arduino.cli.commands.v1.DetectedPort
+	(*BoardListAllRequest)(nil),           // 13: cc.arduino.cli.commands.v1.BoardListAllRequest
+	(*BoardListAllResponse)(nil),          // 14: cc.arduino.cli.commands.v1.BoardListAllResponse
+	(*BoardListWatchRequest)(nil),         // 15: cc.arduino.cli.commands.v1.BoardListWatchRequest
+	(*BoardListWatchResponse)(nil),        // 16: cc.arduino.cli.commands.v1.BoardListWatchResponse
+	(*BoardListItem)(nil),                 // 17: cc.arduino.cli.commands.v1.BoardListItem
+	(*BoardSearchRequest)(nil),            // 18: cc.arduino.cli.commands.v1.BoardSearchRequest
+	(*BoardSearchResponse)(nil),           // 19: cc.arduino.cli.commands.v1.BoardSearchResponse
+	nil,                                   // 20: cc.arduino.cli.commands.v1.BoardIdentificationProperties.PropertiesEntry
+	(*Instance)(nil),                      // 21: cc.arduino.cli.commands.v1.Instance
+	(*Programmer)(nil),                    // 22: cc.arduino.cli.commands.v1.Programmer
+	(*Port)(nil),                          // 23: cc.arduino.cli.commands.v1.Port
+	(*Platform)(nil),                      // 24: cc.arduino.cli.commands.v1.Platform
 }
 var file_cc_arduino_cli_commands_v1_board_proto_depIdxs = []int32{
-	23, // 0: cc.arduino.cli.commands.v1.BoardDetailsRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	21, // 0: cc.arduino.cli.commands.v1.BoardDetailsRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
 	3,  // 1: cc.arduino.cli.commands.v1.BoardDetailsResponse.package:type_name -> cc.arduino.cli.commands.v1.Package
 	5,  // 2: cc.arduino.cli.commands.v1.BoardDetailsResponse.platform:type_name -> cc.arduino.cli.commands.v1.BoardPlatform
 	6,  // 3: cc.arduino.cli.commands.v1.BoardDetailsResponse.tools_dependencies:type_name -> cc.arduino.cli.commands.v1.ToolsDependencies
 	8,  // 4: cc.arduino.cli.commands.v1.BoardDetailsResponse.config_options:type_name -> cc.arduino.cli.commands.v1.ConfigOption
-	24, // 5: cc.arduino.cli.commands.v1.BoardDetailsResponse.programmers:type_name -> cc.arduino.cli.commands.v1.Programmer
+	22, // 5: cc.arduino.cli.commands.v1.BoardDetailsResponse.programmers:type_name -> cc.arduino.cli.commands.v1.Programmer
 	2,  // 6: cc.arduino.cli.commands.v1.BoardDetailsResponse.identification_properties:type_name -> cc.arduino.cli.commands.v1.BoardIdentificationProperties
-	22, // 7: cc.arduino.cli.commands.v1.BoardIdentificationProperties.properties:type_name -> cc.arduino.cli.commands.v1.BoardIdentificationProperties.PropertiesEntry
+	20, // 7: cc.arduino.cli.commands.v1.BoardIdentificationProperties.properties:type_name -> cc.arduino.cli.commands.v1.BoardIdentificationProperties.PropertiesEntry
 	4,  // 8: cc.arduino.cli.commands.v1.Package.help:type_name -> cc.arduino.cli.commands.v1.Help
 	7,  // 9: cc.arduino.cli.commands.v1.ToolsDependencies.systems:type_name -> cc.arduino.cli.commands.v1.Systems
 	9,  // 10: cc.arduino.cli.commands.v1.ConfigOption.values:type_name -> cc.arduino.cli.commands.v1.ConfigValue
-	23, // 11: cc.arduino.cli.commands.v1.BoardAttachRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	25, // 12: cc.arduino.cli.commands.v1.BoardAttachResponse.task_progress:type_name -> cc.arduino.cli.commands.v1.TaskProgress
-	23, // 13: cc.arduino.cli.commands.v1.BoardListRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	14, // 14: cc.arduino.cli.commands.v1.BoardListResponse.ports:type_name -> cc.arduino.cli.commands.v1.DetectedPort
-	19, // 15: cc.arduino.cli.commands.v1.DetectedPort.matching_boards:type_name -> cc.arduino.cli.commands.v1.BoardListItem
-	26, // 16: cc.arduino.cli.commands.v1.DetectedPort.port:type_name -> cc.arduino.cli.commands.v1.Port
-	23, // 17: cc.arduino.cli.commands.v1.BoardListAllRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	19, // 18: cc.arduino.cli.commands.v1.BoardListAllResponse.boards:type_name -> cc.arduino.cli.commands.v1.BoardListItem
-	23, // 19: cc.arduino.cli.commands.v1.BoardListWatchRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	14, // 20: cc.arduino.cli.commands.v1.BoardListWatchResponse.port:type_name -> cc.arduino.cli.commands.v1.DetectedPort
-	27, // 21: cc.arduino.cli.commands.v1.BoardListItem.platform:type_name -> cc.arduino.cli.commands.v1.Platform
-	23, // 22: cc.arduino.cli.commands.v1.BoardSearchRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
-	19, // 23: cc.arduino.cli.commands.v1.BoardSearchResponse.boards:type_name -> cc.arduino.cli.commands.v1.BoardListItem
-	24, // [24:24] is the sub-list for method output_type
-	24, // [24:24] is the sub-list for method input_type
-	24, // [24:24] is the sub-list for extension type_name
-	24, // [24:24] is the sub-list for extension extendee
-	0,  // [0:24] is the sub-list for field type_name
+	21, // 11: cc.arduino.cli.commands.v1.BoardListRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	12, // 12: cc.arduino.cli.commands.v1.BoardListResponse.ports:type_name -> cc.arduino.cli.commands.v1.DetectedPort
+	17, // 13: cc.arduino.cli.commands.v1.DetectedPort.matching_boards:type_name -> cc.arduino.cli.commands.v1.BoardListItem
+	23, // 14: cc.arduino.cli.commands.v1.DetectedPort.port:type_name -> cc.arduino.cli.commands.v1.Port
+	21, // 15: cc.arduino.cli.commands.v1.BoardListAllRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	17, // 16: cc.arduino.cli.commands.v1.BoardListAllResponse.boards:type_name -> cc.arduino.cli.commands.v1.BoardListItem
+	21, // 17: cc.arduino.cli.commands.v1.BoardListWatchRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	12, // 18: cc.arduino.cli.commands.v1.BoardListWatchResponse.port:type_name -> cc.arduino.cli.commands.v1.DetectedPort
+	24, // 19: cc.arduino.cli.commands.v1.BoardListItem.platform:type_name -> cc.arduino.cli.commands.v1.Platform
+	21, // 20: cc.arduino.cli.commands.v1.BoardSearchRequest.instance:type_name -> cc.arduino.cli.commands.v1.Instance
+	17, // 21: cc.arduino.cli.commands.v1.BoardSearchResponse.boards:type_name -> cc.arduino.cli.commands.v1.BoardListItem
+	22, // [22:22] is the sub-list for method output_type
+	22, // [22:22] is the sub-list for method input_type
+	22, // [22:22] is the sub-list for extension type_name
+	22, // [22:22] is the sub-list for extension extendee
+	0,  // [0:22] is the sub-list for field type_name
 }
 
 func init() { file_cc_arduino_cli_commands_v1_board_proto_init() }
@@ -2007,30 +1858,6 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 			}
 		}
 		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*BoardAttachRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*BoardAttachResponse); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListRequest); i {
 			case 0:
 				return &v.state
@@ -2042,7 +1869,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListResponse); i {
 			case 0:
 				return &v.state
@@ -2054,7 +1881,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*DetectedPort); i {
 			case 0:
 				return &v.state
@@ -2066,7 +1893,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListAllRequest); i {
 			case 0:
 				return &v.state
@@ -2078,7 +1905,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListAllResponse); i {
 			case 0:
 				return &v.state
@@ -2090,7 +1917,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListWatchRequest); i {
 			case 0:
 				return &v.state
@@ -2102,7 +1929,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListWatchResponse); i {
 			case 0:
 				return &v.state
@@ -2114,7 +1941,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardListItem); i {
 			case 0:
 				return &v.state
@@ -2126,7 +1953,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardSearchRequest); i {
 			case 0:
 				return &v.state
@@ -2138,7 +1965,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 				return nil
 			}
 		}
-		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+		file_cc_arduino_cli_commands_v1_board_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*BoardSearchResponse); i {
 			case 0:
 				return &v.state
@@ -2157,7 +1984,7 @@ func file_cc_arduino_cli_commands_v1_board_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_cc_arduino_cli_commands_v1_board_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   23,
+			NumMessages:   21,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/rpc/cc/arduino/cli/commands/v1/board.proto b/rpc/cc/arduino/cli/commands/v1/board.proto
index ec217beee06..5fdcb885333 100644
--- a/rpc/cc/arduino/cli/commands/v1/board.proto
+++ b/rpc/cc/arduino/cli/commands/v1/board.proto
@@ -147,24 +147,6 @@ message ConfigValue {
   bool selected = 3;
 }
 
-message BoardAttachRequest {
-  // Arduino Core Service instance from the `Init` response.
-  Instance instance = 1;
-  // The board's URI (e.g., /dev/ttyACM0).
-  string board_uri = 2;
-  // Path of the sketch to attach the board to. The board attachment
-  // metadata will be saved to `{sketch_path}/sketch.json`.
-  string sketch_path = 3;
-  // Duration in seconds to search the given URI for a connected board before
-  // timing out. The default value is 5 seconds.
-  string search_timeout = 4;
-}
-
-message BoardAttachResponse {
-  // Description of the current stage of the board attachment.
-  TaskProgress task_progress = 1;
-}
-
 message BoardListRequest {
   // Arduino Core Service instance from the `Init` response.
   Instance instance = 1;
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.pb.go b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
index 93a04ac6655..08d689d25d0 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
@@ -1229,7 +1229,7 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
 	0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x72, 0x22,
 	0x17, 0x0a, 0x15, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xbb, 0x25, 0x0a, 0x12, 0x41, 0x72, 0x64,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc9, 0x24, 0x0a, 0x12, 0x41, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
 	0x61, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61,
 	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
@@ -1300,241 +1300,234 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
 	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
 	0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64,
-	0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x09, 0x42, 0x6f, 0x61,
-	0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x09, 0x42, 0x6f, 0x61, 0x72, 0x64,
+	0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
 	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74,
-	0x41, 0x6c, 0x6c, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c,
+	0x6c, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
+	0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61,
+	0x72, 0x63, 0x68, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53,
-	0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c,
-	0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73,
+	0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74,
+	0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74,
+	0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30,
+	0x01, 0x12, 0x64, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+	0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
 	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57,
-	0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69,
-	0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28,
-	0x01, 0x30, 0x01, 0x12, 0x64, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2a,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
-	0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66,
+	0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61,
-	0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x32, 0x2e, 0x63,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
+	0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
+	0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44,
+	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
+	0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x74, 0x66,
+	0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
 	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
-	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66,
-	0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
-	0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
-	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x61,
-	0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34,
+	0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+	0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50,
+	0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x32,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
 	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74,
-	0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a,
-	0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65,
-	0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
-	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64,
-	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x06, 0x55,
-	0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
-	0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x8e,
-	0x01, 0x0a, 0x15, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72,
-	0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e,
-	0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72,
-	0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12,
-	0x86, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65,
-	0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73,
-	0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70,
-	0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73,
-	0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69,
-	0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44,
+	0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x06, 0x55, 0x70, 0x6c,
+	0x6f, 0x61, 0x64, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
-	0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c,
-	0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x45, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72,
-	0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c,
-	0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x0e, 0x42,
-	0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f,
+	0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x8e, 0x01, 0x0a,
+	0x15, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67,
+	0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50,
+	0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x39, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
+	0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+	0x6d, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01,
+	0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46,
+	0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72,
+	0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e,
 	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42,
-	0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75,
-	0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x77, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65,
-	0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f,
+	0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x50,
+	0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61,
+	0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72,
+	0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
+	0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x45, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41,
+	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61,
+	0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x0e, 0x42, 0x75, 0x72,
+	0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e, 0x63, 0x63,
 	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
-	0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x71, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12,
-	0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61,
-	0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
-	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77,
-	0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
-	0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f,
+	0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e,
+	0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x30, 0x01, 0x12, 0x77, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+	0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72,
+	0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61,
 	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f,
-	0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01,
-	0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x31, 0x2e,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53,
+	0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a,
+	0x0c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e,
 	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66,
+	0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
+	0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x7c, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
+	0x6f, 0x61, 0x64, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e,
+	0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79,
+	0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+	0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
 	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69,
+	0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69,
+	0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12,
+	0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73,
+	0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f,
+	0x0a, 0x10, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61,
+	0x6c, 0x6c, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11,
-	0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47,
-	0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49,
-	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01,
-	0x12, 0x7f, 0x0a, 0x10, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73,
-	0x74, 0x61, 0x6c, 0x6c, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e,
-	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30,
-	0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67,
-	0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72,
-	0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65,
-	0x6e, 0x63, 0x69, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e,
+	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12,
+	0x82, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61,
+	0x64, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
 	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76,
-	0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65,
-	0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53,
-	0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64,
+	0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x30, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+	0x69, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44,
+	0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65,
+	0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61,
+	0x72, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
 	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
 	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72,
-	0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69,
-	0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69,
-	0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f,
-	0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d,
-	0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01,
-	0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65,
-	0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69,
-	0x6e, 0x67, 0x73, 0x12, 0x3f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69,
+	0x74, 0x6f, 0x72, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
-	0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
-	0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
-	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e,
+	0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01,
+	0x12, 0xa1, 0x01, 0x0a, 0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f,
+	0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
+	0x73, 0x12, 0x3f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45,
+	0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50,
+	0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
+	0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
+	0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1576,65 +1569,63 @@ var file_cc_arduino_cli_commands_v1_commands_proto_goTypes = []interface{}{
 	(*DownloadProgress)(nil),                          // 22: cc.arduino.cli.commands.v1.DownloadProgress
 	(*TaskProgress)(nil),                              // 23: cc.arduino.cli.commands.v1.TaskProgress
 	(*BoardDetailsRequest)(nil),                       // 24: cc.arduino.cli.commands.v1.BoardDetailsRequest
-	(*BoardAttachRequest)(nil),                        // 25: cc.arduino.cli.commands.v1.BoardAttachRequest
-	(*BoardListRequest)(nil),                          // 26: cc.arduino.cli.commands.v1.BoardListRequest
-	(*BoardListAllRequest)(nil),                       // 27: cc.arduino.cli.commands.v1.BoardListAllRequest
-	(*BoardSearchRequest)(nil),                        // 28: cc.arduino.cli.commands.v1.BoardSearchRequest
-	(*BoardListWatchRequest)(nil),                     // 29: cc.arduino.cli.commands.v1.BoardListWatchRequest
-	(*CompileRequest)(nil),                            // 30: cc.arduino.cli.commands.v1.CompileRequest
-	(*PlatformInstallRequest)(nil),                    // 31: cc.arduino.cli.commands.v1.PlatformInstallRequest
-	(*PlatformDownloadRequest)(nil),                   // 32: cc.arduino.cli.commands.v1.PlatformDownloadRequest
-	(*PlatformUninstallRequest)(nil),                  // 33: cc.arduino.cli.commands.v1.PlatformUninstallRequest
-	(*PlatformUpgradeRequest)(nil),                    // 34: cc.arduino.cli.commands.v1.PlatformUpgradeRequest
-	(*UploadRequest)(nil),                             // 35: cc.arduino.cli.commands.v1.UploadRequest
-	(*UploadUsingProgrammerRequest)(nil),              // 36: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest
-	(*SupportedUserFieldsRequest)(nil),                // 37: cc.arduino.cli.commands.v1.SupportedUserFieldsRequest
-	(*ListProgrammersAvailableForUploadRequest)(nil),  // 38: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest
-	(*BurnBootloaderRequest)(nil),                     // 39: cc.arduino.cli.commands.v1.BurnBootloaderRequest
-	(*PlatformSearchRequest)(nil),                     // 40: cc.arduino.cli.commands.v1.PlatformSearchRequest
-	(*PlatformListRequest)(nil),                       // 41: cc.arduino.cli.commands.v1.PlatformListRequest
-	(*LibraryDownloadRequest)(nil),                    // 42: cc.arduino.cli.commands.v1.LibraryDownloadRequest
-	(*LibraryInstallRequest)(nil),                     // 43: cc.arduino.cli.commands.v1.LibraryInstallRequest
-	(*LibraryUpgradeRequest)(nil),                     // 44: cc.arduino.cli.commands.v1.LibraryUpgradeRequest
-	(*ZipLibraryInstallRequest)(nil),                  // 45: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
-	(*GitLibraryInstallRequest)(nil),                  // 46: cc.arduino.cli.commands.v1.GitLibraryInstallRequest
-	(*LibraryUninstallRequest)(nil),                   // 47: cc.arduino.cli.commands.v1.LibraryUninstallRequest
-	(*LibraryUpgradeAllRequest)(nil),                  // 48: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
-	(*LibraryResolveDependenciesRequest)(nil),         // 49: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
-	(*LibrarySearchRequest)(nil),                      // 50: cc.arduino.cli.commands.v1.LibrarySearchRequest
-	(*LibraryListRequest)(nil),                        // 51: cc.arduino.cli.commands.v1.LibraryListRequest
-	(*MonitorRequest)(nil),                            // 52: cc.arduino.cli.commands.v1.MonitorRequest
-	(*EnumerateMonitorPortSettingsRequest)(nil),       // 53: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
-	(*BoardDetailsResponse)(nil),                      // 54: cc.arduino.cli.commands.v1.BoardDetailsResponse
-	(*BoardAttachResponse)(nil),                       // 55: cc.arduino.cli.commands.v1.BoardAttachResponse
-	(*BoardListResponse)(nil),                         // 56: cc.arduino.cli.commands.v1.BoardListResponse
-	(*BoardListAllResponse)(nil),                      // 57: cc.arduino.cli.commands.v1.BoardListAllResponse
-	(*BoardSearchResponse)(nil),                       // 58: cc.arduino.cli.commands.v1.BoardSearchResponse
-	(*BoardListWatchResponse)(nil),                    // 59: cc.arduino.cli.commands.v1.BoardListWatchResponse
-	(*CompileResponse)(nil),                           // 60: cc.arduino.cli.commands.v1.CompileResponse
-	(*PlatformInstallResponse)(nil),                   // 61: cc.arduino.cli.commands.v1.PlatformInstallResponse
-	(*PlatformDownloadResponse)(nil),                  // 62: cc.arduino.cli.commands.v1.PlatformDownloadResponse
-	(*PlatformUninstallResponse)(nil),                 // 63: cc.arduino.cli.commands.v1.PlatformUninstallResponse
-	(*PlatformUpgradeResponse)(nil),                   // 64: cc.arduino.cli.commands.v1.PlatformUpgradeResponse
-	(*UploadResponse)(nil),                            // 65: cc.arduino.cli.commands.v1.UploadResponse
-	(*UploadUsingProgrammerResponse)(nil),             // 66: cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
-	(*SupportedUserFieldsResponse)(nil),               // 67: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
-	(*ListProgrammersAvailableForUploadResponse)(nil), // 68: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
-	(*BurnBootloaderResponse)(nil),                    // 69: cc.arduino.cli.commands.v1.BurnBootloaderResponse
-	(*PlatformSearchResponse)(nil),                    // 70: cc.arduino.cli.commands.v1.PlatformSearchResponse
-	(*PlatformListResponse)(nil),                      // 71: cc.arduino.cli.commands.v1.PlatformListResponse
-	(*LibraryDownloadResponse)(nil),                   // 72: cc.arduino.cli.commands.v1.LibraryDownloadResponse
-	(*LibraryInstallResponse)(nil),                    // 73: cc.arduino.cli.commands.v1.LibraryInstallResponse
-	(*LibraryUpgradeResponse)(nil),                    // 74: cc.arduino.cli.commands.v1.LibraryUpgradeResponse
-	(*ZipLibraryInstallResponse)(nil),                 // 75: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
-	(*GitLibraryInstallResponse)(nil),                 // 76: cc.arduino.cli.commands.v1.GitLibraryInstallResponse
-	(*LibraryUninstallResponse)(nil),                  // 77: cc.arduino.cli.commands.v1.LibraryUninstallResponse
-	(*LibraryUpgradeAllResponse)(nil),                 // 78: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
-	(*LibraryResolveDependenciesResponse)(nil),        // 79: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
-	(*LibrarySearchResponse)(nil),                     // 80: cc.arduino.cli.commands.v1.LibrarySearchResponse
-	(*LibraryListResponse)(nil),                       // 81: cc.arduino.cli.commands.v1.LibraryListResponse
-	(*MonitorResponse)(nil),                           // 82: cc.arduino.cli.commands.v1.MonitorResponse
-	(*EnumerateMonitorPortSettingsResponse)(nil),      // 83: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
+	(*BoardListRequest)(nil),                          // 25: cc.arduino.cli.commands.v1.BoardListRequest
+	(*BoardListAllRequest)(nil),                       // 26: cc.arduino.cli.commands.v1.BoardListAllRequest
+	(*BoardSearchRequest)(nil),                        // 27: cc.arduino.cli.commands.v1.BoardSearchRequest
+	(*BoardListWatchRequest)(nil),                     // 28: cc.arduino.cli.commands.v1.BoardListWatchRequest
+	(*CompileRequest)(nil),                            // 29: cc.arduino.cli.commands.v1.CompileRequest
+	(*PlatformInstallRequest)(nil),                    // 30: cc.arduino.cli.commands.v1.PlatformInstallRequest
+	(*PlatformDownloadRequest)(nil),                   // 31: cc.arduino.cli.commands.v1.PlatformDownloadRequest
+	(*PlatformUninstallRequest)(nil),                  // 32: cc.arduino.cli.commands.v1.PlatformUninstallRequest
+	(*PlatformUpgradeRequest)(nil),                    // 33: cc.arduino.cli.commands.v1.PlatformUpgradeRequest
+	(*UploadRequest)(nil),                             // 34: cc.arduino.cli.commands.v1.UploadRequest
+	(*UploadUsingProgrammerRequest)(nil),              // 35: cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest
+	(*SupportedUserFieldsRequest)(nil),                // 36: cc.arduino.cli.commands.v1.SupportedUserFieldsRequest
+	(*ListProgrammersAvailableForUploadRequest)(nil),  // 37: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest
+	(*BurnBootloaderRequest)(nil),                     // 38: cc.arduino.cli.commands.v1.BurnBootloaderRequest
+	(*PlatformSearchRequest)(nil),                     // 39: cc.arduino.cli.commands.v1.PlatformSearchRequest
+	(*PlatformListRequest)(nil),                       // 40: cc.arduino.cli.commands.v1.PlatformListRequest
+	(*LibraryDownloadRequest)(nil),                    // 41: cc.arduino.cli.commands.v1.LibraryDownloadRequest
+	(*LibraryInstallRequest)(nil),                     // 42: cc.arduino.cli.commands.v1.LibraryInstallRequest
+	(*LibraryUpgradeRequest)(nil),                     // 43: cc.arduino.cli.commands.v1.LibraryUpgradeRequest
+	(*ZipLibraryInstallRequest)(nil),                  // 44: cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
+	(*GitLibraryInstallRequest)(nil),                  // 45: cc.arduino.cli.commands.v1.GitLibraryInstallRequest
+	(*LibraryUninstallRequest)(nil),                   // 46: cc.arduino.cli.commands.v1.LibraryUninstallRequest
+	(*LibraryUpgradeAllRequest)(nil),                  // 47: cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
+	(*LibraryResolveDependenciesRequest)(nil),         // 48: cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
+	(*LibrarySearchRequest)(nil),                      // 49: cc.arduino.cli.commands.v1.LibrarySearchRequest
+	(*LibraryListRequest)(nil),                        // 50: cc.arduino.cli.commands.v1.LibraryListRequest
+	(*MonitorRequest)(nil),                            // 51: cc.arduino.cli.commands.v1.MonitorRequest
+	(*EnumerateMonitorPortSettingsRequest)(nil),       // 52: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
+	(*BoardDetailsResponse)(nil),                      // 53: cc.arduino.cli.commands.v1.BoardDetailsResponse
+	(*BoardListResponse)(nil),                         // 54: cc.arduino.cli.commands.v1.BoardListResponse
+	(*BoardListAllResponse)(nil),                      // 55: cc.arduino.cli.commands.v1.BoardListAllResponse
+	(*BoardSearchResponse)(nil),                       // 56: cc.arduino.cli.commands.v1.BoardSearchResponse
+	(*BoardListWatchResponse)(nil),                    // 57: cc.arduino.cli.commands.v1.BoardListWatchResponse
+	(*CompileResponse)(nil),                           // 58: cc.arduino.cli.commands.v1.CompileResponse
+	(*PlatformInstallResponse)(nil),                   // 59: cc.arduino.cli.commands.v1.PlatformInstallResponse
+	(*PlatformDownloadResponse)(nil),                  // 60: cc.arduino.cli.commands.v1.PlatformDownloadResponse
+	(*PlatformUninstallResponse)(nil),                 // 61: cc.arduino.cli.commands.v1.PlatformUninstallResponse
+	(*PlatformUpgradeResponse)(nil),                   // 62: cc.arduino.cli.commands.v1.PlatformUpgradeResponse
+	(*UploadResponse)(nil),                            // 63: cc.arduino.cli.commands.v1.UploadResponse
+	(*UploadUsingProgrammerResponse)(nil),             // 64: cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
+	(*SupportedUserFieldsResponse)(nil),               // 65: cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
+	(*ListProgrammersAvailableForUploadResponse)(nil), // 66: cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
+	(*BurnBootloaderResponse)(nil),                    // 67: cc.arduino.cli.commands.v1.BurnBootloaderResponse
+	(*PlatformSearchResponse)(nil),                    // 68: cc.arduino.cli.commands.v1.PlatformSearchResponse
+	(*PlatformListResponse)(nil),                      // 69: cc.arduino.cli.commands.v1.PlatformListResponse
+	(*LibraryDownloadResponse)(nil),                   // 70: cc.arduino.cli.commands.v1.LibraryDownloadResponse
+	(*LibraryInstallResponse)(nil),                    // 71: cc.arduino.cli.commands.v1.LibraryInstallResponse
+	(*LibraryUpgradeResponse)(nil),                    // 72: cc.arduino.cli.commands.v1.LibraryUpgradeResponse
+	(*ZipLibraryInstallResponse)(nil),                 // 73: cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
+	(*GitLibraryInstallResponse)(nil),                 // 74: cc.arduino.cli.commands.v1.GitLibraryInstallResponse
+	(*LibraryUninstallResponse)(nil),                  // 75: cc.arduino.cli.commands.v1.LibraryUninstallResponse
+	(*LibraryUpgradeAllResponse)(nil),                 // 76: cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
+	(*LibraryResolveDependenciesResponse)(nil),        // 77: cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
+	(*LibrarySearchResponse)(nil),                     // 78: cc.arduino.cli.commands.v1.LibrarySearchResponse
+	(*LibraryListResponse)(nil),                       // 79: cc.arduino.cli.commands.v1.LibraryListResponse
+	(*MonitorResponse)(nil),                           // 80: cc.arduino.cli.commands.v1.MonitorResponse
+	(*EnumerateMonitorPortSettingsResponse)(nil),      // 81: cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
 }
 var file_cc_arduino_cli_commands_v1_commands_proto_depIdxs = []int32{
 	19, // 0: cc.arduino.cli.commands.v1.CreateResponse.instance:type_name -> cc.arduino.cli.commands.v1.Instance
@@ -1661,76 +1652,74 @@ var file_cc_arduino_cli_commands_v1_commands_proto_depIdxs = []int32{
 	14, // 21: cc.arduino.cli.commands.v1.ArduinoCoreService.LoadSketch:input_type -> cc.arduino.cli.commands.v1.LoadSketchRequest
 	16, // 22: cc.arduino.cli.commands.v1.ArduinoCoreService.ArchiveSketch:input_type -> cc.arduino.cli.commands.v1.ArchiveSketchRequest
 	24, // 23: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardDetails:input_type -> cc.arduino.cli.commands.v1.BoardDetailsRequest
-	25, // 24: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardAttach:input_type -> cc.arduino.cli.commands.v1.BoardAttachRequest
-	26, // 25: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardList:input_type -> cc.arduino.cli.commands.v1.BoardListRequest
-	27, // 26: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListAll:input_type -> cc.arduino.cli.commands.v1.BoardListAllRequest
-	28, // 27: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardSearch:input_type -> cc.arduino.cli.commands.v1.BoardSearchRequest
-	29, // 28: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListWatch:input_type -> cc.arduino.cli.commands.v1.BoardListWatchRequest
-	30, // 29: cc.arduino.cli.commands.v1.ArduinoCoreService.Compile:input_type -> cc.arduino.cli.commands.v1.CompileRequest
-	31, // 30: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformInstall:input_type -> cc.arduino.cli.commands.v1.PlatformInstallRequest
-	32, // 31: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformDownload:input_type -> cc.arduino.cli.commands.v1.PlatformDownloadRequest
-	33, // 32: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUninstall:input_type -> cc.arduino.cli.commands.v1.PlatformUninstallRequest
-	34, // 33: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUpgrade:input_type -> cc.arduino.cli.commands.v1.PlatformUpgradeRequest
-	35, // 34: cc.arduino.cli.commands.v1.ArduinoCoreService.Upload:input_type -> cc.arduino.cli.commands.v1.UploadRequest
-	36, // 35: cc.arduino.cli.commands.v1.ArduinoCoreService.UploadUsingProgrammer:input_type -> cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest
-	37, // 36: cc.arduino.cli.commands.v1.ArduinoCoreService.SupportedUserFields:input_type -> cc.arduino.cli.commands.v1.SupportedUserFieldsRequest
-	38, // 37: cc.arduino.cli.commands.v1.ArduinoCoreService.ListProgrammersAvailableForUpload:input_type -> cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest
-	39, // 38: cc.arduino.cli.commands.v1.ArduinoCoreService.BurnBootloader:input_type -> cc.arduino.cli.commands.v1.BurnBootloaderRequest
-	40, // 39: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformSearch:input_type -> cc.arduino.cli.commands.v1.PlatformSearchRequest
-	41, // 40: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:input_type -> cc.arduino.cli.commands.v1.PlatformListRequest
-	42, // 41: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:input_type -> cc.arduino.cli.commands.v1.LibraryDownloadRequest
-	43, // 42: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:input_type -> cc.arduino.cli.commands.v1.LibraryInstallRequest
-	44, // 43: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgrade:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeRequest
-	45, // 44: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:input_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
-	46, // 45: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:input_type -> cc.arduino.cli.commands.v1.GitLibraryInstallRequest
-	47, // 46: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:input_type -> cc.arduino.cli.commands.v1.LibraryUninstallRequest
-	48, // 47: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
-	49, // 48: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:input_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
-	50, // 49: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:input_type -> cc.arduino.cli.commands.v1.LibrarySearchRequest
-	51, // 50: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:input_type -> cc.arduino.cli.commands.v1.LibraryListRequest
-	52, // 51: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:input_type -> cc.arduino.cli.commands.v1.MonitorRequest
-	53, // 52: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:input_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
-	1,  // 53: cc.arduino.cli.commands.v1.ArduinoCoreService.Create:output_type -> cc.arduino.cli.commands.v1.CreateResponse
-	3,  // 54: cc.arduino.cli.commands.v1.ArduinoCoreService.Init:output_type -> cc.arduino.cli.commands.v1.InitResponse
-	5,  // 55: cc.arduino.cli.commands.v1.ArduinoCoreService.Destroy:output_type -> cc.arduino.cli.commands.v1.DestroyResponse
-	7,  // 56: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateIndex:output_type -> cc.arduino.cli.commands.v1.UpdateIndexResponse
-	9,  // 57: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateLibrariesIndex:output_type -> cc.arduino.cli.commands.v1.UpdateLibrariesIndexResponse
-	11, // 58: cc.arduino.cli.commands.v1.ArduinoCoreService.Version:output_type -> cc.arduino.cli.commands.v1.VersionResponse
-	13, // 59: cc.arduino.cli.commands.v1.ArduinoCoreService.NewSketch:output_type -> cc.arduino.cli.commands.v1.NewSketchResponse
-	15, // 60: cc.arduino.cli.commands.v1.ArduinoCoreService.LoadSketch:output_type -> cc.arduino.cli.commands.v1.LoadSketchResponse
-	17, // 61: cc.arduino.cli.commands.v1.ArduinoCoreService.ArchiveSketch:output_type -> cc.arduino.cli.commands.v1.ArchiveSketchResponse
-	54, // 62: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardDetails:output_type -> cc.arduino.cli.commands.v1.BoardDetailsResponse
-	55, // 63: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardAttach:output_type -> cc.arduino.cli.commands.v1.BoardAttachResponse
-	56, // 64: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardList:output_type -> cc.arduino.cli.commands.v1.BoardListResponse
-	57, // 65: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListAll:output_type -> cc.arduino.cli.commands.v1.BoardListAllResponse
-	58, // 66: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardSearch:output_type -> cc.arduino.cli.commands.v1.BoardSearchResponse
-	59, // 67: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListWatch:output_type -> cc.arduino.cli.commands.v1.BoardListWatchResponse
-	60, // 68: cc.arduino.cli.commands.v1.ArduinoCoreService.Compile:output_type -> cc.arduino.cli.commands.v1.CompileResponse
-	61, // 69: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformInstall:output_type -> cc.arduino.cli.commands.v1.PlatformInstallResponse
-	62, // 70: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformDownload:output_type -> cc.arduino.cli.commands.v1.PlatformDownloadResponse
-	63, // 71: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUninstall:output_type -> cc.arduino.cli.commands.v1.PlatformUninstallResponse
-	64, // 72: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUpgrade:output_type -> cc.arduino.cli.commands.v1.PlatformUpgradeResponse
-	65, // 73: cc.arduino.cli.commands.v1.ArduinoCoreService.Upload:output_type -> cc.arduino.cli.commands.v1.UploadResponse
-	66, // 74: cc.arduino.cli.commands.v1.ArduinoCoreService.UploadUsingProgrammer:output_type -> cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
-	67, // 75: cc.arduino.cli.commands.v1.ArduinoCoreService.SupportedUserFields:output_type -> cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
-	68, // 76: cc.arduino.cli.commands.v1.ArduinoCoreService.ListProgrammersAvailableForUpload:output_type -> cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
-	69, // 77: cc.arduino.cli.commands.v1.ArduinoCoreService.BurnBootloader:output_type -> cc.arduino.cli.commands.v1.BurnBootloaderResponse
-	70, // 78: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformSearch:output_type -> cc.arduino.cli.commands.v1.PlatformSearchResponse
-	71, // 79: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:output_type -> cc.arduino.cli.commands.v1.PlatformListResponse
-	72, // 80: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:output_type -> cc.arduino.cli.commands.v1.LibraryDownloadResponse
-	73, // 81: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:output_type -> cc.arduino.cli.commands.v1.LibraryInstallResponse
-	74, // 82: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgrade:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeResponse
-	75, // 83: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:output_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
-	76, // 84: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:output_type -> cc.arduino.cli.commands.v1.GitLibraryInstallResponse
-	77, // 85: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:output_type -> cc.arduino.cli.commands.v1.LibraryUninstallResponse
-	78, // 86: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
-	79, // 87: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:output_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
-	80, // 88: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:output_type -> cc.arduino.cli.commands.v1.LibrarySearchResponse
-	81, // 89: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:output_type -> cc.arduino.cli.commands.v1.LibraryListResponse
-	82, // 90: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:output_type -> cc.arduino.cli.commands.v1.MonitorResponse
-	83, // 91: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:output_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
-	53, // [53:92] is the sub-list for method output_type
-	14, // [14:53] is the sub-list for method input_type
+	25, // 24: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardList:input_type -> cc.arduino.cli.commands.v1.BoardListRequest
+	26, // 25: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListAll:input_type -> cc.arduino.cli.commands.v1.BoardListAllRequest
+	27, // 26: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardSearch:input_type -> cc.arduino.cli.commands.v1.BoardSearchRequest
+	28, // 27: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListWatch:input_type -> cc.arduino.cli.commands.v1.BoardListWatchRequest
+	29, // 28: cc.arduino.cli.commands.v1.ArduinoCoreService.Compile:input_type -> cc.arduino.cli.commands.v1.CompileRequest
+	30, // 29: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformInstall:input_type -> cc.arduino.cli.commands.v1.PlatformInstallRequest
+	31, // 30: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformDownload:input_type -> cc.arduino.cli.commands.v1.PlatformDownloadRequest
+	32, // 31: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUninstall:input_type -> cc.arduino.cli.commands.v1.PlatformUninstallRequest
+	33, // 32: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUpgrade:input_type -> cc.arduino.cli.commands.v1.PlatformUpgradeRequest
+	34, // 33: cc.arduino.cli.commands.v1.ArduinoCoreService.Upload:input_type -> cc.arduino.cli.commands.v1.UploadRequest
+	35, // 34: cc.arduino.cli.commands.v1.ArduinoCoreService.UploadUsingProgrammer:input_type -> cc.arduino.cli.commands.v1.UploadUsingProgrammerRequest
+	36, // 35: cc.arduino.cli.commands.v1.ArduinoCoreService.SupportedUserFields:input_type -> cc.arduino.cli.commands.v1.SupportedUserFieldsRequest
+	37, // 36: cc.arduino.cli.commands.v1.ArduinoCoreService.ListProgrammersAvailableForUpload:input_type -> cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadRequest
+	38, // 37: cc.arduino.cli.commands.v1.ArduinoCoreService.BurnBootloader:input_type -> cc.arduino.cli.commands.v1.BurnBootloaderRequest
+	39, // 38: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformSearch:input_type -> cc.arduino.cli.commands.v1.PlatformSearchRequest
+	40, // 39: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:input_type -> cc.arduino.cli.commands.v1.PlatformListRequest
+	41, // 40: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:input_type -> cc.arduino.cli.commands.v1.LibraryDownloadRequest
+	42, // 41: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:input_type -> cc.arduino.cli.commands.v1.LibraryInstallRequest
+	43, // 42: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgrade:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeRequest
+	44, // 43: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:input_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallRequest
+	45, // 44: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:input_type -> cc.arduino.cli.commands.v1.GitLibraryInstallRequest
+	46, // 45: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:input_type -> cc.arduino.cli.commands.v1.LibraryUninstallRequest
+	47, // 46: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:input_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllRequest
+	48, // 47: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:input_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesRequest
+	49, // 48: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:input_type -> cc.arduino.cli.commands.v1.LibrarySearchRequest
+	50, // 49: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:input_type -> cc.arduino.cli.commands.v1.LibraryListRequest
+	51, // 50: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:input_type -> cc.arduino.cli.commands.v1.MonitorRequest
+	52, // 51: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:input_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsRequest
+	1,  // 52: cc.arduino.cli.commands.v1.ArduinoCoreService.Create:output_type -> cc.arduino.cli.commands.v1.CreateResponse
+	3,  // 53: cc.arduino.cli.commands.v1.ArduinoCoreService.Init:output_type -> cc.arduino.cli.commands.v1.InitResponse
+	5,  // 54: cc.arduino.cli.commands.v1.ArduinoCoreService.Destroy:output_type -> cc.arduino.cli.commands.v1.DestroyResponse
+	7,  // 55: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateIndex:output_type -> cc.arduino.cli.commands.v1.UpdateIndexResponse
+	9,  // 56: cc.arduino.cli.commands.v1.ArduinoCoreService.UpdateLibrariesIndex:output_type -> cc.arduino.cli.commands.v1.UpdateLibrariesIndexResponse
+	11, // 57: cc.arduino.cli.commands.v1.ArduinoCoreService.Version:output_type -> cc.arduino.cli.commands.v1.VersionResponse
+	13, // 58: cc.arduino.cli.commands.v1.ArduinoCoreService.NewSketch:output_type -> cc.arduino.cli.commands.v1.NewSketchResponse
+	15, // 59: cc.arduino.cli.commands.v1.ArduinoCoreService.LoadSketch:output_type -> cc.arduino.cli.commands.v1.LoadSketchResponse
+	17, // 60: cc.arduino.cli.commands.v1.ArduinoCoreService.ArchiveSketch:output_type -> cc.arduino.cli.commands.v1.ArchiveSketchResponse
+	53, // 61: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardDetails:output_type -> cc.arduino.cli.commands.v1.BoardDetailsResponse
+	54, // 62: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardList:output_type -> cc.arduino.cli.commands.v1.BoardListResponse
+	55, // 63: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListAll:output_type -> cc.arduino.cli.commands.v1.BoardListAllResponse
+	56, // 64: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardSearch:output_type -> cc.arduino.cli.commands.v1.BoardSearchResponse
+	57, // 65: cc.arduino.cli.commands.v1.ArduinoCoreService.BoardListWatch:output_type -> cc.arduino.cli.commands.v1.BoardListWatchResponse
+	58, // 66: cc.arduino.cli.commands.v1.ArduinoCoreService.Compile:output_type -> cc.arduino.cli.commands.v1.CompileResponse
+	59, // 67: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformInstall:output_type -> cc.arduino.cli.commands.v1.PlatformInstallResponse
+	60, // 68: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformDownload:output_type -> cc.arduino.cli.commands.v1.PlatformDownloadResponse
+	61, // 69: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUninstall:output_type -> cc.arduino.cli.commands.v1.PlatformUninstallResponse
+	62, // 70: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformUpgrade:output_type -> cc.arduino.cli.commands.v1.PlatformUpgradeResponse
+	63, // 71: cc.arduino.cli.commands.v1.ArduinoCoreService.Upload:output_type -> cc.arduino.cli.commands.v1.UploadResponse
+	64, // 72: cc.arduino.cli.commands.v1.ArduinoCoreService.UploadUsingProgrammer:output_type -> cc.arduino.cli.commands.v1.UploadUsingProgrammerResponse
+	65, // 73: cc.arduino.cli.commands.v1.ArduinoCoreService.SupportedUserFields:output_type -> cc.arduino.cli.commands.v1.SupportedUserFieldsResponse
+	66, // 74: cc.arduino.cli.commands.v1.ArduinoCoreService.ListProgrammersAvailableForUpload:output_type -> cc.arduino.cli.commands.v1.ListProgrammersAvailableForUploadResponse
+	67, // 75: cc.arduino.cli.commands.v1.ArduinoCoreService.BurnBootloader:output_type -> cc.arduino.cli.commands.v1.BurnBootloaderResponse
+	68, // 76: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformSearch:output_type -> cc.arduino.cli.commands.v1.PlatformSearchResponse
+	69, // 77: cc.arduino.cli.commands.v1.ArduinoCoreService.PlatformList:output_type -> cc.arduino.cli.commands.v1.PlatformListResponse
+	70, // 78: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryDownload:output_type -> cc.arduino.cli.commands.v1.LibraryDownloadResponse
+	71, // 79: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryInstall:output_type -> cc.arduino.cli.commands.v1.LibraryInstallResponse
+	72, // 80: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgrade:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeResponse
+	73, // 81: cc.arduino.cli.commands.v1.ArduinoCoreService.ZipLibraryInstall:output_type -> cc.arduino.cli.commands.v1.ZipLibraryInstallResponse
+	74, // 82: cc.arduino.cli.commands.v1.ArduinoCoreService.GitLibraryInstall:output_type -> cc.arduino.cli.commands.v1.GitLibraryInstallResponse
+	75, // 83: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUninstall:output_type -> cc.arduino.cli.commands.v1.LibraryUninstallResponse
+	76, // 84: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryUpgradeAll:output_type -> cc.arduino.cli.commands.v1.LibraryUpgradeAllResponse
+	77, // 85: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryResolveDependencies:output_type -> cc.arduino.cli.commands.v1.LibraryResolveDependenciesResponse
+	78, // 86: cc.arduino.cli.commands.v1.ArduinoCoreService.LibrarySearch:output_type -> cc.arduino.cli.commands.v1.LibrarySearchResponse
+	79, // 87: cc.arduino.cli.commands.v1.ArduinoCoreService.LibraryList:output_type -> cc.arduino.cli.commands.v1.LibraryListResponse
+	80, // 88: cc.arduino.cli.commands.v1.ArduinoCoreService.Monitor:output_type -> cc.arduino.cli.commands.v1.MonitorResponse
+	81, // 89: cc.arduino.cli.commands.v1.ArduinoCoreService.EnumerateMonitorPortSettings:output_type -> cc.arduino.cli.commands.v1.EnumerateMonitorPortSettingsResponse
+	52, // [52:90] is the sub-list for method output_type
+	14, // [14:52] is the sub-list for method input_type
 	14, // [14:14] is the sub-list for extension type_name
 	14, // [14:14] is the sub-list for extension extendee
 	0,  // [0:14] is the sub-list for field type_name
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.proto b/rpc/cc/arduino/cli/commands/v1/commands.proto
index 4874d84f2d0..699cfb6807e 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.proto
+++ b/rpc/cc/arduino/cli/commands/v1/commands.proto
@@ -69,10 +69,6 @@ service ArduinoCoreService {
   // Requests details about a board
   rpc BoardDetails(BoardDetailsRequest) returns (BoardDetailsResponse);
 
-  // Attach a board to a sketch. When the `fqbn` field of a request is not
-  // provided, the FQBN of the attached board will be used.
-  rpc BoardAttach(BoardAttachRequest) returns (stream BoardAttachResponse);
-
   // List the boards currently connected to the computer.
   rpc BoardList(BoardListRequest) returns (BoardListResponse);
 
diff --git a/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go b/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go
index 27348321c5f..b092524084e 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/commands_grpc.pb.go
@@ -43,9 +43,6 @@ type ArduinoCoreServiceClient interface {
 	ArchiveSketch(ctx context.Context, in *ArchiveSketchRequest, opts ...grpc.CallOption) (*ArchiveSketchResponse, error)
 	// Requests details about a board
 	BoardDetails(ctx context.Context, in *BoardDetailsRequest, opts ...grpc.CallOption) (*BoardDetailsResponse, error)
-	// Attach a board to a sketch. When the `fqbn` field of a request is not
-	// provided, the FQBN of the attached board will be used.
-	BoardAttach(ctx context.Context, in *BoardAttachRequest, opts ...grpc.CallOption) (ArduinoCoreService_BoardAttachClient, error)
 	// List the boards currently connected to the computer.
 	BoardList(ctx context.Context, in *BoardListRequest, opts ...grpc.CallOption) (*BoardListResponse, error)
 	// List all the boards provided by installed platforms.
@@ -276,38 +273,6 @@ func (c *arduinoCoreServiceClient) BoardDetails(ctx context.Context, in *BoardDe
 	return out, nil
 }
 
-func (c *arduinoCoreServiceClient) BoardAttach(ctx context.Context, in *BoardAttachRequest, opts ...grpc.CallOption) (ArduinoCoreService_BoardAttachClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[3], "/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardAttach", opts...)
-	if err != nil {
-		return nil, err
-	}
-	x := &arduinoCoreServiceBoardAttachClient{stream}
-	if err := x.ClientStream.SendMsg(in); err != nil {
-		return nil, err
-	}
-	if err := x.ClientStream.CloseSend(); err != nil {
-		return nil, err
-	}
-	return x, nil
-}
-
-type ArduinoCoreService_BoardAttachClient interface {
-	Recv() (*BoardAttachResponse, error)
-	grpc.ClientStream
-}
-
-type arduinoCoreServiceBoardAttachClient struct {
-	grpc.ClientStream
-}
-
-func (x *arduinoCoreServiceBoardAttachClient) Recv() (*BoardAttachResponse, error) {
-	m := new(BoardAttachResponse)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
-}
-
 func (c *arduinoCoreServiceClient) BoardList(ctx context.Context, in *BoardListRequest, opts ...grpc.CallOption) (*BoardListResponse, error) {
 	out := new(BoardListResponse)
 	err := c.cc.Invoke(ctx, "/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardList", in, out, opts...)
@@ -336,7 +301,7 @@ func (c *arduinoCoreServiceClient) BoardSearch(ctx context.Context, in *BoardSea
 }
 
 func (c *arduinoCoreServiceClient) BoardListWatch(ctx context.Context, opts ...grpc.CallOption) (ArduinoCoreService_BoardListWatchClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[4], "/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardListWatch", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[3], "/cc.arduino.cli.commands.v1.ArduinoCoreService/BoardListWatch", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -367,7 +332,7 @@ func (x *arduinoCoreServiceBoardListWatchClient) Recv() (*BoardListWatchResponse
 }
 
 func (c *arduinoCoreServiceClient) Compile(ctx context.Context, in *CompileRequest, opts ...grpc.CallOption) (ArduinoCoreService_CompileClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[5], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Compile", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[4], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Compile", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -399,7 +364,7 @@ func (x *arduinoCoreServiceCompileClient) Recv() (*CompileResponse, error) {
 }
 
 func (c *arduinoCoreServiceClient) PlatformInstall(ctx context.Context, in *PlatformInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_PlatformInstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[6], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformInstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[5], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformInstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -431,7 +396,7 @@ func (x *arduinoCoreServicePlatformInstallClient) Recv() (*PlatformInstallRespon
 }
 
 func (c *arduinoCoreServiceClient) PlatformDownload(ctx context.Context, in *PlatformDownloadRequest, opts ...grpc.CallOption) (ArduinoCoreService_PlatformDownloadClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[7], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformDownload", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[6], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformDownload", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -463,7 +428,7 @@ func (x *arduinoCoreServicePlatformDownloadClient) Recv() (*PlatformDownloadResp
 }
 
 func (c *arduinoCoreServiceClient) PlatformUninstall(ctx context.Context, in *PlatformUninstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_PlatformUninstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[8], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformUninstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[7], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformUninstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -495,7 +460,7 @@ func (x *arduinoCoreServicePlatformUninstallClient) Recv() (*PlatformUninstallRe
 }
 
 func (c *arduinoCoreServiceClient) PlatformUpgrade(ctx context.Context, in *PlatformUpgradeRequest, opts ...grpc.CallOption) (ArduinoCoreService_PlatformUpgradeClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[9], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformUpgrade", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[8], "/cc.arduino.cli.commands.v1.ArduinoCoreService/PlatformUpgrade", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -527,7 +492,7 @@ func (x *arduinoCoreServicePlatformUpgradeClient) Recv() (*PlatformUpgradeRespon
 }
 
 func (c *arduinoCoreServiceClient) Upload(ctx context.Context, in *UploadRequest, opts ...grpc.CallOption) (ArduinoCoreService_UploadClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[10], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Upload", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[9], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Upload", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -559,7 +524,7 @@ func (x *arduinoCoreServiceUploadClient) Recv() (*UploadResponse, error) {
 }
 
 func (c *arduinoCoreServiceClient) UploadUsingProgrammer(ctx context.Context, in *UploadUsingProgrammerRequest, opts ...grpc.CallOption) (ArduinoCoreService_UploadUsingProgrammerClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[11], "/cc.arduino.cli.commands.v1.ArduinoCoreService/UploadUsingProgrammer", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[10], "/cc.arduino.cli.commands.v1.ArduinoCoreService/UploadUsingProgrammer", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -609,7 +574,7 @@ func (c *arduinoCoreServiceClient) ListProgrammersAvailableForUpload(ctx context
 }
 
 func (c *arduinoCoreServiceClient) BurnBootloader(ctx context.Context, in *BurnBootloaderRequest, opts ...grpc.CallOption) (ArduinoCoreService_BurnBootloaderClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[12], "/cc.arduino.cli.commands.v1.ArduinoCoreService/BurnBootloader", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[11], "/cc.arduino.cli.commands.v1.ArduinoCoreService/BurnBootloader", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -659,7 +624,7 @@ func (c *arduinoCoreServiceClient) PlatformList(ctx context.Context, in *Platfor
 }
 
 func (c *arduinoCoreServiceClient) LibraryDownload(ctx context.Context, in *LibraryDownloadRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryDownloadClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[13], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryDownload", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[12], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryDownload", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -691,7 +656,7 @@ func (x *arduinoCoreServiceLibraryDownloadClient) Recv() (*LibraryDownloadRespon
 }
 
 func (c *arduinoCoreServiceClient) LibraryInstall(ctx context.Context, in *LibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryInstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[14], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryInstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[13], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryInstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -723,7 +688,7 @@ func (x *arduinoCoreServiceLibraryInstallClient) Recv() (*LibraryInstallResponse
 }
 
 func (c *arduinoCoreServiceClient) LibraryUpgrade(ctx context.Context, in *LibraryUpgradeRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUpgradeClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[15], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgrade", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[14], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgrade", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -755,7 +720,7 @@ func (x *arduinoCoreServiceLibraryUpgradeClient) Recv() (*LibraryUpgradeResponse
 }
 
 func (c *arduinoCoreServiceClient) ZipLibraryInstall(ctx context.Context, in *ZipLibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_ZipLibraryInstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[16], "/cc.arduino.cli.commands.v1.ArduinoCoreService/ZipLibraryInstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[15], "/cc.arduino.cli.commands.v1.ArduinoCoreService/ZipLibraryInstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -787,7 +752,7 @@ func (x *arduinoCoreServiceZipLibraryInstallClient) Recv() (*ZipLibraryInstallRe
 }
 
 func (c *arduinoCoreServiceClient) GitLibraryInstall(ctx context.Context, in *GitLibraryInstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_GitLibraryInstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[17], "/cc.arduino.cli.commands.v1.ArduinoCoreService/GitLibraryInstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[16], "/cc.arduino.cli.commands.v1.ArduinoCoreService/GitLibraryInstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -819,7 +784,7 @@ func (x *arduinoCoreServiceGitLibraryInstallClient) Recv() (*GitLibraryInstallRe
 }
 
 func (c *arduinoCoreServiceClient) LibraryUninstall(ctx context.Context, in *LibraryUninstallRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUninstallClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[18], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUninstall", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[17], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUninstall", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -851,7 +816,7 @@ func (x *arduinoCoreServiceLibraryUninstallClient) Recv() (*LibraryUninstallResp
 }
 
 func (c *arduinoCoreServiceClient) LibraryUpgradeAll(ctx context.Context, in *LibraryUpgradeAllRequest, opts ...grpc.CallOption) (ArduinoCoreService_LibraryUpgradeAllClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[19], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgradeAll", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[18], "/cc.arduino.cli.commands.v1.ArduinoCoreService/LibraryUpgradeAll", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -910,7 +875,7 @@ func (c *arduinoCoreServiceClient) LibraryList(ctx context.Context, in *LibraryL
 }
 
 func (c *arduinoCoreServiceClient) Monitor(ctx context.Context, opts ...grpc.CallOption) (ArduinoCoreService_MonitorClient, error) {
-	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[20], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Monitor", opts...)
+	stream, err := c.cc.NewStream(ctx, &ArduinoCoreService_ServiceDesc.Streams[19], "/cc.arduino.cli.commands.v1.ArduinoCoreService/Monitor", opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -974,9 +939,6 @@ type ArduinoCoreServiceServer interface {
 	ArchiveSketch(context.Context, *ArchiveSketchRequest) (*ArchiveSketchResponse, error)
 	// Requests details about a board
 	BoardDetails(context.Context, *BoardDetailsRequest) (*BoardDetailsResponse, error)
-	// Attach a board to a sketch. When the `fqbn` field of a request is not
-	// provided, the FQBN of the attached board will be used.
-	BoardAttach(*BoardAttachRequest, ArduinoCoreService_BoardAttachServer) error
 	// List the boards currently connected to the computer.
 	BoardList(context.Context, *BoardListRequest) (*BoardListResponse, error)
 	// List all the boards provided by installed platforms.
@@ -1075,9 +1037,6 @@ func (UnimplementedArduinoCoreServiceServer) ArchiveSketch(context.Context, *Arc
 func (UnimplementedArduinoCoreServiceServer) BoardDetails(context.Context, *BoardDetailsRequest) (*BoardDetailsResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method BoardDetails not implemented")
 }
-func (UnimplementedArduinoCoreServiceServer) BoardAttach(*BoardAttachRequest, ArduinoCoreService_BoardAttachServer) error {
-	return status.Errorf(codes.Unimplemented, "method BoardAttach not implemented")
-}
 func (UnimplementedArduinoCoreServiceServer) BoardList(context.Context, *BoardListRequest) (*BoardListResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method BoardList not implemented")
 }
@@ -1364,27 +1323,6 @@ func _ArduinoCoreService_BoardDetails_Handler(srv interface{}, ctx context.Conte
 	return interceptor(ctx, in, info, handler)
 }
 
-func _ArduinoCoreService_BoardAttach_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(BoardAttachRequest)
-	if err := stream.RecvMsg(m); err != nil {
-		return err
-	}
-	return srv.(ArduinoCoreServiceServer).BoardAttach(m, &arduinoCoreServiceBoardAttachServer{stream})
-}
-
-type ArduinoCoreService_BoardAttachServer interface {
-	Send(*BoardAttachResponse) error
-	grpc.ServerStream
-}
-
-type arduinoCoreServiceBoardAttachServer struct {
-	grpc.ServerStream
-}
-
-func (x *arduinoCoreServiceBoardAttachServer) Send(m *BoardAttachResponse) error {
-	return x.ServerStream.SendMsg(m)
-}
-
 func _ArduinoCoreService_BoardList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
 	in := new(BoardListRequest)
 	if err := dec(in); err != nil {
@@ -2046,11 +1984,6 @@ var ArduinoCoreService_ServiceDesc = grpc.ServiceDesc{
 			Handler:       _ArduinoCoreService_UpdateLibrariesIndex_Handler,
 			ServerStreams: true,
 		},
-		{
-			StreamName:    "BoardAttach",
-			Handler:       _ArduinoCoreService_BoardAttach_Handler,
-			ServerStreams: true,
-		},
 		{
 			StreamName:    "BoardListWatch",
 			Handler:       _ArduinoCoreService_BoardListWatch_Handler,

From 06a3564d5bcb4fcdf196cce1dee940c7f78f419c Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Mon, 21 Nov 2022 14:01:22 +0100
Subject: [PATCH 003/606] Improve `board list` detection via cloud API (cache
 responses / do not error on network failure) (#1982)

* Slightly refactored apiByVidPid

* Cache cloud-api response for 24h to improve responsiveness

* Do not fail with errors in case of cloud-api is not available

* Fixed linter warning...

* Removed useless ErrNotFound from `apiByVidPid`

The `apiByVidPid` function now masks the odd behavior of the builder-api
returning an HTTP 404 if the request succeed but the result is empty.
---
 commands/board/list.go      | 114 ++++++++++++++++++++----------------
 commands/board/list_test.go |   7 +--
 inventory/inventory.go      |   6 ++
 3 files changed, 73 insertions(+), 54 deletions(-)

diff --git a/commands/board/list.go b/commands/board/list.go
index 13f1dbd05ad..6335fa69cb3 100644
--- a/commands/board/list.go
+++ b/commands/board/list.go
@@ -19,7 +19,7 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"regexp"
 	"sort"
@@ -32,24 +32,43 @@ import (
 	"github.com/arduino/arduino-cli/arduino/discovery"
 	"github.com/arduino/arduino-cli/arduino/httpclient"
 	"github.com/arduino/arduino-cli/commands"
+	"github.com/arduino/arduino-cli/inventory"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
 
-type boardNotFoundError struct{}
-
-func (e *boardNotFoundError) Error() string {
-	return tr("board not found")
-}
-
 var (
-	// ErrNotFound is returned when the API returns 404
-	ErrNotFound = &boardNotFoundError{}
 	vidPidURL   = "https://builder.arduino.cc/v3/boards/byVidPid"
 	validVidPid = regexp.MustCompile(`0[xX][a-fA-F\d]{4}`)
 )
 
+func cachedAPIByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
+	var resp []*rpc.BoardListItem
+
+	cacheKey := fmt.Sprintf("cache.builder-api.v3/boards/byvid/pid/%s/%s", vid, pid)
+	if cachedResp := inventory.Store.GetString(cacheKey + ".data"); cachedResp != "" {
+		ts := inventory.Store.GetTime(cacheKey + ".ts")
+		if time.Since(ts) < time.Hour*24 {
+			// Use cached response
+			if err := json.Unmarshal([]byte(cachedResp), &resp); err == nil {
+				return resp, nil
+			}
+		}
+	}
+
+	resp, err := apiByVidPid(vid, pid) // Perform API requrest
+
+	if err == nil {
+		if cachedResp, err := json.Marshal(resp); err == nil {
+			inventory.Store.Set(cacheKey+".data", string(cachedResp))
+			inventory.Store.Set(cacheKey+".ts", time.Now())
+			inventory.WriteStore()
+		}
+	}
+	return resp, err
+}
+
 func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
 	// ensure vid and pid are valid before hitting the API
 	if !validVidPid.MatchString(vid) {
@@ -60,7 +79,6 @@ func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
 	}
 
 	url := fmt.Sprintf("%s/%s/%s", vidPidURL, vid, pid)
-	retVal := []*rpc.BoardListItem{}
 	req, _ := http.NewRequest("GET", url, nil)
 	req.Header.Set("Content-Type", "application/json")
 
@@ -72,50 +90,53 @@ func apiByVidPid(vid, pid string) ([]*rpc.BoardListItem, error) {
 		return nil, errors.Wrap(err, tr("failed to initialize http client"))
 	}
 
-	if res, err := httpClient.Do(req); err == nil {
-		if res.StatusCode >= 400 {
-			if res.StatusCode == 404 {
-				return nil, ErrNotFound
-			}
-			return nil, errors.Errorf(tr("the server responded with status %s"), res.Status)
-		}
-
-		body, _ := ioutil.ReadAll(res.Body)
-		res.Body.Close()
-
-		var dat map[string]interface{}
-		err = json.Unmarshal(body, &dat)
-		if err != nil {
-			return nil, errors.Wrap(err, tr("error processing response from server"))
-		}
+	res, err := httpClient.Do(req)
+	if err != nil {
+		return nil, errors.Wrap(err, tr("error querying Arduino Cloud Api"))
+	}
+	if res.StatusCode == 404 {
+		// This is not an error, it just means that the board is not recognized
+		return nil, nil
+	}
+	if res.StatusCode >= 400 {
+		return nil, errors.Errorf(tr("the server responded with status %s"), res.Status)
+	}
 
-		name, nameFound := dat["name"].(string)
-		fqbn, fbqnFound := dat["fqbn"].(string)
+	resp, err := io.ReadAll(res.Body)
+	if err != nil {
+		return nil, err
+	}
+	if err := res.Body.Close(); err != nil {
+		return nil, err
+	}
 
-		if !nameFound || !fbqnFound {
-			return nil, errors.New(tr("wrong format in server response"))
-		}
+	var dat map[string]interface{}
+	if err := json.Unmarshal(resp, &dat); err != nil {
+		return nil, errors.Wrap(err, tr("error processing response from server"))
+	}
+	name, nameFound := dat["name"].(string)
+	fqbn, fbqnFound := dat["fqbn"].(string)
+	if !nameFound || !fbqnFound {
+		return nil, errors.New(tr("wrong format in server response"))
+	}
 
-		retVal = append(retVal, &rpc.BoardListItem{
+	return []*rpc.BoardListItem{
+		{
 			Name: name,
 			Fqbn: fqbn,
-		})
-	} else {
-		return nil, errors.Wrap(err, tr("error querying Arduino Cloud Api"))
-	}
-
-	return retVal, nil
+		},
+	}, nil
 }
 
 func identifyViaCloudAPI(port *discovery.Port) ([]*rpc.BoardListItem, error) {
 	// If the port is not USB do not try identification via cloud
 	id := port.Properties
 	if !id.ContainsKey("vid") || !id.ContainsKey("pid") {
-		return nil, ErrNotFound
+		return nil, nil
 	}
 
 	logrus.Debug("Querying builder API for board identification...")
-	return apiByVidPid(id.Get("vid"), id.Get("pid"))
+	return cachedAPIByVidPid(id.Get("vid"), id.Get("pid"))
 }
 
 // identify returns a list of boards checking first the installed platforms or the Cloud API
@@ -146,17 +167,10 @@ func identify(pme *packagemanager.Explorer, port *discovery.Port) ([]*rpc.BoardL
 	// the builder API if the board is a USB device port
 	if len(boards) == 0 {
 		items, err := identifyViaCloudAPI(port)
-		if errors.Is(err, ErrNotFound) {
-			// the board couldn't be detected, print a warning
-			logrus.Debug("Board not recognized")
-		} else if err != nil {
-			// this is bad, bail out
-			return nil, &arduino.UnavailableError{Message: tr("Error getting board info from Arduino Cloud")}
+		if err != nil {
+			// this is bad, but keep going
+			logrus.WithError(err).Debug("Error querying builder API")
 		}
-
-		// add a DetectedPort entry in any case: the `Boards` field will
-		// be empty but the port will be shown anyways (useful for 3rd party
-		// boards)
 		boards = items
 	}
 
diff --git a/commands/board/list_test.go b/commands/board/list_test.go
index 3d3314f9404..cf1dca37e4c 100644
--- a/commands/board/list_test.go
+++ b/commands/board/list_test.go
@@ -71,9 +71,8 @@ func TestGetByVidPidNotFound(t *testing.T) {
 
 	vidPidURL = ts.URL
 	res, err := apiByVidPid("0x0420", "0x0069")
-	require.NotNil(t, err)
-	require.Equal(t, "board not found", err.Error())
-	require.Len(t, res, 0)
+	require.NoError(t, err)
+	require.Empty(t, res)
 }
 
 func TestGetByVidPid5xx(t *testing.T) {
@@ -108,7 +107,7 @@ func TestBoardDetectionViaAPIWithNonUSBPort(t *testing.T) {
 		Properties: properties.NewMap(),
 	}
 	items, err := identifyViaCloudAPI(port)
-	require.ErrorIs(t, err, ErrNotFound)
+	require.NoError(t, err)
 	require.Empty(t, items)
 }
 
diff --git a/inventory/inventory.go b/inventory/inventory.go
index fe86634b6ac..8411a58fc2c 100644
--- a/inventory/inventory.go
+++ b/inventory/inventory.go
@@ -19,6 +19,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"sync"
 
 	"github.com/arduino/arduino-cli/i18n"
 	"github.com/gofrs/uuid"
@@ -77,9 +78,14 @@ func generateInstallationData() error {
 	return nil
 }
 
+var writeStoreMux sync.Mutex
+
 // WriteStore writes the current information from Store to configFilePath.
 // Returns err if it fails.
 func WriteStore() error {
+	writeStoreMux.Lock()
+	defer writeStoreMux.Unlock()
+
 	configPath := filepath.Dir(configFilePath)
 
 	// Create config dir if not present,

From 2bde46134f316efc69b492565968577f2c4007c3 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Tue, 22 Nov 2022 08:55:00 +0100
Subject: [PATCH 004/606] Migrate TestUploadSketch to upload_mock_test.go and
 delete test_upload_mock.py (#1976)

---
 .../upload_mock/upload_mock_test.go           |  704 ++++++++++
 test/test_upload_mock.py                      | 1240 -----------------
 2 files changed, 704 insertions(+), 1240 deletions(-)
 create mode 100644 internal/integrationtest/upload_mock/upload_mock_test.go
 delete mode 100644 test/test_upload_mock.py

diff --git a/internal/integrationtest/upload_mock/upload_mock_test.go b/internal/integrationtest/upload_mock/upload_mock_test.go
new file mode 100644
index 00000000000..cf6613805ef
--- /dev/null
+++ b/internal/integrationtest/upload_mock/upload_mock_test.go
@@ -0,0 +1,704 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package upload_mock_test
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"fmt"
+	"runtime"
+	"strings"
+	"testing"
+
+	"github.com/arduino/arduino-cli/internal/integrationtest"
+	"github.com/arduino/go-paths-helper"
+	"github.com/stretchr/testify/require"
+)
+
+type parameters struct {
+	Fqbn       string
+	UploadPort string
+	Programmer string
+	Output     string
+}
+
+type parametersMap struct {
+	Fqbn       string
+	UploadPort string
+	Programmer string
+	Output     map[string]string
+}
+
+func TestUploadSketch(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	indexes := []string{
+		"https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json",
+		"https://adafruit.github.io/arduino-board-index/package_adafruit_index.json",
+		"https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json",
+		"http://arduino.esp8266.com/stable/package_esp8266com_index.json",
+		"https://github.com/sonydevworld/spresense-arduino-compatible/releases/download/generic/package_spresense_index.json",
+	}
+
+	coresToInstall := []string{
+		"STMicroelectronics:stm32@2.2.0",
+		"arduino:avr@1.8.3",
+		"adafruit:avr@1.4.13",
+		"arduino:samd@1.8.11",
+		"esp32:esp32@1.0.6",
+		"esp8266:esp8266@3.0.2",
+		"SPRESENSE:spresense@2.0.2",
+	}
+
+	testParameters := []parameters{
+		{
+			Fqbn:       "arduino:avr:uno",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -carduino \"-P/dev/ttyACM0\" -b115200 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:uno",
+			UploadPort: "",
+			Programmer: "usbasp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cusbasp -Pusb \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:uno",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "avrisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:uno",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "arduinoasisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 -b19200 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -carduino \"-P/dev/ttyACM0\" -b115200 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano",
+			UploadPort: "",
+			Programmer: "usbasp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cusbasp -Pusb \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "avrisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "arduinoasisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 -b19200 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano:cpu=atmega328old",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -carduino \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano:cpu=atmega328old",
+			UploadPort: "",
+			Programmer: "usbasp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cusbasp -Pusb \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano:cpu=atmega328old",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "avrisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:nano:cpu=atmega328old",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "arduinoasisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 -b19200 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:mega",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega2560 -cwiring \"-P/dev/ttyACM0\" -b115200 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:mega:cpu=atmega1280",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega1280 -carduino \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:diecimila",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -carduino \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:leonardo",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM9990\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:micro",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM9990\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:circuitplay32u4cat",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM9990\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:gemma",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "usbGemma",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/hardware/avr/1.8.3/bootloaders/gemma/avrdude.conf\" -v -V -pattiny85 -carduinogemma  \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:gemma",
+			UploadPort: "",
+			Programmer: "usbGemma",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/hardware/avr/1.8.3/bootloaders/gemma/avrdude.conf\" -v -V -pattiny85 -carduinogemma  \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:unowifi",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega328p -carduino \"-P/dev/ttyACM0\" -b115200 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "arduino:avr:yun",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM9990\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:circuitplay32u4cat",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:flora8",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:gemma",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "usbGemma",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/adafruit/hardware/avr/1.4.13/bootloaders/gemma/avrdude.conf\" -v -pattiny85 -carduinogemma  \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:gemma",
+			UploadPort: "",
+			Programmer: "usbGemma",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/adafruit/hardware/avr/1.4.13/bootloaders/gemma/avrdude.conf\" -v -pattiny85 -carduinogemma  \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:itsybitsy32u4_3V",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:itsybitsy32u4_5V",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output:     "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:metro",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:trinket3",
+			UploadPort: "",
+			Programmer: "usbasp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -pattiny85 -cusbasp -Pusb \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:trinket3",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "avrisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -pattiny85 -cstk500v1 -P/dev/ttyACM0 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "adafruit:avr:trinket3",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "arduinoasisp",
+			Output:     "\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -pattiny85 -cstk500v1 -P/dev/ttyACM0 -b19200 \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+		},
+		{
+			Fqbn:       "esp8266:esp8266:generic",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/esp8266/tools/python3/3.7.2-post1/python3\" -I \"{data_dir}/packages/esp8266/hardware/esp8266/3.0.2/tools/upload.py\" --chip esp8266 --port \"/dev/ttyACM0\" --baud \"115200\" \"\"  --before default_reset --after hard_reset write_flash 0x0 \"{build_dir}/{sketch_name}.ino.bin\"\n",
+		},
+		{
+			Fqbn:       "esp8266:esp8266:generic:xtal=160,vt=heap,mmu=3216,ResetMethod=nodtr_nosync,CrystalFreq=40,FlashFreq=20,eesz=2M,baud=57600",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output:     "\"{data_dir}/packages/esp8266/tools/python3/3.7.2-post1/python3\" -I \"{data_dir}/packages/esp8266/hardware/esp8266/3.0.2/tools/upload.py\" --chip esp8266 --port \"/dev/ttyACM0\" --baud \"57600\" \"\"  --before no_reset_no_sync --after soft_reset write_flash 0x0 \"{build_dir}/{sketch_name}.ino.bin\"\n",
+		},
+	}
+
+	testParametersMap := []parametersMap{
+		{
+			Fqbn:       "arduino:avr:leonardo",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:avr:micro",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:avr:circuitplay32u4cat",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:avr:yun",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "adafruit:avr:circuitplay32u4cat",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "adafruit:avr:flora8",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "adafruit:avr:itsybitsy32u4_3V",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "adafruit:avr:itsybitsy32u4_5V",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+			},
+		},
+		{
+			Fqbn:       "STMicroelectronics:stm32:Nucleo_32:pnum=NUCLEO_F031K6,upload_method=serialMethod",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "\"\" sh \"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/stm32CubeProg.sh\" 1 \"{build_dir}/{sketch_name}.ino.bin\" ttyACM0 -s\n",
+				"linux":  "\"\" sh \"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/stm32CubeProg.sh\" 1 \"{build_dir}/{sketch_name}.ino.bin\" ttyACM0 -s\n",
+				"win32":  "\"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/win/busybox.exe\" \"sh \"\"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/stm32CubeProg.sh\" 1 \"{build_dir}/{sketch_name}.ino.bin\" ttyACM0 -s\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:arduino_zero_edbg",
+			UploadPort: "",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "\"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd\" -d2 -s \"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/\" -f \"{data_dir}/packages/arduino/hardware/samd/1.8.11/variants/arduino_zero/openocd_scripts/arduino_zero.cfg\" -c \"telnet_port disabled; program {{build_dir}/{sketch_name}.ino.bin} verify reset 0x2000; shutdown\"\n",
+				"linux":  "\"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd\" -d2 -s \"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/\" -f \"{data_dir}/packages/arduino/hardware/samd/1.8.11/variants/arduino_zero/openocd_scripts/arduino_zero.cfg\" -c \"telnet_port disabled; program {{build_dir}/{sketch_name}.ino.bin} verify reset 0x2000; shutdown\"\n",
+				"win32":  "\"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd.exe\" -d2 -s \"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/\" -f \"{data_dir}/packages/arduino/hardware/samd/1.8.11/variants/arduino_zero/openocd_scripts/arduino_zero.cfg\" -c \"telnet_port disabled; program {{build_dir}/{sketch_name}.ino.bin} verify reset 0x2000; shutdown\"\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:adafruit_circuitplayground_m0",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:adafruit_circuitplayground_m0",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrfox1200",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrfox1200",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrgsm1400",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrgsm1400",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrvidor4000",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrvidor4000",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrwan1310",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrwan1310",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrwifi1010",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrwifi1010",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkr1000",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkr1000",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrzero",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:mkrzero",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:nano_33_iot",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:nano_33_iot",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:arduino_zero_native",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "arduino:samd:arduino_zero_native",
+			UploadPort: "/dev/ttyACM999",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM999\nWaiting for upload port...\nUpload port found on /dev/ttyACM9990\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM9990 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+			},
+		},
+		{
+			Fqbn:       "esp32:esp32:esp32",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "\"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool\" --chip esp32 --port \"/dev/ttyACM0\" --baud 921600  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_qio_80m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+				"linux":  "python \"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.py\" --chip esp32 --port \"/dev/ttyACM0\" --baud 921600  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_qio_80m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+				"win32":  "\"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.exe\" --chip esp32 --port \"/dev/ttyACM0\" --baud 921600  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_qio_80m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+			},
+		},
+		{
+			Fqbn:       "esp32:esp32:esp32:PSRAM=enabled,PartitionScheme=no_ota,CPUFreq=80,FlashMode=dio,FlashFreq=40,FlashSize=8M,UploadSpeed=230400,DebugLevel=info",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "\"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool\" --chip esp32 --port \"/dev/ttyACM0\" --baud 230400  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_40m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+				"linux":  "python \"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.py\" --chip esp32 --port \"/dev/ttyACM0\" --baud 230400  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_40m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+				"win32":  "\"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.exe\" --chip esp32 --port \"/dev/ttyACM0\" --baud 230400  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_40m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+			},
+		},
+		{
+			Fqbn:       "esp32:esp32:esp32thing",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "\"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool\" --chip esp32 --port \"/dev/ttyACM0\" --baud 921600  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_80m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+				"linux":  "python \"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.py\" --chip esp32 --port \"/dev/ttyACM0\" --baud 921600  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_80m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+				"win32":  "\"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.exe\" --chip esp32 --port \"/dev/ttyACM0\" --baud 921600  --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0xe000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin\" 0x1000 \"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_80m.bin\" 0x10000 \"{build_dir}/{sketch_name}.ino.bin\" 0x8000 \"{build_dir}/{sketch_name}.ino.partitions.bin\"\n",
+			},
+		},
+		{
+			Fqbn:       "SPRESENSE:spresense:spresense",
+			UploadPort: "/dev/ttyACM0",
+			Programmer: "",
+			Output: map[string]string{
+				"darwin": "\"{data_dir}/packages/SPRESENSE/tools/spresense-tools/2.0.2/flash_writer/macosx/flash_writer\" -s -c \"/dev/ttyACM0\"  -d -n \"{build_dir}/{sketch_name}.ino.spk\"",
+				"linux":  "\"{data_dir}/packages/SPRESENSE/tools/spresense-tools/2.0.2/flash_writer/linux/flash_writer\" -s -c \"/dev/ttyACM0\"  -d -n \"{build_dir}/{sketch_name}.ino.spk\"",
+				"win32":  "\"{data_dir}/packages/SPRESENSE/tools/spresense-tools/2.0.2/flash_writer/windows/flash_writer.exe\" -s -c \"/dev/ttyACM0\"  -d -n \"{build_dir}/{sketch_name}.ino.spk\"",
+			},
+		},
+	}
+
+	if cli.DataDir().Join("packages").NotExist() {
+		_, _, err := cli.Run("config", "init", "--overwrite")
+		require.NoError(t, err)
+		for _, v := range indexes {
+			_, _, err := cli.Run("config", "add", "board_manager.additional_urls", v)
+			require.NoError(t, err)
+		}
+		_, _, err = cli.Run("update")
+		require.NoError(t, err)
+		for _, v := range coresToInstall {
+			_, _, err := cli.Run("core", "install", v)
+			require.NoError(t, err)
+		}
+	}
+
+	sketchName := "TestSketchForUpload"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+	_, _, err := cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	var stdout []byte
+
+	for i, test := range testParameters {
+		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
+			buildDir := generateBuildDir(sketchPath, t)
+			defer buildDir.RemoveAll()
+			if test.Programmer != "" {
+				if test.UploadPort != "" {
+					stdout, _, err = cli.Run("upload", "-p", test.UploadPort, "-P", test.Programmer, "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				} else {
+					stdout, _, err = cli.Run("upload", "-P", test.Programmer, "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				}
+			} else {
+				if test.UploadPort != "" {
+					stdout, _, err = cli.Run("upload", "-p", test.UploadPort, "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				} else {
+					stdout, _, err = cli.Run("upload", "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				}
+			}
+			r := strings.NewReplacer("{data_dir}", cli.DataDir().String(), "{upload_port", test.UploadPort,
+				"{build_dir}", buildDir.String(), "{sketch_name}", sketchName)
+			expectedOut := strings.ReplaceAll(r.Replace(test.Output), "\\", "/")
+			require.Contains(t, strings.ReplaceAll(string(stdout), "\\", "/"), expectedOut)
+		})
+	}
+
+	for i, test := range testParametersMap {
+		t.Run(fmt.Sprintf("WithMap%d", i), func(t *testing.T) {
+			buildDir := generateBuildDir(sketchPath, t)
+			defer buildDir.RemoveAll()
+			if test.Programmer != "" {
+				if test.UploadPort != "" {
+					stdout, _, err = cli.Run("upload", "-p", test.UploadPort, "-P", test.Programmer, "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				} else {
+					stdout, _, err = cli.Run("upload", "-P", test.Programmer, "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				}
+			} else {
+				if test.UploadPort != "" {
+					stdout, _, err = cli.Run("upload", "-p", test.UploadPort, "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				} else {
+					stdout, _, err = cli.Run("upload", "-b", test.Fqbn, sketchPath.String(), "--dry-run", "-v")
+					require.NoError(t, err)
+				}
+			}
+			out := test.Output[runtime.GOOS]
+			r := strings.NewReplacer("{data_dir}", cli.DataDir().String(), "{upload_port", test.UploadPort,
+				"{build_dir}", buildDir.String(), "{sketch_name}", sketchName)
+			expectedOut := strings.ReplaceAll(r.Replace(out), "\\", "/")
+			require.Contains(t, strings.ReplaceAll(string(stdout), "\\", "/"), expectedOut)
+		})
+	}
+}
+
+func generateBuildDir(sketchPath *paths.Path, t *testing.T) *paths.Path {
+	md5 := md5.Sum(([]byte(sketchPath.String())))
+	sketchPathMd5 := strings.ToUpper(hex.EncodeToString(md5[:]))
+	buildDir := paths.TempDir().Join("arduino-sketch-" + sketchPathMd5)
+	require.NoError(t, buildDir.MkdirAll())
+	require.NoError(t, buildDir.ToAbs())
+	return buildDir
+}
diff --git a/test/test_upload_mock.py b/test/test_upload_mock.py
deleted file mode 100644
index efb42781c25..00000000000
--- a/test/test_upload_mock.py
+++ /dev/null
@@ -1,1240 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
-
-import tempfile
-import sys
-import hashlib
-import pytest
-from pathlib import Path
-
-
-def generate_build_dir(sketch_path):
-    sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
-    build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
-    build_dir.mkdir(parents=True, exist_ok=True)
-    return build_dir.resolve()
-
-
-indexes = [
-    "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json",
-    "https://adafruit.github.io/arduino-board-index/package_adafruit_index.json",
-    "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json",
-    "http://arduino.esp8266.com/stable/package_esp8266com_index.json",
-    "https://github.com/sonydevworld/spresense-arduino-compatible/releases/download/generic/package_spresense_index.json",
-]
-
-cores_to_install = [
-    "STMicroelectronics:stm32@2.2.0",
-    "arduino:avr@1.8.3",
-    "adafruit:avr@1.4.13",
-    "arduino:samd@1.8.11",
-    "esp32:esp32@1.0.6",
-    "esp8266:esp8266@3.0.2",
-    "SPRESENSE:spresense@2.0.2",
-]
-
-testdata = [
-    (
-        "STMicroelectronics:stm32:Nucleo_32:pnum=NUCLEO_F031K6,upload_method=serialMethod",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": '"" sh '
-            '"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/stm32CubeProg.sh" '
-            '1 "{build_dir}/{sketch_name}.ino.bin" ttyACM0 -s\n',
-            "linux": '"" sh '
-            '"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/stm32CubeProg.sh" '
-            '1 "{build_dir}/{sketch_name}.ino.bin" ttyACM0 -s\n',
-            "win32": '"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/win/busybox.exe" '
-            "sh "
-            '"{data_dir}/packages/STMicroelectronics/tools/STM32Tools/2.1.1/stm32CubeProg.sh" '
-            '1 "{build_dir}/{sketch_name}.ino.bin" ttyACM0 -s\n',
-        },
-    ),
-    (
-        "arduino:avr:uno",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega328p -carduino "-P/dev/ttyACM0" -b115200 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:uno",
-        "",
-        "usbasp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cusbasp -Pusb "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:uno",
-        "/dev/ttyACM0",
-        "avrisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:uno",
-        "/dev/ttyACM0",
-        "arduinoasisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 -b19200 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega328p -carduino "-P/dev/ttyACM0" -b115200 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano",
-        "",
-        "usbasp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cusbasp -Pusb "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano",
-        "/dev/ttyACM0",
-        "avrisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano",
-        "/dev/ttyACM0",
-        "arduinoasisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 -b19200 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano:cpu=atmega328old",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega328p -carduino "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano:cpu=atmega328old",
-        "",
-        "usbasp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cusbasp -Pusb "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano:cpu=atmega328old",
-        "/dev/ttyACM0",
-        "avrisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:nano:cpu=atmega328old",
-        "/dev/ttyACM0",
-        "arduinoasisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -V -patmega328p -cstk500v1 -P/dev/ttyACM0 -b19200 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:mega",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega2560 -cwiring "-P/dev/ttyACM0" -b115200 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:mega:cpu=atmega1280",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega1280 -carduino "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:diecimila",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega328p -carduino "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:leonardo",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:leonardo",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM9990" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:micro",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:micro",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM9990" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:circuitplay32u4cat",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:circuitplay32u4cat",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM9990" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:gemma",
-        "/dev/ttyACM0",
-        "usbGemma",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/hardware/avr/1.8.3/bootloaders/gemma/avrdude.conf" '
-        "-v -V -pattiny85 -carduinogemma  "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:gemma",
-        "",
-        "usbGemma",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/hardware/avr/1.8.3/bootloaders/gemma/avrdude.conf" '
-        "-v -V -pattiny85 -carduinogemma  "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:unowifi",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega328p -carduino "-P/dev/ttyACM0" -b115200 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:yun",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM0" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:avr:yun",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        '-v -V -patmega32u4 -cavr109 "-P/dev/ttyACM9990" -b57600 -D '
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:circuitplay32u4cat",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:circuitplay32u4cat",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:flora8",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:flora8",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:gemma",
-        "/dev/ttyACM0",
-        "usbGemma",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/adafruit/hardware/avr/1.4.13/bootloaders/gemma/avrdude.conf" '
-        "-v -pattiny85 -carduinogemma  "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:gemma",
-        "",
-        "usbGemma",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/adafruit/hardware/avr/1.4.13/bootloaders/gemma/avrdude.conf" '
-        "-v -pattiny85 -carduinogemma  "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:itsybitsy32u4_3V",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:itsybitsy32u4_3V",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:itsybitsy32u4_5V",
-        "/dev/ttyACM0",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-        "Waiting for upload port...\n"
-        "No upload port found, using /dev/ttyACM0 as fallback\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:itsybitsy32u4_5V",
-        "/dev/ttyACM999",
-        "",
-        "Performing 1200-bps touch reset on serial port /dev/ttyACM999\n"
-        "Waiting for upload port...\n"
-        "Upload port found on /dev/ttyACM9990\n"
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega32u4 -cavr109 -P/dev/ttyACM9990 -b57600 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:metro",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:trinket3",
-        "",
-        "usbasp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -pattiny85 -cusbasp -Pusb "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:trinket3",
-        "/dev/ttyACM0",
-        "avrisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -pattiny85 -cstk500v1 -P/dev/ttyACM0 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "adafruit:avr:trinket3",
-        "/dev/ttyACM0",
-        "arduinoasisp",
-        '"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude" '
-        '"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" '
-        "-v -pattiny85 -cstk500v1 -P/dev/ttyACM0 -b19200 "
-        '"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i"\n',
-    ),
-    (
-        "arduino:samd:arduino_zero_edbg",
-        "",
-        "",
-        {
-            "darwin": '"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd" '
-            "-d2 -s "
-            '"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/" '
-            "-f "
-            '"{data_dir}/packages/arduino/hardware/samd/1.8.11/variants/arduino_zero/openocd_scripts/arduino_zero.cfg" '
-            '-c "telnet_port disabled; program '
-            "{{{build_dir}/{sketch_name}.ino.bin}} verify reset 0x2000; "
-            'shutdown"\n',
-            "linux": '"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd" '
-            "-d2 -s "
-            '"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/" '
-            "-f "
-            '"{data_dir}/packages/arduino/hardware/samd/1.8.11/variants/arduino_zero/openocd_scripts/arduino_zero.cfg" '
-            '-c "telnet_port disabled; program '
-            "{{{build_dir}/{sketch_name}.ino.bin}} verify reset 0x2000; "
-            'shutdown"\n',
-            "win32": '"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/bin/openocd.exe" '
-            "-d2 -s "
-            '"{data_dir}/packages/arduino/tools/openocd/0.10.0-arduino7/share/openocd/scripts/" '
-            "-f "
-            '"{data_dir}/packages/arduino/hardware/samd/1.8.11/variants/arduino_zero/openocd_scripts/arduino_zero.cfg" '
-            '-c "telnet_port disabled; program '
-            "{{{build_dir}/{sketch_name}.ino.bin}} verify reset 0x2000; "
-            'shutdown"\n',
-        },
-    ),
-    (
-        "arduino:samd:adafruit_circuitplayground_m0",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:adafruit_circuitplayground_m0",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrfox1200",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrfox1200",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrgsm1400",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrgsm1400",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrvidor4000",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -I -U true -i -e -w "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -I -U true -i -e -w "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -I -U true -i -e -w "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrvidor4000",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -I -U true -i -e -w "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -I -U true -i -e -w "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -I -U true -i -e -w "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrwan1310",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrwan1310",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrwifi1010",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrwifi1010",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkr1000",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkr1000",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrzero",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:mkrzero",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:nano_33_iot",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:nano_33_iot",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:arduino_zero_native",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\n"
-            "Waiting for upload port...\n"
-            "No upload port found, using /dev/ttyACM0 as fallback\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM0 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "arduino:samd:arduino_zero_native",
-        "/dev/ttyACM999",
-        "",
-        {
-            "darwin": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "linux": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-            "win32": "Performing 1200-bps touch reset on serial port "
-            "/dev/ttyACM999\n"
-            "Waiting for upload port...\n"
-            "Upload port found on /dev/ttyACM9990\n"
-            '"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe" '
-            "-i -d --port=ttyACM9990 -U true -i -e -w -v "
-            '"{build_dir}/{sketch_name}.ino.bin" -R\n',
-        },
-    ),
-    (
-        "esp32:esp32:esp32",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 921600  --before '
-            "default_reset --after hard_reset write_flash -z "
-            "--flash_mode dio --flash_freq 80m --flash_size detect "
-            "0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_qio_80m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-            "linux": "python "
-            '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.py" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 921600  --before '
-            "default_reset --after hard_reset write_flash -z --flash_mode "
-            "dio --flash_freq 80m --flash_size detect 0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_qio_80m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-            "win32": '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.exe" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 921600  --before '
-            "default_reset --after hard_reset write_flash -z --flash_mode "
-            "dio --flash_freq 80m --flash_size detect 0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_qio_80m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-        },
-    ),
-    (
-        "esp32:esp32:esp32:PSRAM=enabled,PartitionScheme=no_ota,CPUFreq=80,FlashMode=dio,FlashFreq=40,FlashSize=8M,UploadSpeed=230400,DebugLevel=info",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 230400  --before '
-            "default_reset --after hard_reset write_flash -z "
-            "--flash_mode dio --flash_freq 40m --flash_size detect "
-            "0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_40m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-            "linux": "python "
-            '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.py" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 230400  --before '
-            "default_reset --after hard_reset write_flash -z --flash_mode "
-            "dio --flash_freq 40m --flash_size detect 0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_40m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-            "win32": '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.exe" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 230400  --before '
-            "default_reset --after hard_reset write_flash -z --flash_mode "
-            "dio --flash_freq 40m --flash_size detect 0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_40m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-        },
-    ),
-    (
-        "esp32:esp32:esp32thing",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 921600  --before '
-            "default_reset --after hard_reset write_flash -z "
-            "--flash_mode dio --flash_freq 80m --flash_size detect "
-            "0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_80m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-            "linux": "python "
-            '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.py" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 921600  --before '
-            "default_reset --after hard_reset write_flash -z --flash_mode "
-            "dio --flash_freq 80m --flash_size detect 0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_80m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-            "win32": '"{data_dir}/packages/esp32/tools/esptool_py/3.0.0/esptool.exe" '
-            '--chip esp32 --port "/dev/ttyACM0" --baud 921600  --before '
-            "default_reset --after hard_reset write_flash -z --flash_mode "
-            "dio --flash_freq 80m --flash_size detect 0xe000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/partitions/boot_app0.bin" '
-            "0x1000 "
-            '"{data_dir}/packages/esp32/hardware/esp32/1.0.6/tools/sdk/bin/bootloader_dio_80m.bin" '
-            '0x10000 "{build_dir}/{sketch_name}.ino.bin" 0x8000 '
-            '"{build_dir}/{sketch_name}.ino.partitions.bin"\n',
-        },
-    ),
-    (
-        "esp8266:esp8266:generic",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/esp8266/tools/python3/3.7.2-post1/python3" -I '
-        '"{data_dir}/packages/esp8266/hardware/esp8266/3.0.2/tools/upload.py" '
-        '--chip esp8266 --port "/dev/ttyACM0" --baud "115200" ""  --before '
-        "default_reset --after hard_reset write_flash 0x0 "
-        '"{build_dir}/{sketch_name}.ino.bin"\n',
-    ),
-    (
-        "esp8266:esp8266:generic:xtal=160,vt=heap,mmu=3216,ResetMethod=nodtr_nosync,CrystalFreq=40,FlashFreq=20,eesz=2M,baud=57600",
-        "/dev/ttyACM0",
-        "",
-        '"{data_dir}/packages/esp8266/tools/python3/3.7.2-post1/python3" -I '
-        '"{data_dir}/packages/esp8266/hardware/esp8266/3.0.2/tools/upload.py" '
-        '--chip esp8266 --port "/dev/ttyACM0" --baud "57600" ""  --before '
-        "no_reset_no_sync --after soft_reset write_flash 0x0 "
-        '"{build_dir}/{sketch_name}.ino.bin"\n',
-    ),
-    (
-        "SPRESENSE:spresense:spresense",
-        "/dev/ttyACM0",
-        "",
-        {
-            "darwin": '"{data_dir}/packages/SPRESENSE/tools/spresense-tools/2.0.2/flash_writer/macosx/flash_writer" '
-            '-s -c "/dev/ttyACM0"  -d -n "{build_dir}/{sketch_name}.ino.spk"',
-            "linux": '"{data_dir}/packages/SPRESENSE/tools/spresense-tools/2.0.2/flash_writer/linux/flash_writer" '
-            '-s -c "/dev/ttyACM0"  -d -n "{build_dir}/{sketch_name}.ino.spk"',
-            "win32": '"{data_dir}/packages/SPRESENSE/tools/spresense-tools/2.0.2/flash_writer/windows/flash_writer.exe" '
-            '-s -c "/dev/ttyACM0"  -d -n "{build_dir}/{sketch_name}.ino.spk"',
-        },
-    ),
-]
-
-
-@pytest.mark.parametrize("fqbn, upload_port, programmer, output", testdata)
-def test_upload_sketch(
-    run_command,
-    session_data_dir,
-    downloads_dir,
-    fqbn,
-    upload_port,
-    programmer,
-    output,
-):
-    env = {
-        "ARDUINO_DATA_DIR": session_data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": session_data_dir,
-    }
-
-    # Install everything just once
-    if not Path(session_data_dir, "packages").is_dir():
-        assert run_command(["config", "init", "--overwrite"], custom_env=env)
-        for package_index in indexes:
-            assert run_command(["config", "add", "board_manager.additional_urls", package_index], custom_env=env)
-        assert run_command(["update"], custom_env=env)
-
-        for d in cores_to_install:
-            assert run_command(["core", "install", d], custom_env=env)
-
-    # Create a sketch
-    sketch_name = "TestSketchForUpload"
-    sketch_path = Path(session_data_dir, sketch_name)
-    assert run_command(["sketch", "new", sketch_path], custom_env=env)
-
-    # Fake compilation, we just need the folder to exist
-    build_dir = generate_build_dir(sketch_path)
-    programmer_arg = ["-P", programmer] if programmer else []
-    port_arg = ["-p", upload_port] if upload_port else []
-    res = run_command(
-        ["upload"] + port_arg + programmer_arg + ["-b", fqbn, sketch_path, "--dry-run", "-v"], custom_env=env
-    )
-    assert res.ok
-
-    if isinstance(output, str):
-        out = output
-    else:
-        out = output[sys.platform]
-    expected_output = out.format(
-        data_dir=session_data_dir,
-        upload_port=upload_port,
-        build_dir=build_dir,
-        sketch_name=sketch_name,
-    ).replace("\\", "/")
-
-    expected_output in res.stdout.replace("\\", "/").replace("\r", "")

From 0856bc273ed629a5fe230f7c00aca09403934742 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 22 Nov 2022 07:31:50 -0800
Subject: [PATCH 005/606] Bump liskin/gh-problem-matcher-wrap from 1 to 2
 (#1988)

Bumps [liskin/gh-problem-matcher-wrap](https://github.com/liskin/gh-problem-matcher-wrap) from 1 to 2.
- [Release notes](https://github.com/liskin/gh-problem-matcher-wrap/releases)
- [Commits](https://github.com/liskin/gh-problem-matcher-wrap/compare/v1...v2)

---
updated-dependencies:
- dependency-name: liskin/gh-problem-matcher-wrap
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 .github/workflows/check-python-task.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/check-python-task.yml b/.github/workflows/check-python-task.yml
index c8fe4e35d4c..81762a78443 100644
--- a/.github/workflows/check-python-task.yml
+++ b/.github/workflows/check-python-task.yml
@@ -53,7 +53,7 @@ jobs:
           version: 3.x
 
       - name: Run flake8
-        uses: liskin/gh-problem-matcher-wrap@v1
+        uses: liskin/gh-problem-matcher-wrap@v2
         with:
           linters: flake8
           run: task python:lint

From b1dd623e684d3f46f5a092d34c731890af5901ae Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Tue, 22 Nov 2022 17:41:11 +0100
Subject: [PATCH 006/606] [skip-changelog] Upgrade x/text to 0.4.0 (#1987)

---
 .../go/golang.org/x/crypto/blowfish.dep.yml   |  6 +-
 .../go/golang.org/x/crypto/cast5.dep.yml      |  6 +-
 .../crypto/curve25519/internal/field.dep.yml  | 62 +++++++++++++++++
 .../go/golang.org/x/crypto/ed25519.dep.yml    |  6 +-
 .../x/crypto/internal/poly1305.dep.yml        | 63 +++++++++++++++++
 .../go/golang.org/x/crypto/openpgp.dep.yml    |  6 +-
 .../golang.org/x/crypto/openpgp/armor.dep.yml |  6 +-
 .../x/crypto/openpgp/elgamal.dep.yml          |  6 +-
 .../x/crypto/openpgp/errors.dep.yml           |  6 +-
 .../x/crypto/openpgp/packet.dep.yml           |  6 +-
 .../golang.org/x/crypto/openpgp/s2k.dep.yml   |  6 +-
 .licenses/go/golang.org/x/crypto/ssh.dep.yml  |  6 +-
 .../go/golang.org/x/crypto/ssh/agent.dep.yml  |  6 +-
 .../crypto/ssh/internal/bcrypt_pbkdf.dep.yml  |  6 +-
 .../x/crypto/ssh/knownhosts.dep.yml           |  6 +-
 .../golang.org/x/crypto/ssh/terminal.dep.yml  |  6 +-
 .licenses/go/golang.org/x/net/context.dep.yml |  6 +-
 .licenses/go/golang.org/x/net/http2.dep.yml   |  6 +-
 .../golang.org/x/net/internal/socks.dep.yml   |  6 +-
 .../x/net/internal/timeseries.dep.yml         |  6 +-
 .licenses/go/golang.org/x/net/proxy.dep.yml   |  6 +-
 .licenses/go/golang.org/x/net/trace.dep.yml   |  6 +-
 .../x/sys/internal/unsafeheader.dep.yml       |  6 +-
 .licenses/go/golang.org/x/sys/unix.dep.yml    |  6 +-
 .licenses/go/golang.org/x/term.dep.yml        | 68 +++++++++++++++++++
 .licenses/go/golang.org/x/text/runes.dep.yml  |  6 +-
 arduino/discovery/discovery_client/go.mod     |  6 +-
 arduino/discovery/discovery_client/go.sum     | 20 ++++--
 client_example/go.mod                         |  6 +-
 client_example/go.sum                         | 20 ++++--
 docsgen/go.mod                                |  9 +--
 docsgen/go.sum                                | 23 +++++--
 go.mod                                        | 11 +--
 go.sum                                        | 23 +++++--
 34 files changed, 339 insertions(+), 110 deletions(-)
 create mode 100644 .licenses/go/golang.org/x/crypto/curve25519/internal/field.dep.yml
 create mode 100644 .licenses/go/golang.org/x/crypto/internal/poly1305.dep.yml
 create mode 100644 .licenses/go/golang.org/x/term.dep.yml

diff --git a/.licenses/go/golang.org/x/crypto/blowfish.dep.yml b/.licenses/go/golang.org/x/crypto/blowfish.dep.yml
index 2267ebc9862..9e538424bf8 100644
--- a/.licenses/go/golang.org/x/crypto/blowfish.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/blowfish.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/blowfish
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
 homepage: https://pkg.go.dev/golang.org/x/crypto/blowfish
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/cast5.dep.yml b/.licenses/go/golang.org/x/crypto/cast5.dep.yml
index c3f55392eb7..6f63e0f6864 100644
--- a/.licenses/go/golang.org/x/crypto/cast5.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/cast5.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/cast5
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package cast5 implements CAST5, as defined in RFC 2144.
 homepage: https://pkg.go.dev/golang.org/x/crypto/cast5
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/curve25519/internal/field.dep.yml b/.licenses/go/golang.org/x/crypto/curve25519/internal/field.dep.yml
new file mode 100644
index 00000000000..8b5e8800c1a
--- /dev/null
+++ b/.licenses/go/golang.org/x/crypto/curve25519/internal/field.dep.yml
@@ -0,0 +1,62 @@
+---
+name: golang.org/x/crypto/curve25519/internal/field
+version: v0.0.0-20210921155107-089bfa567519
+type: go
+summary: Package field implements fast arithmetic modulo 2^255-19.
+homepage: https://pkg.go.dev/golang.org/x/crypto/curve25519/internal/field
+license: bsd-3-clause
+licenses:
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
+  text: |
+    Copyright (c) 2009 The Go Authors. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+       * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+       * Neither the name of Google Inc. nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
+  text: |
+    Additional IP Rights Grant (Patents)
+
+    "This implementation" means the copyrightable works distributed by
+    Google as part of the Go project.
+
+    Google hereby grants to You a perpetual, worldwide, non-exclusive,
+    no-charge, royalty-free, irrevocable (except as stated in this section)
+    patent license to make, have made, use, offer to sell, sell, import,
+    transfer and otherwise run, modify and propagate the contents of this
+    implementation of Go, where such license applies only to those patent
+    claims, both currently owned or controlled by Google and acquired in
+    the future, licensable by Google that are necessarily infringed by this
+    implementation of Go.  This grant does not include claims that would be
+    infringed only as a consequence of further modification of this
+    implementation.  If you or your agent or exclusive licensee institute or
+    order or agree to the institution of patent litigation against any
+    entity (including a cross-claim or counterclaim in a lawsuit) alleging
+    that this implementation of Go or any code incorporated within this
+    implementation of Go constitutes direct or contributory patent
+    infringement, or inducement of patent infringement, then any patent
+    rights granted to you under this License for this implementation of Go
+    shall terminate as of the date such litigation is filed.
+notices: []
diff --git a/.licenses/go/golang.org/x/crypto/ed25519.dep.yml b/.licenses/go/golang.org/x/crypto/ed25519.dep.yml
index 6fdaddfad70..a86485c236c 100644
--- a/.licenses/go/golang.org/x/crypto/ed25519.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/ed25519.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/ed25519
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package ed25519 implements the Ed25519 signature algorithm.
 homepage: https://pkg.go.dev/golang.org/x/crypto/ed25519
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/internal/poly1305.dep.yml b/.licenses/go/golang.org/x/crypto/internal/poly1305.dep.yml
new file mode 100644
index 00000000000..aa8eaea984a
--- /dev/null
+++ b/.licenses/go/golang.org/x/crypto/internal/poly1305.dep.yml
@@ -0,0 +1,63 @@
+---
+name: golang.org/x/crypto/internal/poly1305
+version: v0.0.0-20210921155107-089bfa567519
+type: go
+summary: Package poly1305 implements Poly1305 one-time message authentication code
+  as specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
+homepage: https://pkg.go.dev/golang.org/x/crypto/internal/poly1305
+license: bsd-3-clause
+licenses:
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
+  text: |
+    Copyright (c) 2009 The Go Authors. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+       * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+       * Neither the name of Google Inc. nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
+  text: |
+    Additional IP Rights Grant (Patents)
+
+    "This implementation" means the copyrightable works distributed by
+    Google as part of the Go project.
+
+    Google hereby grants to You a perpetual, worldwide, non-exclusive,
+    no-charge, royalty-free, irrevocable (except as stated in this section)
+    patent license to make, have made, use, offer to sell, sell, import,
+    transfer and otherwise run, modify and propagate the contents of this
+    implementation of Go, where such license applies only to those patent
+    claims, both currently owned or controlled by Google and acquired in
+    the future, licensable by Google that are necessarily infringed by this
+    implementation of Go.  This grant does not include claims that would be
+    infringed only as a consequence of further modification of this
+    implementation.  If you or your agent or exclusive licensee institute or
+    order or agree to the institution of patent litigation against any
+    entity (including a cross-claim or counterclaim in a lawsuit) alleging
+    that this implementation of Go or any code incorporated within this
+    implementation of Go constitutes direct or contributory patent
+    infringement, or inducement of patent infringement, then any patent
+    rights granted to you under this License for this implementation of Go
+    shall terminate as of the date such litigation is filed.
+notices: []
diff --git a/.licenses/go/golang.org/x/crypto/openpgp.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp.dep.yml
index e87b75bcc09..7641dc31e6b 100644
--- a/.licenses/go/golang.org/x/crypto/openpgp.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/openpgp.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/openpgp
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package openpgp implements high level operations on OpenPGP messages.
 homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml
index 0ea04215540..b068c02a359 100644
--- a/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/openpgp/armor.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/openpgp/armor
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package armor implements OpenPGP ASCII Armor, see RFC 4880.
 homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/armor
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml
index 5e68f331034..f1fae8532fd 100644
--- a/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/openpgp/elgamal.dep.yml
@@ -1,6 +1,6 @@
 ---
 name: golang.org/x/crypto/openpgp/elgamal
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package elgamal implements ElGamal encryption, suitable for OpenPGP, as specified
   in "A Public-Key Cryptosystem and a Signature Scheme Based on Discrete Logarithms,"
@@ -8,7 +8,7 @@ summary: Package elgamal implements ElGamal encryption, suitable for OpenPGP, as
 homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/elgamal
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -37,7 +37,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml
index b3c74e3ab65..afd2fffd0fb 100644
--- a/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/openpgp/errors.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/openpgp/errors
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package errors contains common error types for the OpenPGP packages.
 homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/errors
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml
index 7936abe48b2..ce944a0ebca 100644
--- a/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/openpgp/packet.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/crypto/openpgp/packet
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package packet implements parsing and serialization of OpenPGP packets, as
   specified in RFC 4880.
 homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/packet
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml b/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml
index b7cc610f021..a121c06961a 100644
--- a/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/openpgp/s2k.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/crypto/openpgp/s2k
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package s2k implements the various OpenPGP string-to-key transforms as specified
   in RFC 4800 section 3.7.1.
 homepage: https://pkg.go.dev/golang.org/x/crypto/openpgp/s2k
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/ssh.dep.yml b/.licenses/go/golang.org/x/crypto/ssh.dep.yml
index d41e0c2f492..72dcad98090 100644
--- a/.licenses/go/golang.org/x/crypto/ssh.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/ssh.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/ssh
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package ssh implements an SSH client and server.
 homepage: https://pkg.go.dev/golang.org/x/crypto/ssh
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml
index 6516072be33..53a4214f95c 100644
--- a/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/ssh/agent.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/crypto/ssh/agent
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package agent implements the ssh-agent protocol, and provides both a client
   and a server.
 homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/agent
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml
index aa7c1a386be..75a6e2ff8d8 100644
--- a/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package bcrypt_pbkdf implements bcrypt_pbkdf(3) from OpenBSD.
 homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml
index 3ae9e38ae37..d602d69345a 100644
--- a/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/ssh/knownhosts.dep.yml
@@ -1,6 +1,6 @@
 ---
 name: golang.org/x/crypto/ssh/knownhosts
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package knownhosts implements a parser for the OpenSSH known_hosts host key
   database, and provides utility functions for writing OpenSSH compliant known_hosts
@@ -8,7 +8,7 @@ summary: Package knownhosts implements a parser for the OpenSSH known_hosts host
 homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/knownhosts
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -37,7 +37,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml
index d23667f47ba..43a34ca6961 100644
--- a/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml
+++ b/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/crypto/ssh/terminal
-version: v0.0.0-20200622213623-75b288015ac9
+version: v0.0.0-20210921155107-089bfa567519
 type: go
 summary: Package terminal provides support functions for dealing with terminals, as
   commonly found on UNIX systems.
 homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/terminal
 license: bsd-3-clause
 licenses:
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/LICENSE
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20200622213623-75b288015ac9/PATENTS
+- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/net/context.dep.yml b/.licenses/go/golang.org/x/net/context.dep.yml
index 58f8090c845..0e0ccd0851b 100644
--- a/.licenses/go/golang.org/x/net/context.dep.yml
+++ b/.licenses/go/golang.org/x/net/context.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/net/context
-version: v0.0.0-20210505024714-0287a6fb4125
+version: v0.0.0-20220722155237-a158d28d115b
 type: go
 summary: Package context defines the Context type, which carries deadlines, cancelation
   signals, and other request-scoped values across API boundaries and between processes.
 homepage: https://pkg.go.dev/golang.org/x/net/context
 license: bsd-3-clause
 licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
+- sources: net@v0.0.0-20220722155237-a158d28d115b/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
+- sources: net@v0.0.0-20220722155237-a158d28d115b/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/net/http2.dep.yml b/.licenses/go/golang.org/x/net/http2.dep.yml
index 87cddaca12b..b05f1488aa2 100644
--- a/.licenses/go/golang.org/x/net/http2.dep.yml
+++ b/.licenses/go/golang.org/x/net/http2.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/net/http2
-version: v0.0.0-20210505024714-0287a6fb4125
+version: v0.0.0-20220722155237-a158d28d115b
 type: go
 summary: Package http2 implements the HTTP/2 protocol.
 homepage: https://pkg.go.dev/golang.org/x/net/http2
 license: bsd-3-clause
 licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
+- sources: net@v0.0.0-20220722155237-a158d28d115b/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
+- sources: net@v0.0.0-20220722155237-a158d28d115b/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/net/internal/socks.dep.yml b/.licenses/go/golang.org/x/net/internal/socks.dep.yml
index b58faea3fb3..08ee9854bf8 100644
--- a/.licenses/go/golang.org/x/net/internal/socks.dep.yml
+++ b/.licenses/go/golang.org/x/net/internal/socks.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/net/internal/socks
-version: v0.0.0-20210505024714-0287a6fb4125
+version: v0.0.0-20220722155237-a158d28d115b
 type: go
 summary: Package socks provides a SOCKS version 5 client implementation.
 homepage: https://pkg.go.dev/golang.org/x/net/internal/socks
 license: bsd-3-clause
 licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
+- sources: net@v0.0.0-20220722155237-a158d28d115b/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
+- sources: net@v0.0.0-20220722155237-a158d28d115b/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml b/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml
index 0bdebce9b44..d03ccbdab77 100644
--- a/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml
+++ b/.licenses/go/golang.org/x/net/internal/timeseries.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/net/internal/timeseries
-version: v0.0.0-20210505024714-0287a6fb4125
+version: v0.0.0-20220722155237-a158d28d115b
 type: go
 summary: Package timeseries implements a time series structure for stats collection.
 homepage: https://pkg.go.dev/golang.org/x/net/internal/timeseries
 license: bsd-3-clause
 licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
+- sources: net@v0.0.0-20220722155237-a158d28d115b/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
+- sources: net@v0.0.0-20220722155237-a158d28d115b/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/net/proxy.dep.yml b/.licenses/go/golang.org/x/net/proxy.dep.yml
index 734ebc7a125..58da7044890 100644
--- a/.licenses/go/golang.org/x/net/proxy.dep.yml
+++ b/.licenses/go/golang.org/x/net/proxy.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/net/proxy
-version: v0.0.0-20210505024714-0287a6fb4125
+version: v0.0.0-20220722155237-a158d28d115b
 type: go
 summary: Package proxy provides support for a variety of protocols to proxy network
   data.
 homepage: https://pkg.go.dev/golang.org/x/net/proxy
 license: bsd-3-clause
 licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
+- sources: net@v0.0.0-20220722155237-a158d28d115b/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
+- sources: net@v0.0.0-20220722155237-a158d28d115b/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/net/trace.dep.yml b/.licenses/go/golang.org/x/net/trace.dep.yml
index ac721338e23..5476928eee9 100644
--- a/.licenses/go/golang.org/x/net/trace.dep.yml
+++ b/.licenses/go/golang.org/x/net/trace.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/net/trace
-version: v0.0.0-20210505024714-0287a6fb4125
+version: v0.0.0-20220722155237-a158d28d115b
 type: go
 summary: Package trace implements tracing of requests and long-lived objects.
 homepage: https://pkg.go.dev/golang.org/x/net/trace
 license: bsd-3-clause
 licenses:
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/LICENSE
+- sources: net@v0.0.0-20220722155237-a158d28d115b/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: net@v0.0.0-20210505024714-0287a6fb4125/PATENTS
+- sources: net@v0.0.0-20220722155237-a158d28d115b/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/sys/internal/unsafeheader.dep.yml b/.licenses/go/golang.org/x/sys/internal/unsafeheader.dep.yml
index 043976e8d4c..3d45b0b7758 100644
--- a/.licenses/go/golang.org/x/sys/internal/unsafeheader.dep.yml
+++ b/.licenses/go/golang.org/x/sys/internal/unsafeheader.dep.yml
@@ -1,13 +1,13 @@
 ---
 name: golang.org/x/sys/internal/unsafeheader
-version: v0.0.0-20220520151302-bc2c85ada10a
+version: v0.0.0-20220722155257-8c9f86f7a55f
 type: go
 summary: Package unsafeheader contains header declarations for the Go runtime's slice
   and string implementations.
 homepage: https://pkg.go.dev/golang.org/x/sys/internal/unsafeheader
 license: bsd-3-clause
 licenses:
-- sources: sys@v0.0.0-20220520151302-bc2c85ada10a/LICENSE
+- sources: sys@v0.0.0-20220722155257-8c9f86f7a55f/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -36,7 +36,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: sys@v0.0.0-20220520151302-bc2c85ada10a/PATENTS
+- sources: sys@v0.0.0-20220722155257-8c9f86f7a55f/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/sys/unix.dep.yml b/.licenses/go/golang.org/x/sys/unix.dep.yml
index 0b125d7ada7..f5447473cbd 100644
--- a/.licenses/go/golang.org/x/sys/unix.dep.yml
+++ b/.licenses/go/golang.org/x/sys/unix.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/sys/unix
-version: v0.0.0-20220520151302-bc2c85ada10a
+version: v0.0.0-20220722155257-8c9f86f7a55f
 type: go
 summary: Package unix contains an interface to the low-level operating system primitives.
 homepage: https://pkg.go.dev/golang.org/x/sys/unix
 license: bsd-3-clause
 licenses:
-- sources: sys@v0.0.0-20220520151302-bc2c85ada10a/LICENSE
+- sources: sys@v0.0.0-20220722155257-8c9f86f7a55f/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: sys@v0.0.0-20220520151302-bc2c85ada10a/PATENTS
+- sources: sys@v0.0.0-20220722155257-8c9f86f7a55f/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/.licenses/go/golang.org/x/term.dep.yml b/.licenses/go/golang.org/x/term.dep.yml
new file mode 100644
index 00000000000..41c38f43250
--- /dev/null
+++ b/.licenses/go/golang.org/x/term.dep.yml
@@ -0,0 +1,68 @@
+---
+name: golang.org/x/term
+version: v0.0.0-20210927222741-03fcf44c2211
+type: go
+summary: Package term provides support functions for dealing with terminals, as commonly
+  found on UNIX systems.
+homepage: https://pkg.go.dev/golang.org/x/term
+license: bsd-3-clause
+licenses:
+- sources: LICENSE
+  text: |
+    Copyright (c) 2009 The Go Authors. All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+
+       * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+       * Neither the name of Google Inc. nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- sources: PATENTS
+  text: |
+    Additional IP Rights Grant (Patents)
+
+    "This implementation" means the copyrightable works distributed by
+    Google as part of the Go project.
+
+    Google hereby grants to You a perpetual, worldwide, non-exclusive,
+    no-charge, royalty-free, irrevocable (except as stated in this section)
+    patent license to make, have made, use, offer to sell, sell, import,
+    transfer and otherwise run, modify and propagate the contents of this
+    implementation of Go, where such license applies only to those patent
+    claims, both currently owned or controlled by Google and acquired in
+    the future, licensable by Google that are necessarily infringed by this
+    implementation of Go.  This grant does not include claims that would be
+    infringed only as a consequence of further modification of this
+    implementation.  If you or your agent or exclusive licensee institute or
+    order or agree to the institution of patent litigation against any
+    entity (including a cross-claim or counterclaim in a lawsuit) alleging
+    that this implementation of Go or any code incorporated within this
+    implementation of Go constitutes direct or contributory patent
+    infringement, or inducement of patent infringement, then any patent
+    rights granted to you under this License for this implementation of Go
+    shall terminate as of the date such litigation is filed.
+notices:
+- sources: AUTHORS
+  text: |-
+    # This source code refers to The Go Authors for copyright purposes.
+    # The master list of authors is in the main Go distribution,
+    # visible at http://tip.golang.org/AUTHORS.
diff --git a/.licenses/go/golang.org/x/text/runes.dep.yml b/.licenses/go/golang.org/x/text/runes.dep.yml
index 22972c51d3c..1db7cfa0b9e 100644
--- a/.licenses/go/golang.org/x/text/runes.dep.yml
+++ b/.licenses/go/golang.org/x/text/runes.dep.yml
@@ -1,12 +1,12 @@
 ---
 name: golang.org/x/text/runes
-version: v0.3.6
+version: v0.4.0
 type: go
 summary: Package runes provide transforms for UTF-8 encoded text.
 homepage: https://pkg.go.dev/golang.org/x/text/runes
 license: bsd-3-clause
 licenses:
-- sources: text@v0.3.6/LICENSE
+- sources: text@v0.4.0/LICENSE
   text: |
     Copyright (c) 2009 The Go Authors. All rights reserved.
 
@@ -35,7 +35,7 @@ licenses:
     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: text@v0.3.6/PATENTS
+- sources: text@v0.4.0/PATENTS
   text: |
     Additional IP Rights Grant (Patents)
 
diff --git a/arduino/discovery/discovery_client/go.mod b/arduino/discovery/discovery_client/go.mod
index e411cbbec2e..6d1c6b6a9f4 100644
--- a/arduino/discovery/discovery_client/go.mod
+++ b/arduino/discovery/discovery_client/go.mod
@@ -21,9 +21,9 @@ require (
 	github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
-	golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect
-	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
-	golang.org/x/text v0.3.6 // indirect
+	golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
+	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
+	golang.org/x/text v0.4.0 // indirect
 	google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
 	google.golang.org/grpc v1.38.0 // indirect
 	google.golang.org/protobuf v1.26.0 // indirect
diff --git a/arduino/discovery/discovery_client/go.sum b/arduino/discovery/discovery_client/go.sum
index ee95d54ba27..6ad8d7bdc4d 100644
--- a/arduino/discovery/discovery_client/go.sum
+++ b/arduino/discovery/discovery_client/go.sum
@@ -303,6 +303,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
 go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII=
 go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
@@ -331,6 +332,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -366,6 +368,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -403,8 +406,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 h1:Ugb8sMTWuWRC3+sz5WeN/4kejDx9BvIwnPUiJBjJE+8=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -428,6 +431,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -471,13 +475,15 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -485,8 +491,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -542,6 +549,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/client_example/go.mod b/client_example/go.mod
index b00743c6f6f..a19f2ac6ab3 100644
--- a/client_example/go.mod
+++ b/client_example/go.mod
@@ -11,9 +11,9 @@ require (
 
 require (
 	github.com/golang/protobuf v1.5.2 // indirect
-	golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect
-	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
-	golang.org/x/text v0.3.6 // indirect
+	golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
+	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
+	golang.org/x/text v0.4.0 // indirect
 	google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
 	google.golang.org/protobuf v1.26.0 // indirect
 )
diff --git a/client_example/go.sum b/client_example/go.sum
index 3a56561f90d..cd793e04060 100644
--- a/client_example/go.sum
+++ b/client_example/go.sum
@@ -285,6 +285,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
 go.bug.st/downloader/v2 v2.1.1/go.mod h1:VZW2V1iGKV8rJL2ZEGIDzzBeKowYv34AedJz13RzVII=
 go.bug.st/relaxed-semver v0.9.0/go.mod h1:ug0/W/RPYUjliE70Ghxg77RDHmPxqpo7SHV16ijss7Q=
@@ -313,6 +314,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -348,6 +350,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -385,8 +388,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 h1:Ugb8sMTWuWRC3+sz5WeN/4kejDx9BvIwnPUiJBjJE+8=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -410,6 +413,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -453,13 +457,15 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -467,8 +473,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -524,6 +531,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/docsgen/go.mod b/docsgen/go.mod
index c30cbbe4f23..4c91e2749f7 100644
--- a/docsgen/go.mod
+++ b/docsgen/go.mod
@@ -65,10 +65,11 @@ require (
 	go.bug.st/downloader/v2 v2.1.1 // indirect
 	go.bug.st/relaxed-semver v0.9.0 // indirect
 	go.bug.st/serial v1.3.2 // indirect
-	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
-	golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect
-	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
-	golang.org/x/text v0.3.6 // indirect
+	golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
+	golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
+	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
+	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
+	golang.org/x/text v0.4.0 // indirect
 	google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
 	google.golang.org/grpc v1.38.0 // indirect
 	google.golang.org/protobuf v1.26.0 // indirect
diff --git a/docsgen/go.sum b/docsgen/go.sum
index 7e2e1e0cdf7..42a082e6c5f 100644
--- a/docsgen/go.sum
+++ b/docsgen/go.sum
@@ -350,6 +350,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.bug.st/cleanup v1.0.0 h1:XVj1HZxkBXeq3gMT7ijWUpHyIC1j8XAoNSyQ06CskgA=
 go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
 go.bug.st/downloader/v2 v2.1.1 h1:nyqbUizo3E2IxCCm4YFac4FtSqqFpqWP+Aae5GCMuw4=
@@ -381,8 +382,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -418,6 +420,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -455,8 +458,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 h1:Ugb8sMTWuWRC3+sz5WeN/4kejDx9BvIwnPUiJBjJE+8=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -480,6 +483,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -523,13 +527,16 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -537,8 +544,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -594,6 +602,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/go.mod b/go.mod
index c812dd60b11..b4532e290c8 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,6 @@ require (
 	github.com/marcinbor85/gohex v0.0.0-20210308104911-55fb1c624d84
 	github.com/mattn/go-colorable v0.1.8
 	github.com/mattn/go-isatty v0.0.14
-	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/pkg/errors v0.9.1
 	github.com/pmylund/sortutil v0.0.0-20120526081524-abeda66eb583
 	github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
@@ -39,9 +38,8 @@ require (
 	go.bug.st/downloader/v2 v2.1.1
 	go.bug.st/relaxed-semver v0.9.0
 	go.bug.st/serial v1.3.2
-	golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
-	golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 // indirect
-	golang.org/x/text v0.3.6
+	golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
+	golang.org/x/text v0.4.0
 	google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
 	google.golang.org/grpc v1.38.0
 	google.golang.org/protobuf v1.26.0
@@ -73,6 +71,7 @@ require (
 	github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
 	github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
 	github.com/magiconair/properties v1.8.5 // indirect
+	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/mapstructure v1.4.1 // indirect
 	github.com/pelletier/go-toml v1.9.3 // indirect
@@ -86,7 +85,9 @@ require (
 	github.com/src-d/gcfg v1.4.0 // indirect
 	github.com/subosito/gotenv v1.2.0 // indirect
 	github.com/xanzy/ssh-agent v0.2.1 // indirect
-	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
+	golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
+	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
+	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	gopkg.in/ini.v1 v1.62.0 // indirect
 	gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
diff --git a/go.sum b/go.sum
index 62309295405..572bdc4dc65 100644
--- a/go.sum
+++ b/go.sum
@@ -353,6 +353,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.bug.st/cleanup v1.0.0 h1:XVj1HZxkBXeq3gMT7ijWUpHyIC1j8XAoNSyQ06CskgA=
 go.bug.st/cleanup v1.0.0/go.mod h1:EqVmTg2IBk4znLbPD28xne3abjsJftMdqqJEjhn70bk=
 go.bug.st/downloader/v2 v2.1.1 h1:nyqbUizo3E2IxCCm4YFac4FtSqqFpqWP+Aae5GCMuw4=
@@ -385,8 +386,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -422,6 +424,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -459,8 +462,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125 h1:Ugb8sMTWuWRC3+sz5WeN/4kejDx9BvIwnPUiJBjJE+8=
-golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -484,6 +487,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -527,13 +531,16 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -541,8 +548,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -598,6 +606,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

From d86bc138c186db94cc76a488b02682eb8a50d739 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Thu, 24 Nov 2022 11:47:35 +0100
Subject: [PATCH 007/606] [skip-changelog] Small change in upload message
 (#1991)

* Renamed variables

* Do not print full Port structure on messages

This produce a more clean output and stabilizes tests.
---
 commands/upload/upload.go                     |  26 ++---
 .../upload_mock/upload_mock_test.go           | 108 +++++++++---------
 2 files changed, 67 insertions(+), 67 deletions(-)

diff --git a/commands/upload/upload.go b/commands/upload/upload.go
index 87488a84337..95631369991 100644
--- a/commands/upload/upload.go
+++ b/commands/upload/upload.go
@@ -396,10 +396,10 @@ func runProgramAction(pme *packagemanager.Explorer,
 		}
 
 		cb := &serialutils.ResetProgressCallbacks{
-			TouchingPort: func(port string) {
-				logrus.WithField("phase", "board reset").Infof("Performing 1200-bps touch reset on serial port %s", port)
+			TouchingPort: func(portAddress string) {
+				logrus.WithField("phase", "board reset").Infof("Performing 1200-bps touch reset on serial port %s", portAddress)
 				if verbose {
-					outStream.Write([]byte(fmt.Sprintln(tr("Performing 1200-bps touch reset on serial port %s", port))))
+					outStream.Write([]byte(fmt.Sprintln(tr("Performing 1200-bps touch reset on serial port %s", portAddress))))
 				}
 			},
 			WaitingForNewSerial: func() {
@@ -408,17 +408,17 @@ func runProgramAction(pme *packagemanager.Explorer,
 					outStream.Write([]byte(fmt.Sprintln(tr("Waiting for upload port..."))))
 				}
 			},
-			BootloaderPortFound: func(port string) {
-				if port != "" {
-					logrus.WithField("phase", "board reset").Infof("Upload port found on %s", port)
+			BootloaderPortFound: func(portAddress string) {
+				if portAddress != "" {
+					logrus.WithField("phase", "board reset").Infof("Upload port found on %s", portAddress)
 				} else {
-					logrus.WithField("phase", "board reset").Infof("No upload port found, using %s as fallback", actualPort)
+					logrus.WithField("phase", "board reset").Infof("No upload port found, using %s as fallback", actualPort.Address)
 				}
 				if verbose {
-					if port != "" {
-						outStream.Write([]byte(fmt.Sprintln(tr("Upload port found on %s", port))))
+					if portAddress != "" {
+						outStream.Write([]byte(fmt.Sprintln(tr("Upload port found on %s", portAddress))))
 					} else {
-						outStream.Write([]byte(fmt.Sprintln(tr("No upload port found, using %s as fallback", actualPort))))
+						outStream.Write([]byte(fmt.Sprintln(tr("No upload port found, using %s as fallback", actualPort.Address))))
 					}
 				}
 			},
@@ -427,11 +427,11 @@ func runProgramAction(pme *packagemanager.Explorer,
 			},
 		}
 
-		if newPort, err := serialutils.Reset(portToTouch, wait, cb, dryRun); err != nil {
+		if newPortAddress, err := serialutils.Reset(portToTouch, wait, cb, dryRun); err != nil {
 			outStream.Write([]byte(fmt.Sprintln(tr("Cannot perform port reset: %s", err))))
 		} else {
-			if newPort != "" {
-				actualPort.Address = newPort
+			if newPortAddress != "" {
+				actualPort.Address = newPortAddress
 			}
 		}
 	}
diff --git a/internal/integrationtest/upload_mock/upload_mock_test.go b/internal/integrationtest/upload_mock/upload_mock_test.go
index cf6613805ef..db304ad8aec 100644
--- a/internal/integrationtest/upload_mock/upload_mock_test.go
+++ b/internal/integrationtest/upload_mock/upload_mock_test.go
@@ -277,9 +277,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -287,9 +287,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -297,9 +297,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -307,9 +307,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -V -patmega32u4 -cavr109 \"-P/dev/ttyACM0\" -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -317,9 +317,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -327,9 +327,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -337,9 +337,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -347,9 +347,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude\" \"-C{data_dir}/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf\" -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -D \"-Uflash:w:{build_dir}/{sketch_name}.ino.hex:i\"\n",
 			},
 		},
 		{
@@ -377,9 +377,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -397,9 +397,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -417,9 +417,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -437,9 +437,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -I -U true -i -e -w \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -457,9 +457,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -477,9 +477,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -497,9 +497,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -517,9 +517,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -537,9 +537,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{
@@ -557,9 +557,9 @@ func TestUploadSketch(t *testing.T) {
 			UploadPort: "/dev/ttyACM0",
 			Programmer: "",
 			Output: map[string]string{
-				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\" protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
-				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using address:\"/dev/ttyACM0\"  protocol:\"serial\" as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"darwin": "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"linux":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
+				"win32":  "Performing 1200-bps touch reset on serial port /dev/ttyACM0\nWaiting for upload port...\nNo upload port found, using /dev/ttyACM0 as fallback\n\"{data_dir}/packages/arduino/tools/bossac/1.7.0-arduino3/bossac.exe\" -i -d --port=ttyACM0 -U true -i -e -w -v \"{build_dir}/{sketch_name}.ino.bin\" -R\n",
 			},
 		},
 		{

From c570916273a5f9304907fddba9a226245b622e32 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Tue, 29 Nov 2022 12:39:00 +0100
Subject: [PATCH 008/606] [breaking] Fixed detection of double-install using
 `lib install` with `--git-url` or `--zip-path` (#1983)

* Remove useless logging

The errors are already reported upstream via returned `err` value

* librariesmanager.InstallPrerequisiteCheck signature change

It now accepts library name and version as single arguments since we are
going to use this function also for libraries not present in the index.

* Added integration test

* Fixed `lib install --git-url` pre-install checks

Now it performs all the needed checks to avoid multiple installations.

* Added test for double install with -.zip-path flag

* Fixed `lib install --zip-path` pre-install checks

Now it performs all the needed checks to avoid multiple installations

* Simplified loop in LibraryInstall function

* Factored some of the checks in LibrariesManager.InstallPrerequisiteCheck

They were duplicated and spread around all the library install
functions.

* Refactored LibrariesManager.getLibrariesDir function

This helped to find out 2 places where the `installDir` was unnecessary.

* Factored all duplicated code for importing a library from a directory

* Updated docs

* Fixed integration test

The installation folder is now taken from the `name` field in `library.properties`.

* Update docs/UPGRADING.md

Co-authored-by: Umberto Baldi <34278123+umbynos@users.noreply.github.com>

Co-authored-by: Umberto Baldi <34278123+umbynos@users.noreply.github.com>
---
 arduino/libraries/librariesmanager/install.go | 245 ++++++++----------
 .../librariesmanager/librariesmanager.go      |  14 +-
 commands/lib/install.go                       |  75 ++----
 docs/UPGRADING.md                             |  23 ++
 .../integrationtest/compile_1/compile_test.go |   2 +-
 internal/integrationtest/lib/lib_test.go      |  60 +++++
 6 files changed, 230 insertions(+), 189 deletions(-)

diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go
index 5baa17e3d94..5a3db0ff646 100644
--- a/arduino/libraries/librariesmanager/install.go
+++ b/arduino/libraries/librariesmanager/install.go
@@ -29,49 +29,49 @@ import (
 	"github.com/arduino/arduino-cli/arduino/utils"
 	paths "github.com/arduino/go-paths-helper"
 	"github.com/codeclysm/extract/v3"
-	"github.com/sirupsen/logrus"
+	semver "go.bug.st/relaxed-semver"
 	"gopkg.in/src-d/go-git.v4"
 	"gopkg.in/src-d/go-git.v4/plumbing"
 )
 
-type alreadyInstalledError struct{}
+// LibraryInstallPlan contains the main information required to perform a library
+// install, like the path where the library should be installed and the library
+// that is going to be replaced by the new one.
+// This is the result of a call to InstallPrerequisiteCheck.
+type LibraryInstallPlan struct {
+	// Name of the library to install
+	Name string
 
-func (e *alreadyInstalledError) Error() string {
-	return tr("library already installed")
-}
+	// Version of the library to install
+	Version *semver.Version
 
-var (
-	// ErrAlreadyInstalled is returned when a library is already installed and task
-	// cannot proceed.
-	ErrAlreadyInstalled = &alreadyInstalledError{}
-)
+	// TargetPath is the path where the library should be installed.
+	TargetPath *paths.Path
+
+	// ReplacedLib is the library that is going to be replaced by the new one.
+	ReplacedLib *libraries.Library
+
+	// UpToDate is true if the library to install has the same version of the library we are going to replace.
+	UpToDate bool
+}
 
 // InstallPrerequisiteCheck performs prequisite checks to install a library. It returns the
 // install path, where the library should be installed and the possible library that is already
 // installed on the same folder and it's going to be replaced by the new one.
-func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) {
-	installDir := lm.getLibrariesDir(installLocation)
-	if installDir == nil {
-		if installLocation == libraries.User {
-			return nil, nil, fmt.Errorf(tr("User directory not set"))
-		}
-		return nil, nil, fmt.Errorf(tr("Builtin libraries directory not set"))
+func (lm *LibrariesManager) InstallPrerequisiteCheck(name string, version *semver.Version, installLocation libraries.LibraryLocation) (*LibraryInstallPlan, error) {
+	installDir, err := lm.getLibrariesDir(installLocation)
+	if err != nil {
+		return nil, err
 	}
 
-	name := indexLibrary.Library.Name
 	libs := lm.FindByReference(&librariesindex.Reference{Name: name}, installLocation)
-	for _, lib := range libs {
-		if lib.Version != nil && lib.Version.Equal(indexLibrary.Version) {
-			return lib.InstallDir, nil, ErrAlreadyInstalled
-		}
-	}
 
 	if len(libs) > 1 {
 		libsDir := paths.NewPathList()
 		for _, lib := range libs {
 			libsDir.Add(lib.InstallDir)
 		}
-		return nil, nil, &arduino.MultipleLibraryInstallDetected{
+		return nil, &arduino.MultipleLibraryInstallDetected{
 			LibName: name,
 			LibsDir: libsDir,
 			Message: tr("Automatic library install can't be performed in this case, please manually remove all duplicates and retry."),
@@ -79,22 +79,71 @@ func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesinde
 	}
 
 	var replaced *libraries.Library
+	var upToDate bool
 	if len(libs) == 1 {
-		replaced = libs[0]
+		lib := libs[0]
+		replaced = lib
+		upToDate = lib.Version != nil && lib.Version.Equal(version)
 	}
 
-	libPath := installDir.Join(utils.SanitizeName(indexLibrary.Library.Name))
-	if replaced != nil && replaced.InstallDir.EquivalentTo(libPath) {
-		return libPath, replaced, nil
-	} else if libPath.IsDir() {
-		return nil, nil, fmt.Errorf(tr("destination dir %s already exists, cannot install"), libPath)
+	libPath := installDir.Join(utils.SanitizeName(name))
+	if libPath.IsDir() {
+		if replaced == nil || !replaced.InstallDir.EquivalentTo(libPath) {
+			return nil, fmt.Errorf(tr("destination dir %s already exists, cannot install"), libPath)
+		}
 	}
-	return libPath, replaced, nil
+
+	return &LibraryInstallPlan{
+		Name:        name,
+		Version:     version,
+		TargetPath:  libPath,
+		ReplacedLib: replaced,
+		UpToDate:    upToDate,
+	}, nil
 }
 
 // Install installs a library on the specified path.
-func (lm *LibrariesManager) Install(indexLibrary *librariesindex.Release, libPath *paths.Path) error {
-	return indexLibrary.Resource.Install(lm.DownloadsDir, libPath.Parent(), libPath)
+func (lm *LibrariesManager) Install(indexLibrary *librariesindex.Release, installPath *paths.Path) error {
+	return indexLibrary.Resource.Install(lm.DownloadsDir, installPath.Parent(), installPath)
+}
+
+// importLibraryFromDirectory installs a library by copying it from the given directory.
+func (lm *LibrariesManager) importLibraryFromDirectory(libPath *paths.Path, overwrite bool) error {
+	// Check if the library is valid and load metatada
+	if err := validateLibrary(libPath); err != nil {
+		return err
+	}
+	library, err := libraries.Load(libPath, libraries.User)
+	if err != nil {
+		return err
+	}
+
+	// Check if the library is already installed and determine install path
+	installPlan, err := lm.InstallPrerequisiteCheck(library.Name, library.Version, libraries.User)
+	if err != nil {
+		return err
+	}
+
+	if installPlan.UpToDate {
+		if !overwrite {
+			return fmt.Errorf(tr("library %s already installed"), installPlan.Name)
+		}
+	}
+	if installPlan.ReplacedLib != nil {
+		if !overwrite {
+			return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", installPlan.Name, installPlan.ReplacedLib))
+		}
+		if err := lm.Uninstall(installPlan.ReplacedLib); err != nil {
+			return err
+		}
+	}
+	if installPlan.TargetPath.Exist() {
+		return fmt.Errorf("%s: %s", tr("destination directory already exists"), installPlan.TargetPath)
+	}
+	if err := libPath.CopyDirTo(installPlan.TargetPath); err != nil {
+		return fmt.Errorf("%s: %w", tr("copying library to destination directory:"), err)
+	}
+	return nil
 }
 
 // Uninstall removes a Library
@@ -103,7 +152,7 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error {
 		return fmt.Errorf(tr("install directory not set"))
 	}
 	if err := lib.InstallDir.RemoveAll(); err != nil {
-		return fmt.Errorf(tr("removing lib directory: %s"), err)
+		return fmt.Errorf(tr("removing library directory: %s"), err)
 	}
 
 	alternatives := lm.Libraries[lib.Name]
@@ -113,20 +162,15 @@ func (lm *LibrariesManager) Uninstall(lib *libraries.Library) error {
 }
 
 // InstallZipLib installs a Zip library on the specified path.
-func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath string, overwrite bool) error {
-	libsDir := lm.getLibrariesDir(libraries.User)
-	if libsDir == nil {
-		return fmt.Errorf(tr("User directory not set"))
-	}
-
-	tmpDir, err := paths.MkTempDir(paths.TempDir().String(), "arduino-cli-lib-")
+func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *paths.Path, overwrite bool) error {
+	// Clone library in a temporary directory
+	tmpDir, err := paths.MkTempDir("", "")
 	if err != nil {
 		return err
 	}
-	// Deletes temp dir used to extract archive when finished
 	defer tmpDir.RemoveAll()
 
-	file, err := os.Open(archivePath)
+	file, err := archivePath.Open()
 	if err != nil {
 		return err
 	}
@@ -138,58 +182,21 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath strin
 		return fmt.Errorf(tr("extracting archive: %w"), err)
 	}
 
-	paths, err := tmpDir.ReadDir()
+	libRootFiles, err := tmpDir.ReadDir()
 	if err != nil {
 		return err
 	}
-
-	// Ignores metadata from Mac OS X
-	paths.FilterOutPrefix("__MACOSX")
-
-	if len(paths) > 1 {
+	libRootFiles.FilterOutPrefix("__MACOSX") // Ignores metadata from Mac OS X
+	if len(libRootFiles) > 1 {
 		return fmt.Errorf(tr("archive is not valid: multiple files found in zip file top level"))
 	}
-
-	extractionPath := paths[0]
-	libraryName := extractionPath.Base()
-
-	if err := validateLibrary(extractionPath); err != nil {
-		return err
-	}
-
-	installPath := libsDir.Join(libraryName)
-
-	if err := libsDir.MkdirAll(); err != nil {
-		return err
-	}
-	defer func() {
-		// Clean up install dir if installation failed
-		files, err := installPath.ReadDir()
-		if err == nil && len(files) == 0 {
-			installPath.RemoveAll()
-		}
-	}()
-
-	// Delete library folder if already installed
-	if installPath.IsDir() {
-		if !overwrite {
-			return fmt.Errorf(tr("library %s already installed"), libraryName)
-		}
-		logrus.
-			WithField("library name", libraryName).
-			WithField("install path", installPath).
-			Trace("Deleting library")
-		installPath.RemoveAll()
+	if len(libRootFiles) == 0 {
+		return fmt.Errorf(tr("archive is not valid: no files found in zip file top level"))
 	}
+	tmpInstallPath := libRootFiles[0]
 
-	logrus.
-		WithField("library name", libraryName).
-		WithField("install path", installPath).
-		WithField("zip file", archivePath).
-		Trace("Installing library")
-
-	// Copy extracted library in the destination directory
-	if err := extractionPath.CopyDirTo(installPath); err != nil {
+	// Install extracted library in the destination directory
+	if err := lm.importLibraryFromDirectory(tmpInstallPath, overwrite); err != nil {
 		return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err)
 	}
 
@@ -198,84 +205,50 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath strin
 
 // InstallGitLib installs a library hosted on a git repository on the specified path.
 func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
-	installDir := lm.getLibrariesDir(libraries.User)
-	if installDir == nil {
-		return fmt.Errorf(tr("User directory not set"))
-	}
-
-	libraryName, ref, err := parseGitURL(gitURL)
+	gitLibraryName, ref, err := parseGitURL(gitURL)
 	if err != nil {
-		logrus.
-			WithError(err).
-			Warn("Parsing git URL")
 		return err
 	}
 
-	// Deletes libraries folder if already installed
-	installPath := installDir.Join(libraryName)
-	if installPath.IsDir() {
-		if !overwrite {
-			return fmt.Errorf(tr("library %s already installed"), libraryName)
-		}
-		logrus.
-			WithField("library name", libraryName).
-			WithField("install path", installPath).
-			Trace("Deleting library")
-		installPath.RemoveAll()
-	}
-	if installPath.Exist() {
-		return fmt.Errorf(tr("could not create directory %s: a file with the same name exists!", installPath))
+	// Clone library in a temporary directory
+	tmp, err := paths.MkTempDir("", "")
+	if err != nil {
+		return err
 	}
-
-	logrus.
-		WithField("library name", libraryName).
-		WithField("install path", installPath).
-		WithField("git url", gitURL).
-		Trace("Installing library")
+	defer tmp.RemoveAll()
+	tmpInstallPath := tmp.Join(gitLibraryName)
 
 	depth := 1
 	if ref != "" {
 		depth = 0
 	}
-	repo, err := git.PlainClone(installPath.String(), false, &git.CloneOptions{
+	repo, err := git.PlainClone(tmpInstallPath.String(), false, &git.CloneOptions{
 		URL:      gitURL,
 		Depth:    depth,
 		Progress: os.Stdout,
 	})
 	if err != nil {
-		logrus.
-			WithError(err).
-			Warn("Cloning git repository")
 		return err
 	}
 
 	if ref != "" {
 		if h, err := repo.ResolveRevision(ref); err != nil {
-			logrus.
-				WithError(err).
-				Warnf("Resolving revision %s", ref)
 			return err
 		} else if w, err := repo.Worktree(); err != nil {
-			logrus.
-				WithError(err).
-				Warn("Finding worktree")
 			return err
 		} else if err := w.Checkout(&git.CheckoutOptions{Hash: plumbing.NewHash(h.String())}); err != nil {
-			logrus.
-				WithError(err).
-				Warnf("Checking out %s", h)
 			return err
 		}
 	}
 
-	if err := validateLibrary(installPath); err != nil {
-		// Clean up installation directory since this is not a valid library
-		installPath.RemoveAll()
-		return err
+	// We don't want the installed library to be a git repository thus we delete this folder
+	tmpInstallPath.Join(".git").RemoveAll()
+
+	// Install extracted library in the destination directory
+	if err := lm.importLibraryFromDirectory(tmpInstallPath, overwrite); err != nil {
+		return fmt.Errorf(tr("moving extracted archive to destination dir: %s"), err)
 	}
 
-	// We don't want the installed library to be a git repository thus we delete this folder
-	installPath.Join(".git").RemoveAll()
 	return nil
 }
 
diff --git a/arduino/libraries/librariesmanager/librariesmanager.go b/arduino/libraries/librariesmanager/librariesmanager.go
index 9291db64117..30dbf69d644 100644
--- a/arduino/libraries/librariesmanager/librariesmanager.go
+++ b/arduino/libraries/librariesmanager/librariesmanager.go
@@ -16,6 +16,7 @@
 package librariesmanager
 
 import (
+	"errors"
 	"fmt"
 	"os"
 
@@ -140,13 +141,20 @@ func (lm *LibrariesManager) RescanLibraries() []*status.Status {
 	return statuses
 }
 
-func (lm *LibrariesManager) getLibrariesDir(installLocation libraries.LibraryLocation) *paths.Path {
+func (lm *LibrariesManager) getLibrariesDir(installLocation libraries.LibraryLocation) (*paths.Path, error) {
 	for _, dir := range lm.LibrariesDir {
 		if dir.Location == installLocation {
-			return dir.Path
+			return dir.Path, nil
 		}
 	}
-	return nil
+	switch installLocation {
+	case libraries.User:
+		return nil, errors.New(tr("user directory not set"))
+	case libraries.IDEBuiltIn:
+		return nil, errors.New(tr("built-in libraries directory not set"))
+	default:
+		return nil, fmt.Errorf("libraries directory not set: %s", installLocation.String())
+	}
 }
 
 // LoadLibrariesFromDir loads all libraries in the given directory. Returns
diff --git a/commands/lib/install.go b/commands/lib/install.go
index 0a82c9d074d..f76d77a06d4 100644
--- a/commands/lib/install.go
+++ b/commands/lib/install.go
@@ -26,6 +26,7 @@ import (
 	"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
 	"github.com/arduino/arduino-cli/commands"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
+	"github.com/arduino/go-paths-helper"
 	"github.com/sirupsen/logrus"
 )
 
@@ -67,7 +68,7 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa
 	}
 
 	// Find the libReleasesToInstall to install
-	libReleasesToInstall := []*librariesindex.Release{}
+	libReleasesToInstall := map[*librariesindex.Release]*librariesmanager.LibraryInstallPlan{}
 	for _, lib := range toInstall {
 		libRelease, err := findLibraryIndexRelease(lm, &rpc.LibraryInstallRequest{
 			Name:    lib.Name,
@@ -76,79 +77,55 @@ func LibraryInstall(ctx context.Context, req *rpc.LibraryInstallRequest, downloa
 		if err != nil {
 			return err
 		}
-		libReleasesToInstall = append(libReleasesToInstall, libRelease)
-	}
 
-	// Check if any of the libraries to install is already installed and remove it from the list
-	j := 0
-	for i, libRelease := range libReleasesToInstall {
-		_, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease, installLocation)
-		if errors.Is(err, librariesmanager.ErrAlreadyInstalled) {
-			taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true})
-		} else if err != nil {
+		installTask, err := lm.InstallPrerequisiteCheck(libRelease.Library.Name, libRelease.Version, installLocation)
+		if err != nil {
 			return err
-		} else {
-			libReleasesToInstall[j] = libReleasesToInstall[i]
-			j++
 		}
+		if installTask.UpToDate {
+			taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true})
+			continue
+		}
+
 		if req.GetNoOverwrite() {
-			if libReplaced != nil {
-				return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", libRelease, libReplaced))
+			if installTask.ReplacedLib != nil {
+				return fmt.Errorf(tr("Library %[1]s is already installed, but with a different version: %[2]s", libRelease, installTask.ReplacedLib))
 			}
 		}
+		libReleasesToInstall[libRelease] = installTask
 	}
-	libReleasesToInstall = libReleasesToInstall[:j]
 
-	didInstall := false
-	for _, libRelease := range libReleasesToInstall {
+	for libRelease, installTask := range libReleasesToInstall {
 		if err := downloadLibrary(lm, libRelease, downloadCB, taskCB); err != nil {
 			return err
 		}
-
-		if err := installLibrary(lm, libRelease, installLocation, taskCB); err != nil {
-			if errors.Is(err, librariesmanager.ErrAlreadyInstalled) {
-				continue
-			} else {
-				return err
-			}
+		if err := installLibrary(lm, libRelease, installTask, taskCB); err != nil {
+			return err
 		}
-		didInstall = true
 	}
 
-	if didInstall {
-		if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil {
-			return err
-		}
+	if err := commands.Init(&rpc.InitRequest{Instance: req.Instance}, nil); err != nil {
+		return err
 	}
 
 	return nil
 }
 
-func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *librariesindex.Release, installLocation libraries.LibraryLocation, taskCB rpc.TaskProgressCB) error {
+func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *librariesindex.Release, installTask *librariesmanager.LibraryInstallPlan, taskCB rpc.TaskProgressCB) error {
 	taskCB(&rpc.TaskProgress{Name: tr("Installing %s", libRelease)})
 	logrus.WithField("library", libRelease).Info("Installing library")
-	libPath, libReplaced, err := lm.InstallPrerequisiteCheck(libRelease, installLocation)
-	if errors.Is(err, librariesmanager.ErrAlreadyInstalled) {
-		taskCB(&rpc.TaskProgress{Message: tr("Already installed %s", libRelease), Completed: true})
-		return err
-	}
-
-	if err != nil {
-		return &arduino.FailedInstallError{Message: tr("Checking lib install prerequisites"), Cause: err}
-	}
 
-	if libReplaced != nil {
+	if libReplaced := installTask.ReplacedLib; libReplaced != nil {
 		taskCB(&rpc.TaskProgress{Message: tr("Replacing %[1]s with %[2]s", libReplaced, libRelease)})
-	}
-
-	if err := lm.Install(libRelease, libPath); err != nil {
-		return &arduino.FailedLibraryInstallError{Cause: err}
-	}
-	if libReplaced != nil && !libReplaced.InstallDir.EquivalentTo(libPath) {
 		if err := lm.Uninstall(libReplaced); err != nil {
-			return fmt.Errorf("%s: %s", tr("could not remove old library"), err)
+			return &arduino.FailedLibraryInstallError{
+				Cause: fmt.Errorf("%s: %s", tr("could not remove old library"), err)}
 		}
 	}
+	if err := lm.Install(libRelease, installTask.TargetPath); err != nil {
+		return &arduino.FailedLibraryInstallError{Cause: err}
+	}
+
 	taskCB(&rpc.TaskProgress{Message: tr("Installed %s", libRelease), Completed: true})
 	return nil
 }
@@ -156,7 +133,7 @@ func installLibrary(lm *librariesmanager.LibrariesManager, libRelease *libraries
 // ZipLibraryInstall FIXMEDOC
 func ZipLibraryInstall(ctx context.Context, req *rpc.ZipLibraryInstallRequest, taskCB rpc.TaskProgressCB) error {
 	lm := commands.GetLibraryManager(req)
-	if err := lm.InstallZipLib(ctx, req.Path, req.Overwrite); err != nil {
+	if err := lm.InstallZipLib(ctx, paths.New(req.Path), req.Overwrite); err != nil {
 		return &arduino.FailedLibraryInstallError{Cause: err}
 	}
 	taskCB(&rpc.TaskProgress{Message: tr("Library installed"), Completed: true})
diff --git a/docs/UPGRADING.md b/docs/UPGRADING.md
index cd8bb72d709..3ab8b55d26a 100644
--- a/docs/UPGRADING.md
+++ b/docs/UPGRADING.md
@@ -16,6 +16,29 @@ The `sketch.json` file is now completely ignored.
 The `cc.arduino.cli.commands.v1.BoardAttach` gRPC command has been removed. This feature is no longer available through
 gRPC.
 
+### golang API change in `github.com/arduino/arduino-cli/arduino/libraries/librariesmanager.LibrariesManager`
+
+The following `LibrariesManager.InstallPrerequisiteCheck` methods have changed prototype, from:
+
+```go
+func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { ... }
+func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath string, overwrite bool) error { ... }
+```
+
+to
+
+```go
+func (lm *LibrariesManager) InstallPrerequisiteCheck(indexLibrary *librariesindex.Release, installLocation libraries.LibraryLocation) (*paths.Path, *libraries.Library, error) { ... }
+func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath *paths.Path, overwrite bool) error { ... }
+```
+
+`InstallPrerequisiteCheck` now requires an explicit `name` and `version` instead of a `librariesindex.Release`, because
+it can now be used to check any library, not only the libraries available in the index. Also the return value has
+changed to a `LibraryInstallPlan` structure, it contains the same information as before (`TargetPath` and `ReplacedLib`)
+plus `Name`, `Version`, and an `UpToDate` boolean flag.
+
+`InstallZipLib` method `archivePath` is now a `paths.Path` instead of a `string`.
+
 ## 0.29.0
 
 ### Removed gRPC API: `cc.arduino.cli.commands.v1.UpdateCoreLibrariesIndex`, `Outdated`, and `Upgrade`
diff --git a/internal/integrationtest/compile_1/compile_test.go b/internal/integrationtest/compile_1/compile_test.go
index c1f856d071b..7702ba0e4df 100644
--- a/internal/integrationtest/compile_1/compile_test.go
+++ b/internal/integrationtest/compile_1/compile_test.go
@@ -878,7 +878,7 @@ func TestCompileWithFullyPrecompiledLibrary(t *testing.T) {
 	require.NoError(t, err)
 	_, _, err = cli.Run("lib", "install", "--zip-path", wd.Parent().Join("testdata", "Arduino_TensorFlowLite-2.1.0-ALPHA-precompiled.zip").String())
 	require.NoError(t, err)
-	sketchFolder := cli.SketchbookDir().Join("libraries", "Arduino_TensorFlowLite-2.1.0-ALPHA-precompiled", "examples", "hello_world")
+	sketchFolder := cli.SketchbookDir().Join("libraries", "Arduino_TensorFlowLite", "examples", "hello_world")
 
 	// Install example dependency
 	_, _, err = cli.Run("lib", "install", "Arduino_LSM9DS1")
diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go
index 435d26acf03..388b95abd79 100644
--- a/internal/integrationtest/lib/lib_test.go
+++ b/internal/integrationtest/lib/lib_test.go
@@ -17,10 +17,13 @@ package lib_test
 
 import (
 	"encoding/json"
+	"io"
+	"net/http"
 	"strings"
 	"testing"
 
 	"github.com/arduino/arduino-cli/internal/integrationtest"
+	"github.com/arduino/go-paths-helper"
 	"github.com/stretchr/testify/require"
 	"go.bug.st/testifyjson/requirejson"
 )
@@ -145,6 +148,63 @@ func TestDuplicateLibInstallDetection(t *testing.T) {
 	require.Contains(t, string(stdErr), "The library ArduinoOTA has multiple installations")
 }
 
+func TestDuplicateLibInstallFromGitDetection(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+	cliEnv := cli.GetDefaultEnv()
+	cliEnv["ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL"] = "true"
+
+	// Make a double install in the sketchbook/user directory
+	_, _, err := cli.Run("lib", "install", "Arduino SigFox for MKRFox1200")
+	require.NoError(t, err)
+
+	_, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "--git-url", "https://github.com/arduino-libraries/SigFox#1.0.3")
+	require.NoError(t, err)
+
+	jsonOut, _, err := cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	// Count how many libraries with the name "Arduino SigFox for MKRFox1200" are installed
+	requirejson.Parse(t, jsonOut).
+		Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`).
+		LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'")
+
+	// Try to make a double install by upgrade
+	_, _, err = cli.Run("lib", "upgrade")
+	require.NoError(t, err)
+
+	// Check if double install happened
+	jsonOut, _, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Parse(t, jsonOut).
+		Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`).
+		LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'")
+
+	// Try to make a double install by zip-installing
+	tmp, err := paths.MkTempDir("", "")
+	require.NoError(t, err)
+	defer tmp.RemoveAll()
+	tmpZip := tmp.Join("SigFox.zip")
+	defer tmpZip.Remove()
+
+	f, err := tmpZip.Create()
+	require.NoError(t, err)
+	resp, err := http.Get("https://github.com/arduino-libraries/SigFox/archive/refs/tags/1.0.3.zip")
+	require.NoError(t, err)
+	_, err = io.Copy(f, resp.Body)
+	require.NoError(t, err)
+	require.NoError(t, f.Close())
+
+	_, _, err = cli.RunWithCustomEnv(cliEnv, "lib", "install", "--zip-path", tmpZip.String())
+	require.NoError(t, err)
+
+	// Check if double install happened
+	jsonOut, _, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Parse(t, jsonOut).
+		Query(`[.[].library.name | select(. == "Arduino SigFox for MKRFox1200")]`).
+		LengthMustEqualTo(1, "Found multiple installations of Arduino SigFox for MKRFox1200'")
+}
+
 func TestLibDepsOutput(t *testing.T) {
 	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
 	defer env.CleanUp()

From ab73719dc0619b6eedd8561d90acff11daadc1b9 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Tue, 29 Nov 2022 15:48:55 +0100
Subject: [PATCH 009/606] Fix `sketch new` default overwriting behavior (#1993)

* Check .ino sketch file exists in path before creating a new one

Running "arduino-cli sketch new ." from a sketch directory overwrites an existing .ino sketch file, without asking for confirmation. This fix introduces a check to verify if the specified path already
contains a .ino sketch file. If it does, an error is returned, otherwise a new sketch is created as usual.

* Add test to check if sketch new does not overwrite an already existing .ino sketch file

* Add --overwrite flag to sketch new command

Using the "--overwrite" flag, allows to create a new sketch overwriting an existing one.
---
 cli/sketch/new.go                             |  10 +-
 commands/sketch/new.go                        |   6 +
 .../integrationtest/sketch/sketch_test.go     |  26 +
 rpc/cc/arduino/cli/commands/v1/commands.pb.go | 616 +++++++++---------
 rpc/cc/arduino/cli/commands/v1/commands.proto |   2 +
 rpc/cc/arduino/cli/commands/v1/common.pb.go   |   1 +
 rpc/cc/arduino/cli/commands/v1/lib.pb.go      |   3 +-
 rpc/cc/arduino/cli/debug/v1/debug.pb.go       |   1 -
 8 files changed, 359 insertions(+), 306 deletions(-)

diff --git a/cli/sketch/new.go b/cli/sketch/new.go
index b3a131acf04..6726bb67fbe 100644
--- a/cli/sketch/new.go
+++ b/cli/sketch/new.go
@@ -31,18 +31,23 @@ import (
 )
 
 func initNewCommand() *cobra.Command {
+	var overwrite bool
+
 	newCommand := &cobra.Command{
 		Use:     "new",
 		Short:   tr("Create a new Sketch"),
 		Long:    tr("Create a new Sketch"),
 		Example: "  " + os.Args[0] + " sketch new MultiBlinker",
 		Args:    cobra.ExactArgs(1),
-		Run:     runNewCommand,
+		Run:     func(cmd *cobra.Command, args []string) { runNewCommand(args, overwrite) },
 	}
+
+	newCommand.Flags().BoolVarP(&overwrite, "overwrite", "f", false, tr("Overwrites an existing .ino sketch."))
+
 	return newCommand
 }
 
-func runNewCommand(cmd *cobra.Command, args []string) {
+func runNewCommand(args []string, overwrite bool) {
 	logrus.Info("Executing `arduino-cli sketch new`")
 	// Trim to avoid issues if user creates a sketch adding the .ino extesion to the name
 	sketchName := args[0]
@@ -56,6 +61,7 @@ func runNewCommand(cmd *cobra.Command, args []string) {
 		Instance:   nil,
 		SketchName: sketchDirPath.Base(),
 		SketchDir:  sketchDirPath.Parent().String(),
+		Overwrite:  overwrite,
 	})
 	if err != nil {
 		feedback.Errorf(tr("Error creating sketch: %v"), err)
diff --git a/commands/sketch/new.go b/commands/sketch/new.go
index 1aa97060363..b2871c48d95 100644
--- a/commands/sketch/new.go
+++ b/commands/sketch/new.go
@@ -17,6 +17,7 @@ package sketch
 
 import (
 	"context"
+	"errors"
 
 	"github.com/arduino/arduino-cli/arduino"
 	"github.com/arduino/arduino-cli/arduino/globals"
@@ -47,6 +48,11 @@ func NewSketch(ctx context.Context, req *rpc.NewSketchRequest) (*rpc.NewSketchRe
 	}
 	sketchName := sketchDirPath.Base()
 	sketchMainFilePath := sketchDirPath.Join(sketchName + globals.MainFileValidExtension)
+	if !req.Overwrite {
+		if sketchMainFilePath.Exist() {
+			return nil, &arduino.CantCreateSketchError{Cause: errors.New(tr(".ino file already exists"))}
+		}
+	}
 	if err := sketchMainFilePath.WriteFile(emptySketch); err != nil {
 		return nil, &arduino.CantCreateSketchError{Cause: err}
 	}
diff --git a/internal/integrationtest/sketch/sketch_test.go b/internal/integrationtest/sketch/sketch_test.go
index 27fd2705dff..d0b8091a83f 100644
--- a/internal/integrationtest/sketch/sketch_test.go
+++ b/internal/integrationtest/sketch/sketch_test.go
@@ -362,3 +362,29 @@ func TestSketchArchiveCaseMismatchFails(t *testing.T) {
 	require.Error(t, err)
 	require.Contains(t, string(stderr), "Error archiving: Can't open sketch:")
 }
+
+func TestSketchNewDotArgOverwrite(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	sketchNew := "SketchNewDotArgOverwrite"
+	sketchPath := cli.SketchbookDir().Join(sketchNew)
+	require.NoError(t, sketchPath.MkdirAll())
+
+	cli.SetWorkingDir(sketchPath)
+	require.NoFileExists(t, sketchPath.Join(sketchNew+".ino").String())
+	// Create a new sketch
+	_, _, err := cli.Run("sketch", "new", ".")
+	require.NoError(t, err)
+
+	require.FileExists(t, sketchPath.Join(sketchNew+".ino").String())
+	// Tries to overwrite the existing sketch with a new one, but it should fail
+	_, stderr, err := cli.Run("sketch", "new", ".")
+	require.Error(t, err)
+	require.Contains(t, string(stderr), ".ino file already exists")
+
+	// Create a new sketch, overwriting the existing one
+	_, _, err = cli.Run("sketch", "new", ".", "--overwrite")
+	require.NoError(t, err)
+	require.FileExists(t, sketchPath.Join(sketchNew+".ino").String())
+}
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.pb.go b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
index 08d689d25d0..2a8e8cc6091 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
@@ -194,6 +194,7 @@ type InitResponse struct {
 	unknownFields protoimpl.UnknownFields
 
 	// Types that are assignable to Message:
+	//
 	//	*InitResponse_InitProgress
 	//	*InitResponse_Error
 	//	*InitResponse_Profile
@@ -670,6 +671,8 @@ type NewSketchRequest struct {
 	// Default Sketchbook directory "directories.User" is used if sketch_dir is
 	// empty.
 	SketchDir string `protobuf:"bytes,3,opt,name=sketch_dir,json=sketchDir,proto3" json:"sketch_dir,omitempty"`
+	// Specificies if an existing .ino sketch should be overwritten
+	Overwrite bool `protobuf:"varint,4,opt,name=overwrite,proto3" json:"overwrite,omitempty"`
 }
 
 func (x *NewSketchRequest) Reset() {
@@ -725,6 +728,13 @@ func (x *NewSketchRequest) GetSketchDir() string {
 	return ""
 }
 
+func (x *NewSketchRequest) GetOverwrite() bool {
+	if x != nil {
+		return x.Overwrite
+	}
+	return false
+}
+
 type NewSketchResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1185,7 +1195,7 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x0f, 0x56, 0x65,
 	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
 	0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x94, 0x01, 0x0a, 0x10, 0x4e, 0x65, 0x77, 0x53,
+	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xb2, 0x01, 0x0a, 0x10, 0x4e, 0x65, 0x77, 0x53,
 	0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08,
 	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
@@ -1194,340 +1204,342 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x0a, 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
 	0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12,
 	0x1d, 0x0a, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x03, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x44, 0x69, 0x72, 0x22, 0x30,
-	0x0a, 0x11, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65,
-	0x22, 0x76, 0x0a, 0x11, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x44, 0x69, 0x72, 0x12, 0x1c,
+	0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x30, 0x0a, 0x11,
+	0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x22, 0x76,
+	0x0a, 0x11, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x73,
+	0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f,
+	0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74,
+	0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x22, 0xdb, 0x01, 0x0a, 0x12, 0x4c, 0x6f, 0x61, 0x64, 0x53,
+	0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a,
+	0x09, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x08, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x6f,
+	0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74, 0x68, 0x12,
+	0x2c, 0x0a, 0x12, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f,
+	0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x74, 0x68,
+	0x65, 0x72, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x29, 0x0a,
+	0x10, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x6c, 0x65,
+	0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f,
+	0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x6f, 0x6f, 0x74,
+	0x5f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20,
+	0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x46,
+	0x69, 0x6c, 0x65, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x14, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
+	0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a,
+	0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21,
+	0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74,
+	0x68, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69,
+	0x6c, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e,
+	0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x72, 0x22, 0x17, 0x0a,
+	0x15, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc9, 0x24, 0x0a, 0x12, 0x41, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x61, 0x0a,
+	0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x69,
-	0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63,
-	0x68, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b,
-	0x65, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x22, 0xdb, 0x01, 0x0a, 0x12, 0x4c, 0x6f, 0x61,
-	0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d,
-	0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x74,
-	0x68, 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x6b, 0x65, 0x74, 0x63,
-	0x68, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f,
-	0x74, 0x68, 0x65, 0x72, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12,
-	0x29, 0x0a, 0x10, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x69,
-	0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x61, 0x64, 0x64, 0x69, 0x74,
-	0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x6f,
-	0x6f, 0x74, 0x5f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18,
-	0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x6f, 0x6c, 0x64, 0x65,
-	0x72, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x14, 0x41, 0x72, 0x63, 0x68, 0x69,
-	0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
-	0x1f, 0x0a, 0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68,
-	0x12, 0x21, 0x0a, 0x0c, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50,
-	0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62,
-	0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
-	0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x72, 0x22,
-	0x17, 0x0a, 0x15, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc9, 0x24, 0x0a, 0x12, 0x41, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
-	0x61, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x00, 0x12, 0x5d, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x27, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30,
-	0x01, 0x12, 0x64, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x2a, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f,
-	0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
+	0x12, 0x5d, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x27, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
 	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74,
-	0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49,
+	0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12,
+	0x64, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
 	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x8d, 0x01, 0x0a, 0x14,
-	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49,
-	0x6e, 0x64, 0x65, 0x78, 0x12, 0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49,
+	0x6e, 0x64, 0x65, 0x78, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
 	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65,
-	0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
-	0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x64, 0x0a, 0x07, 0x56,
-	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x55, 0x70,
+	0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64,
+	0x65, 0x78, 0x12, 0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
-	0x00, 0x12, 0x6a, 0x0a, 0x09, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2c,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x53,
-	0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49,
+	0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x64, 0x0a, 0x07, 0x56, 0x65, 0x72,
+	0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65,
+	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
+	0x6a, 0x0a, 0x09, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2c, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
 	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65,
-	0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a,
-	0x0a, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2d, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65,
-	0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x63, 0x2e,
+	0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74,
-	0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0d,
-	0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x30, 0x2e,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63,
+	0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x0a, 0x4c,
+	0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63,
+	0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0d, 0x41, 0x72,
+	0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
+	0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e,
 	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
 	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69,
-	0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63,
-	0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74,
-	0x61, 0x69, 0x6c, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x09, 0x42, 0x6f, 0x61, 0x72, 0x64,
-	0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69,
+	0x6c, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c,
-	0x6c, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
-	0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73,
-	0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x09, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69,
+	0x73, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f,
+	0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x12,
+	0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61,
+	0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f,
+	0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63,
+	0x68, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
+	0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
+	0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57,
+	0x61, 0x74, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61,
+	0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12,
+	0x64, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
 	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74,
-	0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74,
-	0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30,
-	0x01, 0x12, 0x64, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
-	0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
+	0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
 	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66,
-	0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e,
+	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
+	0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44,
+	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77,
+	0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
+	0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
+	0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
 	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
-	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
-	0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44,
-	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x74, 0x66,
-	0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63,
+	0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
+	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61,
+	0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x32, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
 	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50,
-	0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x32,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x06, 0x55, 0x70, 0x6c,
-	0x6f, 0x61, 0x64, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
+	0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
+	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61,
+	0x64, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55,
+	0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x8e, 0x01, 0x0a, 0x15, 0x55,
+	0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61,
+	0x6d, 0x6d, 0x65, 0x72, 0x12, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f,
+	0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
 	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f,
-	0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x8e, 0x01, 0x0a,
-	0x15, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67,
-	0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x12, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50,
-	0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x39, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
-	0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
-	0x6d, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01,
-	0x0a, 0x13, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46,
-	0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72,
-	0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f,
-	0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x50,
-	0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61,
-	0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44, 0x2e, 0x63,
+	0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65,
+	0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x13,
+	0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65,
+	0x6c, 0x64, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69,
+	0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
+	0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f,
+	0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
+	0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67,
+	0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+	0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x45, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61,
+	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x0e, 0x42, 0x75, 0x72, 0x6e, 0x42,
+	0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c,
+	0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72,
-	0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
-	0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x45, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41,
-	0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61,
-	0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x0e, 0x42, 0x75, 0x72,
-	0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e, 0x63, 0x63,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f,
+	0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x30, 0x01, 0x12, 0x77, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65,
+	0x61, 0x72, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
+	0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61,
+	0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x50,
+	0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x63,
 	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f,
-	0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
+	0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
+	0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c,
+	0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
+	0x64, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+	0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x31,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e,
-	0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x30, 0x01, 0x12, 0x77, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
-	0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72,
-	0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61,
+	0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61,
 	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53,
-	0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a,
-	0x0c, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66,
-	0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70,
+	0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63,
+	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
-	0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x7c, 0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
-	0x6f, 0x61, 0x64, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e,
-	0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79,
-	0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69, 0x74, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e,
+	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69,
 	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62,
-	0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69,
-	0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69,
-	0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12,
-	0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73,
-	0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f,
-	0x0a, 0x10, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61,
+	0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10,
 	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e,
-	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12,
-	0x82, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61,
-	0x64, 0x65, 0x41, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
 	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64,
-	0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x30, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
-	0x69, 0x65, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74,
+	0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01,
+	0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65,
+	0x41, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44,
-	0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65,
-	0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41,
+	0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70,
+	0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x30, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65,
+	0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65,
+	0x73, 0x12, 0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70,
+	0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x3e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65,
+	0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63,
+	0x68, 0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
 	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
 	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72,
-	0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69,
-	0x74, 0x6f, 0x72, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e,
-	0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01,
-	0x12, 0xa1, 0x01, 0x0a, 0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f,
-	0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
-	0x73, 0x12, 0x3f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45,
-	0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50,
-	0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x40, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
-	0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
-	0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
+	0x72, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d,
+	0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e,
+	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
+	0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0xa1,
+	0x01, 0x0a, 0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69,
+	0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
+	0x3f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75,
+	0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72,
+	0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x40, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e,
+	0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f,
+	0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
+	0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.proto b/rpc/cc/arduino/cli/commands/v1/commands.proto
index 699cfb6807e..1b29c4c86ea 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.proto
+++ b/rpc/cc/arduino/cli/commands/v1/commands.proto
@@ -255,6 +255,8 @@ message NewSketchRequest {
   // Default Sketchbook directory "directories.User" is used if sketch_dir is
   // empty.
   string sketch_dir = 3;
+  // Specificies if an existing .ino sketch should be overwritten
+  bool overwrite = 4;
 }
 
 message NewSketchResponse {
diff --git a/rpc/cc/arduino/cli/commands/v1/common.pb.go b/rpc/cc/arduino/cli/commands/v1/common.pb.go
index 9f98f3d2d8a..9c588c14b65 100644
--- a/rpc/cc/arduino/cli/commands/v1/common.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/common.pb.go
@@ -89,6 +89,7 @@ type DownloadProgress struct {
 	unknownFields protoimpl.UnknownFields
 
 	// Types that are assignable to Message:
+	//
 	//	*DownloadProgress_Start
 	//	*DownloadProgress_Update
 	//	*DownloadProgress_End
diff --git a/rpc/cc/arduino/cli/commands/v1/lib.pb.go b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
index 02be303b665..bd315dc76bc 100644
--- a/rpc/cc/arduino/cli/commands/v1/lib.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/lib.pb.go
@@ -1770,7 +1770,8 @@ type Library struct {
 	// Map of FQBNs that specifies if library is compatible with this library
 	CompatibleWith map[string]bool `protobuf:"bytes,28,rep,name=compatible_with,json=compatibleWith,proto3" json:"compatible_with,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
 	// This value is set to true if the library is in development and should not
-	// be treated as read-only.
+	// be treated as read-only. This status is determined by the presence of a
+	// `.development` file in the library root directory.
 	InDevelopment bool `protobuf:"varint,29,opt,name=in_development,json=inDevelopment,proto3" json:"in_development,omitempty"`
 }
 
diff --git a/rpc/cc/arduino/cli/debug/v1/debug.pb.go b/rpc/cc/arduino/cli/debug/v1/debug.pb.go
index 2d1c9d5973b..11989af3fa8 100644
--- a/rpc/cc/arduino/cli/debug/v1/debug.pb.go
+++ b/rpc/cc/arduino/cli/debug/v1/debug.pb.go
@@ -216,7 +216,6 @@ func (x *DebugConfigRequest) GetProgrammer() string {
 	return ""
 }
 
-//
 type DebugResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache

From 76ddec81e51041d5ffa1c0337a36a0d3e09a8702 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Wed, 30 Nov 2022 09:22:29 +0100
Subject: [PATCH 010/606] Enable `sketch archive` overrides using `overwrite`
 flag (#1994)

* Make includeBuildDir private

* Enable sketch archive override using the --overwrite flag

* Add test to verify the changes
---
 cli/sketch/archive.go                         |  10 +-
 commands/sketch/archive.go                    |   6 +-
 .../integrationtest/sketch/sketch_test.go     |  23 +
 rpc/cc/arduino/cli/commands/v1/commands.pb.go | 551 +++++++++---------
 rpc/cc/arduino/cli/commands/v1/commands.proto |   2 +
 5 files changed, 316 insertions(+), 276 deletions(-)

diff --git a/cli/sketch/archive.go b/cli/sketch/archive.go
index 66bd9107275..7e1058584e8 100644
--- a/cli/sketch/archive.go
+++ b/cli/sketch/archive.go
@@ -30,10 +30,10 @@ import (
 	"github.com/spf13/cobra"
 )
 
-var includeBuildDir bool
-
 // initArchiveCommand creates a new `archive` command
 func initArchiveCommand() *cobra.Command {
+	var includeBuildDir, overwrite bool
+
 	archiveCommand := &cobra.Command{
 		Use:   fmt.Sprintf("archive <%s> <%s>", tr("sketchPath"), tr("archivePath")),
 		Short: tr("Creates a zip file containing all sketch files."),
@@ -45,15 +45,16 @@ func initArchiveCommand() *cobra.Command {
 			"  " + os.Args[0] + " archive /home/user/Arduino/MySketch\n" +
 			"  " + os.Args[0] + " archive /home/user/Arduino/MySketch /home/user/MySketchArchive.zip",
 		Args: cobra.MaximumNArgs(2),
-		Run:  runArchiveCommand,
+		Run:  func(cmd *cobra.Command, args []string) { runArchiveCommand(args, includeBuildDir, overwrite) },
 	}
 
 	archiveCommand.Flags().BoolVar(&includeBuildDir, "include-build-dir", false, tr("Includes %s directory in the archive.", "build"))
+	archiveCommand.Flags().BoolVarP(&overwrite, "overwrite", "f", false, tr("Overwrites an already existing archive"))
 
 	return archiveCommand
 }
 
-func runArchiveCommand(cmd *cobra.Command, args []string) {
+func runArchiveCommand(args []string, includeBuildDir bool, overwrite bool) {
 	logrus.Info("Executing `arduino-cli sketch archive`")
 
 	sketchPath := paths.New(".")
@@ -73,6 +74,7 @@ func runArchiveCommand(cmd *cobra.Command, args []string) {
 			SketchPath:      sketchPath.String(),
 			ArchivePath:     archivePath,
 			IncludeBuildDir: includeBuildDir,
+			Overwrite:       overwrite,
 		})
 
 	if err != nil {
diff --git a/commands/sketch/archive.go b/commands/sketch/archive.go
index c353c670328..583ead6225a 100644
--- a/commands/sketch/archive.go
+++ b/commands/sketch/archive.go
@@ -66,8 +66,10 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchRequest) (*rpc.Arc
 		archivePath = paths.New(archivePath.String() + ".zip")
 	}
 
-	if archivePath.Exist() {
-		return nil, &arduino.InvalidArgumentError{Message: tr("Archive already exists")}
+	if !req.Overwrite {
+		if archivePath.Exist() {
+			return nil, &arduino.InvalidArgumentError{Message: tr("Archive already exists")}
+		}
 	}
 
 	filesToZip, err := sketchPath.ReadDirRecursive()
diff --git a/internal/integrationtest/sketch/sketch_test.go b/internal/integrationtest/sketch/sketch_test.go
index d0b8091a83f..496236b31d1 100644
--- a/internal/integrationtest/sketch/sketch_test.go
+++ b/internal/integrationtest/sketch/sketch_test.go
@@ -388,3 +388,26 @@ func TestSketchNewDotArgOverwrite(t *testing.T) {
 	require.NoError(t, err)
 	require.FileExists(t, sketchPath.Join(sketchNew+".ino").String())
 }
+
+func TestSketchArchiveOverwrite(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	sketchName := "ArchiveSketchOverwrite"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+
+	_, _, err := cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("sketch", "archive", sketchPath.String())
+	require.NoError(t, err)
+
+	// It is not possibile to override an archive by default
+	_, stderr, err := cli.Run("sketch", "archive", sketchPath.String())
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "Archive already exists")
+
+	// Override is enabled by the "overwrite" flag
+	_, _, err = cli.Run("sketch", "archive", sketchPath.String(), "--overwrite")
+	require.NoError(t, err)
+}
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.pb.go b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
index 2a8e8cc6091..91729aeaa13 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.pb.go
+++ b/rpc/cc/arduino/cli/commands/v1/commands.pb.go
@@ -937,6 +937,8 @@ type ArchiveSketchRequest struct {
 	ArchivePath string `protobuf:"bytes,2,opt,name=archive_path,json=archivePath,proto3" json:"archive_path,omitempty"`
 	// Specifies if build directory should be included in the archive
 	IncludeBuildDir bool `protobuf:"varint,3,opt,name=include_build_dir,json=includeBuildDir,proto3" json:"include_build_dir,omitempty"`
+	// Allows to override an already existing archive
+	Overwrite bool `protobuf:"varint,4,opt,name=overwrite,proto3" json:"overwrite,omitempty"`
 }
 
 func (x *ArchiveSketchRequest) Reset() {
@@ -992,6 +994,13 @@ func (x *ArchiveSketchRequest) GetIncludeBuildDir() bool {
 	return false
 }
 
+func (x *ArchiveSketchRequest) GetOverwrite() bool {
+	if x != nil {
+		return x.Overwrite
+	}
+	return false
+}
+
 type ArchiveSketchResponse struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1231,7 +1240,7 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x6f, 0x6f, 0x74,
 	0x5f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20,
 	0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x74, 0x46, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x46,
-	0x69, 0x6c, 0x65, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x14, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
+	0x69, 0x6c, 0x65, 0x73, 0x22, 0xa4, 0x01, 0x0a, 0x14, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
 	0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a,
 	0x0b, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x09, 0x52, 0x0a, 0x73, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21,
@@ -1239,307 +1248,309 @@ var file_cc_arduino_cli_commands_v1_commands_proto_rawDesc = []byte{
 	0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74,
 	0x68, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x69,
 	0x6c, 0x64, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e,
-	0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x72, 0x22, 0x17, 0x0a,
-	0x15, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc9, 0x24, 0x0a, 0x12, 0x41, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x61, 0x0a,
-	0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
-	0x12, 0x5d, 0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x27, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49,
-	0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12,
-	0x64, 0x0a, 0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x72, 0x12, 0x1c, 0x0a,
+	0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x41,
+	0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc9, 0x24, 0x0a, 0x12, 0x41, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x61, 0x0a, 0x06, 0x43,
+	0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+	0x1a, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
+	0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d,
+	0x0a, 0x04, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x27, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
 	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49,
-	0x6e, 0x64, 0x65, 0x78, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x28, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x69,
+	0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x64, 0x0a,
+	0x07, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
 	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x55, 0x70,
+	0x31, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x22, 0x00, 0x12, 0x72, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64,
+	0x65, 0x78, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61,
+	0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78,
+	0x12, 0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
 	0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64,
-	0x65, 0x78, 0x12, 0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x64, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69,
+	0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
 	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49,
-	0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x69, 0x65, 0x73, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x64, 0x0a, 0x07, 0x56, 0x65, 0x72,
-	0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65,
-	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
-	0x6a, 0x0a, 0x09, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2c, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65,
-	0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e,
+	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a, 0x0a,
+	0x09, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
 	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63,
-	0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x0a, 0x4c,
-	0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63,
-	0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
 	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0d, 0x41, 0x72,
-	0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x0a, 0x4c, 0x6f, 0x61,
+	0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0d, 0x41, 0x72, 0x63, 0x68,
+	0x69, 0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x6b,
+	0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63,
 	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
 	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65,
-	0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69,
-	0x76, 0x65, 0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69,
-	0x6c, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x09, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69,
-	0x73, 0x74, 0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
-	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
-	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x2d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x53, 0x6b, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
+	0x12, 0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+	0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
+	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f,
+	0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
+	0x6f, 0x61, 0x72, 0x64, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x09, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74,
+	0x12, 0x2c, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
 	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f,
-	0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x71, 0x0a, 0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x12,
+	0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72,
+	0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a,
+	0x0c, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x12, 0x2f, 0x2e,
+	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64,
+	0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72,
+	0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x6e, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12,
+	0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61,
+	0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
 	0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
 	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61,
-	0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f,
-	0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63,
-	0x68, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
-	0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42,
-	0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57,
-	0x61, 0x74, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x72, 0x64, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x7b, 0x0a, 0x0e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74,
+	0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63,
+	0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x64, 0x0a,
+	0x07, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
 	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x74, 0x63, 0x68,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61,
-	0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12,
-	0x64, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e,
-	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49,
+	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
 	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
-	0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74,
+	0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30,
+	0x01, 0x12, 0x7f, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77,
+	0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
+	0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+	0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55,
+	0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
 	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6e,
-	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44,
-	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
-	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x44, 0x6f, 0x77,
-	0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
-	0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e,
+	0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
+	0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66,
+	0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
 	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
-	0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
-	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7c, 0x0a, 0x0f, 0x50, 0x6c, 0x61,
-	0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x32, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c,
-	0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61,
-	0x64, 0x12, 0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55,
-	0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63,
+	0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74,
+	0x66, 0x6f, 0x72, 0x6d, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12,
+	0x29, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c,
+	0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x8e, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x6c,
+	0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d,
+	0x65, 0x72, 0x12, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72,
+	0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
 	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
-	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x8e, 0x01, 0x0a, 0x15, 0x55,
-	0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61,
-	0x6d, 0x6d, 0x65, 0x72, 0x12, 0x38, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f,
-	0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39,
+	0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x13, 0x53, 0x75,
+	0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64,
+	0x73, 0x12, 0x36, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53,
+	0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c,
+	0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64,
+	0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72,
+	0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46,
+	0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
+	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
+	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61,
+	0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f,
+	0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x45,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f,
-	0x61, 0x64, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65,
-	0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x86, 0x01, 0x0a, 0x13,
-	0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65,
-	0x6c, 0x64, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69,
-	0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74,
-	0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0xb0, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f,
-	0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
-	0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44, 0x2e, 0x63, 0x63, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
+	0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c,
+	0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x0e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f,
+	0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61,
+	0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e,
 	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
-	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x67,
-	0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
-	0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x45, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x73, 0x74, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x73, 0x41, 0x76, 0x61,
-	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x0e, 0x42, 0x75, 0x72, 0x6e, 0x42,
-	0x6f, 0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74,
+	0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01,
+	0x12, 0x77, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72,
+	0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e,
+	0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e,
+	0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
+	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+	0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63,
+	0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x50, 0x6c, 0x61,
+	0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61,
 	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f, 0x6f, 0x74, 0x6c,
-	0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63,
+	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c,
+	0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
+	0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0f,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12,
+	0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x31, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x42, 0x6f,
-	0x6f, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x30, 0x01, 0x12, 0x77, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65,
-	0x61, 0x72, 0x63, 0x68, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
-	0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76,
-	0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
+	0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+	0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+	0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
 	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
-	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x61,
-	0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x50,
-	0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x63,
-	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
-	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
-	0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72,
+	0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e,
+	0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
+	0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55,
+	0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01,
+	0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49,
+	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75,
+	0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
+	0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e,
+	0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63,
 	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
-	0x72, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c,
-	0x0a, 0x0f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
-	0x64, 0x12, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
-	0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x31,
-	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
+	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72,
 	0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x32, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x79, 0x0a, 0x0e, 0x4c, 0x69, 0x62, 0x72, 0x61,
-	0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70,
-	0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63,
-	0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f,
-	0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
-	0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
-	0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72,
-	0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
-	0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
-	0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35,
+	0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47,
+	0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10, 0x4c, 0x69,
+	0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x33,
 	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
-	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x5a, 0x69, 0x70, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73,
-	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11, 0x47, 0x69, 0x74, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x34, 0x2e,
-	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x47, 0x69, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61,
-	0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x7f, 0x0a, 0x10,
-	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x12, 0x33, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74,
-	0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01,
-	0x0a, 0x11, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65,
-	0x41, 0x6c, 0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41,
-	0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61,
-	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
-	0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70,
-	0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x30, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65,
-	0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65,
-	0x73, 0x12, 0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x6e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
+	0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x82, 0x01, 0x0a, 0x11,
+	0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c,
+	0x6c, 0x12, 0x34, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
 	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70,
-	0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x3e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
-	0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65,
-	0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63,
-	0x68, 0x12, 0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64,
+	0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
+	0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x55, 0x70, 0x67, 0x72,
+	0x61, 0x64, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01,
+	0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f,
+	0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x12,
+	0x3d, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e,
+	0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72,
+	0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
+	0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74,
+	0x0a, 0x0d, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12,
+	0x30, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62,
+	0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
 	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c,
-	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c,
+	0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
 	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
-	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72,
-	0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69,
-	0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e,
-	0x76, 0x31, 0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65,
-	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
-	0x72, 0x12, 0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63,
-	0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d,
-	0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
+	0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31,
+	0x2e, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
+	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12,
+	0x2a, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
+	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e,
+	0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x63,
+	0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63, 0x6f, 0x6d,
+	0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0xa1, 0x01, 0x0a,
+	0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
+	0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3f, 0x2e,
 	0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e, 0x63,
-	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
-	0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0xa1,
-	0x01, 0x0a, 0x1c, 0x45, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69,
-	0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
-	0x3f, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69,
-	0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75,
-	0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72,
-	0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x40, 0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c,
-	0x69, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e,
-	0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f,
-	0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
-	0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f,
-	0x2d, 0x63, 0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75,
-	0x69, 0x6e, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73,
-	0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
+	0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x65,
+	0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x53,
+	0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40,
+	0x2e, 0x63, 0x63, 0x2e, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2e, 0x63, 0x6c, 0x69, 0x2e,
+	0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
+	0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x6f, 0x72, 0x74,
+	0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61,
+	0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e, 0x6f, 0x2d, 0x63,
+	0x6c, 0x69, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x63, 0x2f, 0x61, 0x72, 0x64, 0x75, 0x69, 0x6e,
+	0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x2f, 0x76,
+	0x31, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x33,
 }
 
 var (
diff --git a/rpc/cc/arduino/cli/commands/v1/commands.proto b/rpc/cc/arduino/cli/commands/v1/commands.proto
index 1b29c4c86ea..03d8b470d41 100644
--- a/rpc/cc/arduino/cli/commands/v1/commands.proto
+++ b/rpc/cc/arduino/cli/commands/v1/commands.proto
@@ -293,6 +293,8 @@ message ArchiveSketchRequest {
   string archive_path = 2;
   // Specifies if build directory should be included in the archive
   bool include_build_dir = 3;
+  // Allows to override an already existing archive
+  bool overwrite = 4;
 }
 
 message ArchiveSketchResponse {}

From 210dda426cdbb1392ca73306fb9e5772f93c30c4 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Thu, 1 Dec 2022 10:53:13 +0100
Subject: [PATCH 011/606] [skip-changelog] Eliminate empty lines produced by
 `board details -b` (#1997)

* Eliminate blank line between required tools row entries

* Fix Programmers ID typo and modify tests accordingly

* Reduce spacing between "Required tool" columns

Splitting the table produced by `board details` after `Platform checksum` resets both the average length and the variance of the following cells, thus reducing the space between entries.
---
 cli/board/details.go                         | 31 +++++++++++---------
 internal/integrationtest/board/board_test.go |  2 +-
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/cli/board/details.go b/cli/board/details.go
index a51957ac917..9a4143bc8ff 100644
--- a/cli/board/details.go
+++ b/cli/board/details.go
@@ -109,6 +109,7 @@ func (dr detailsResult) String() string {
 	//                 ATmega328P (Old Bootloader)     cpu=atmega328old
 	//                 ATmega168                       cpu=atmega168
 	t := table.New()
+	tab := table.New()
 	addIfNotEmpty := func(label, content string) {
 		if content != "" {
 			t.AddRow(label, content)
@@ -157,32 +158,34 @@ func (dr detailsResult) String() string {
 	addIfNotEmpty(tr("Platform checksum:"), details.Platform.Checksum)
 
 	t.AddRow() // get some space from above
+
+	tab.SetColumnWidthMode(1, table.Average)
 	for _, tool := range details.ToolsDependencies {
-		t.AddRow(tr("Required tool:"), tool.Packager+":"+tool.Name, tool.Version)
+		tab.AddRow(tr("Required tool:"), tool.Packager+":"+tool.Name, tool.Version)
 		if showFullDetails {
 			for _, sys := range tool.Systems {
-				t.AddRow("", tr("OS:"), sys.Host)
-				t.AddRow("", tr("File:"), sys.ArchiveFilename)
-				t.AddRow("", tr("Size (bytes):"), fmt.Sprint(sys.Size))
-				t.AddRow("", tr("Checksum:"), sys.Checksum)
-				t.AddRow("", tr("URL:"), sys.Url)
-				t.AddRow() // get some space from above
+				tab.AddRow("", tr("OS:"), sys.Host)
+				tab.AddRow("", tr("File:"), sys.ArchiveFilename)
+				tab.AddRow("", tr("Size (bytes):"), fmt.Sprint(sys.Size))
+				tab.AddRow("", tr("Checksum:"), sys.Checksum)
+				tab.AddRow("", tr("URL:"), sys.Url)
+				tab.AddRow() // get some space from above
 			}
 		}
-		t.AddRow() // get some space from above
 	}
 
+	tab.AddRow() // get some space from above
 	for _, option := range details.ConfigOptions {
-		t.AddRow(tr("Option:"), option.OptionLabel, "", option.Option)
+		tab.AddRow(tr("Option:"), option.OptionLabel, "", option.Option)
 		for _, value := range option.Values {
 			green := color.New(color.FgGreen)
 			if value.Selected {
-				t.AddRow("",
+				tab.AddRow("",
 					table.NewCell(value.ValueLabel, green),
 					table.NewCell("✔", green),
 					table.NewCell(option.Option+"="+value.Value, green))
 			} else {
-				t.AddRow("",
+				tab.AddRow("",
 					value.ValueLabel,
 					"",
 					option.Option+"="+value.Value)
@@ -190,10 +193,10 @@ func (dr detailsResult) String() string {
 		}
 	}
 
-	t.AddRow(tr("Programmers:"), tr("Id"), tr("Name"))
+	tab.AddRow(tr("Programmers:"), tr("ID"), tr("Name"))
 	for _, programmer := range details.Programmers {
-		t.AddRow("", programmer.GetId(), programmer.GetName())
+		tab.AddRow("", programmer.GetId(), programmer.GetName())
 	}
 
-	return t.Render()
+	return t.Render() + tab.Render()
 }
diff --git a/internal/integrationtest/board/board_test.go b/internal/integrationtest/board/board_test.go
index c243abd7843..b3ac071ddb4 100644
--- a/internal/integrationtest/board/board_test.go
+++ b/internal/integrationtest/board/board_test.go
@@ -326,7 +326,7 @@ func TestBoardDetailsListProgrammersWithoutFlag(t *testing.T) {
 	for i, l := range split {
 		lines[i] = strings.Fields(l)
 	}
-	require.Contains(t, lines, []string{"Programmers:", "Id", "Name"})
+	require.Contains(t, lines, []string{"Programmers:", "ID", "Name"})
 	require.Contains(t, lines, []string{"edbg", "Atmel", "EDBG"})
 	require.Contains(t, lines, []string{"atmel_ice", "Atmel-ICE"})
 	require.Contains(t, lines, []string{"sam_ice", "Atmel", "SAM-ICE"})

From 82dc5dd408e41fffa42901ef9fd2fe7c57620adf Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Fri, 2 Dec 2022 16:30:32 +0100
Subject: [PATCH 012/606] [skip-changelog]Update `installed.json` with newer
 entries (#1998)

---
 .../integrationtest/testdata/installed.json   | 82 ++++++++++++++++---
 1 file changed, 72 insertions(+), 10 deletions(-)

diff --git a/internal/integrationtest/testdata/installed.json b/internal/integrationtest/testdata/installed.json
index 6ed9458a0d3..53e37b7085e 100644
--- a/internal/integrationtest/testdata/installed.json
+++ b/internal/integrationtest/testdata/installed.json
@@ -1814,36 +1814,43 @@
               "host": "i386-apple-darwin11",
               "url": "http://downloads.arduino.cc/tools/dfu-util-0.11.0-arduino3-osx.tar.bz2",
               "archiveFileName": "dfu-util-0.11.0-arduino3-osx.tar.bz2",
-              "size": "78971",
-              "checksum": "SHA-256:75a396bbb919157f7a38250869ad11028c456af2d9852ae85dde05ba657d50d3"
+              "size": "79057",
+              "checksum": "SHA-256:81d88dae0ed068a7bdde14d7cd56c9b953a3aea87aaaf4bcbaf022ba7df47ad5"
             },
             {
               "host": "arm-linux-gnueabihf",
               "url": "http://downloads.arduino.cc/tools/dfu-util-0.11.0-arduino3-arm.tar.bz2",
               "archiveFileName": "dfu-util-0.11.0-arduino3-arm.tar.bz2",
-              "size": "288723",
-              "checksum": "SHA-256:c7772deb103514e08ad8b70752e59aa5db3c6ace96fc4ea6bf85f07e824e7cd6"
+              "size": "241168",
+              "checksum": "SHA-256:27fb1fc8ba19df08f1805236083c7199f59bdaaacacceead98fee0e817e48425"
+            },
+            {
+              "host": "aarch64-linux-gnu",
+              "url": "http://downloads.arduino.cc/tools/dfu-util-0.11.0-arduino3-arm64.tar.bz2",
+              "archiveFileName": "dfu-util-0.11.0-arduino3-arm64.tar.bz2",
+              "size": "282961",
+              "checksum": "SHA-256:5f212524b6338d06bf833a2375f1012740e0a359c81ad1ff728222cc93a28586"
             },
             {
               "host": "x86_64-linux-gnu",
               "url": "http://downloads.arduino.cc/tools/dfu-util-0.11.0-arduino3-linux64.tar.bz2",
               "archiveFileName": "dfu-util-0.11.0-arduino3-linux64.tar.bz2",
-              "size": "81861",
-              "checksum": "SHA-256:4989f33f2e7b9da2973b397b127843478967d6846f4b763823cce342aa34dd0f"
+              "size": "78422",
+              "checksum": "SHA-256:6a72e62546d4ba1c0c05c00a1e4863b23ab99e1224e6325b458207822fbf0da4"
             },
             {
               "host": "i686-linux-gnu",
               "url": "http://downloads.arduino.cc/tools/dfu-util-0.11.0-arduino3-linux32.tar.bz2",
               "archiveFileName": "dfu-util-0.11.0-arduino3-linux32.tar.bz2",
-              "size": "81885",
-              "checksum": "SHA-256:c6d96acef36773044056be4a592c65416ca831a68f6f36c13f5de730948c870b"
+              "size": "82825",
+              "checksum": "SHA-256:d6e5bd3d1861ac01dc85e85ae44667346a18f56537a95fe63e9dc71b1adeac99"
             },
             {
               "host": "i686-mingw32",
               "url": "http://downloads.arduino.cc/tools/dfu-util-0.11.0-arduino3-windows.tar.bz2",
               "archiveFileName": "dfu-util-0.11.0-arduino3-windows.tar.bz2",
-              "size": "635831",
-              "checksum": "SHA-256:f951ffce899108096eb61ccc892b7ba80cae4314ef5463e75e0e1acab21d05b6"
+              "size": "635719",
+              "checksum": "SHA-256:7dccfadc260c5b13f7267fcd9ed610571bc74f6f64a85c20541c9ae48a1833b3"
             }
           ]
         },
@@ -2394,6 +2401,61 @@
             }
           ]
         },
+        {
+          "name": "arduinoOTA",
+          "version": "1.4.0",
+          "systems": [
+            {
+              "host": "i686-pc-linux-gnu",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_Linux_32bit.tar.gz",
+              "archiveFileName": "arduinoOTA_1.4.0_Linux_32bit.tar.gz",
+              "size": "3742108",
+              "checksum": "SHA-256:9080b00d784c51bfd3703ae6a1c3c28ac6a2509356c319d44cd87cdb54853f50"
+            },
+            {
+              "host": "x86_64-pc-linux-gnu",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_Linux_64bit.tar.gz",
+              "archiveFileName": "arduinoOTA_1.4.0_Linux_64bit.tar.gz",
+              "size": "3984473",
+              "checksum": "SHA-256:6bbc317b82753bdae5a98a5785f7ba91171fa4d43c50333801af32c9076b94dc"
+            },
+            {
+              "host": "i686-mingw32",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_Windows_32bit.zip",
+              "archiveFileName": "arduinoOTA_1.4.0_Windows_32bit.zip",
+              "size": "3723215",
+              "checksum": "SHA-256:2cd10357d743fb678fff73dae73ae52ed310db09d103819702d53add13ca0bbb"
+            },
+            {
+              "host": "x86_64-mingw32",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_Windows_64bit.zip",
+              "archiveFileName": "arduinoOTA_1.4.0_Windows_64bit.zip",
+              "size": "3895744",
+              "checksum": "SHA-256:05eeebd155cb53e9528ab132bc00af76719f4c082cdcd0fee1f9cd96c56ecdd4"
+            },
+            {
+              "host": "x86_64-apple-darwin",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_macOS_64bit.tar.gz",
+              "archiveFileName": "arduinoOTA_1.4.0_macOS_64bit.tar.gz",
+              "size": "3955987",
+              "checksum": "SHA-256:c5e7f3c7cc823bceb617a57ba6875710957a7090d059a5335daffcc2b19cbad4"
+            },
+            {
+              "host": "arm-linux-gnueabihf",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_Linux_ARMv6.tar.gz",
+              "archiveFileName": "arduinoOTA_1.4.0_Linux_ARMv6.tar.gz",
+              "size": "3583605",
+              "checksum": "SHA-256:d2c75b73db96c22c01b68326539eecab1100f55a30bf7aab0cfa3942583e58c8"
+            },
+            {
+              "host": "arm64-linux-gnueabihf",
+              "url": "https://downloads.arduino.cc/tools/arduinoOTA/arduinoOTA_1.4.0_Linux_ARM64.tar.gz",
+              "archiveFileName": "arduinoOTA_1.4.0_Linux_ARM64.tar.gz",
+              "size": "3649252",
+              "checksum": "SHA-256:98e311c3e84a7fa7403d52d33fcd67ee90ba816b9628379f65446e259e3197b2"
+            }
+          ]
+        },
         {
           "name": "arduinoOTA",
           "version": "1.3.0",

From f9a3b3644bc6b08680c49ca362504fe2f559d335 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Fri, 2 Dec 2022 16:52:24 +0100
Subject: [PATCH 013/606] [skip-changelog] Migrate twelve tests from
 `test_lib.py` to `lib_test.go` (#1989)

* Migrate TestList from test_lib.py to lib_test.go

* Migrate TestListExitCode from test_lib.py to lib_test.go

* Migrate TestListWithFqbn from test_lib.py to lib_test.go

* Migrate TestListProvidesIncludesFallback from test_lib.py to lib_test.go

* Migrate TestLibDownload from test_lib.py to lib_test.go

* Migrate TestInstall from test_lib.py to lib_test.go

* Migrate TestInstallLibraryWithDependencies from test_lib.py to lib_test.go

* Migrate TestInstallNoDeps from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrl from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrlFragmentAsBranch from test_lib.py to lib_test.go

* Migrate TestUpdateIndex from test_lib.py to lib_test.go

* Migrate TestUninstall from test_lib.py to lib_test.go

* Reduce quoting using verbatim strings and improve jq queries

Co-authored-by: Cristian Maglie <c.maglie@bug.st>

Co-authored-by: Cristian Maglie <c.maglie@bug.st>
---
 internal/integrationtest/lib/lib_test.go | 366 +++++++++++++++++++++++
 test/test_lib.py                         | 312 -------------------
 2 files changed, 366 insertions(+), 312 deletions(-)

diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go
index 388b95abd79..f8993925a28 100644
--- a/internal/integrationtest/lib/lib_test.go
+++ b/internal/integrationtest/lib/lib_test.go
@@ -310,3 +310,369 @@ func TestUpgradeLibraryWithDependencies(t *testing.T) {
 	dependency := jsonOut.Query(`.dependencies[] | select(.name=="MKRWAN")`)
 	require.Equal(t, dependency.Query(".version_required"), dependency.Query(".version_installed"))
 }
+
+func TestList(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	// When output is empty, nothing is printed out, no matter the output format
+	stdout, stderr, err := cli.Run("lib", "list")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	require.Contains(t, string(stdout), "No libraries installed.")
+	stdout, stderr, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	requirejson.Empty(t, stdout)
+
+	// Install something we can list at a version older than latest
+	_, _, err = cli.Run("lib", "install", "ArduinoJson@6.11.0")
+	require.NoError(t, err)
+
+	// Look at the plain text output
+	stdout, stderr, err = cli.Run("lib", "list")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	lines := strings.Split(strings.TrimSpace(string(stdout)), "\n")
+	require.Len(t, lines, 2)
+	lines[1] = strings.Join(strings.Fields(lines[1]), " ")
+	toks := strings.SplitN(lines[1], " ", 5)
+	// Verifies the expected number of field
+	require.Len(t, toks, 5)
+	// be sure line contain the current version AND the available version
+	require.NotEmpty(t, toks[1])
+	require.NotEmpty(t, toks[2])
+	// Verifies library sentence
+	require.Contains(t, toks[4], "An efficient and elegant JSON library...")
+
+	// Look at the JSON output
+	stdout, stderr, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	requirejson.Len(t, stdout, 1)
+	// be sure data contains the available version
+	requirejson.Query(t, stdout, `.[0] | .release | .version != ""`, "true")
+
+	// Install something we can list without provides_includes field given in library.properties
+	_, _, err = cli.Run("lib", "install", "Arduino_APDS9960@1.0.3")
+	require.NoError(t, err)
+	// Look at the JSON output
+	stdout, stderr, err = cli.Run("lib", "list", "Arduino_APDS9960", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	requirejson.Len(t, stdout, 1)
+	// be sure data contains the correct provides_includes field
+	requirejson.Query(t, stdout, ".[0] | .library | .provides_includes | .[0]", `"Arduino_APDS9960.h"`)
+}
+
+func TestListExitCode(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("core", "list")
+	require.NoError(t, err)
+
+	// Verifies lib list doesn't fail when platform is not specified
+	_, stderr, err := cli.Run("lib", "list")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+
+	// Verify lib list command fails because specified platform is not installed
+	_, stderr, err = cli.Run("lib", "list", "-b", "arduino:samd:mkr1000")
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "Error listing Libraries: Unknown FQBN: platform arduino:samd is not installed")
+
+	_, _, err = cli.Run("lib", "install", "AllThingsTalk LoRaWAN SDK")
+	require.NoError(t, err)
+
+	// Verifies lib list command keeps failing
+	_, stderr, err = cli.Run("lib", "list", "-b", "arduino:samd:mkr1000")
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "Error listing Libraries: Unknown FQBN: platform arduino:samd is not installed")
+
+	_, _, err = cli.Run("core", "install", "arduino:samd")
+	require.NoError(t, err)
+
+	// Verifies lib list command now works since platform has been installed
+	_, stderr, err = cli.Run("lib", "list", "-b", "arduino:samd:mkr1000")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+}
+
+func TestListWithFqbn(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	// Install core
+	_, _, err = cli.Run("core", "install", "arduino:avr")
+	require.NoError(t, err)
+
+	// Look at the plain text output
+	_, _, err = cli.Run("lib", "install", "ArduinoJson")
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "install", "wm8978-esp32")
+	require.NoError(t, err)
+
+	// Look at the plain text output
+	stdout, stderr, err := cli.Run("lib", "list", "-b", "arduino:avr:uno")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	lines := strings.Split(strings.TrimSpace(string(stdout)), "\n")
+	require.Len(t, lines, 2)
+
+	// Verifies library is compatible
+	lines[1] = strings.Join(strings.Fields(lines[1]), " ")
+	toks := strings.SplitN(lines[1], " ", 5)
+	require.Len(t, toks, 5)
+	require.Equal(t, "ArduinoJson", toks[0])
+
+	// Look at the JSON output
+	stdout, stderr, err = cli.Run("lib", "list", "-b", "arduino:avr:uno", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	requirejson.Len(t, stdout, 1)
+
+	// Verifies library is compatible
+	requirejson.Query(t, stdout, `.[0] | .library | .name`, `"ArduinoJson"`)
+	requirejson.Query(t, stdout, `.[0] | .library | .compatible_with | ."arduino:avr:uno"`, `true`)
+}
+
+func TestListProvidesIncludesFallback(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Verifies "provides_includes" field is returned even if libraries don't declare
+	// the "includes" property in their "library.properties" file
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Install core
+	_, _, err = cli.Run("core", "install", "arduino:avr@1.8.3")
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "install", "ArduinoJson@6.17.2")
+	require.NoError(t, err)
+
+	// List all libraries, even the ones installed with the above core
+	stdout, stderr, err := cli.Run("lib", "list", "--all", "--fqbn", "arduino:avr:uno", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+
+	requirejson.Len(t, stdout, 6)
+
+	requirejson.Query(t, stdout, "[.[] | .library | { (.name): .provides_includes }] | add",
+		`{
+			"SPI": [
+		  		"SPI.h"
+			],
+			"SoftwareSerial": [
+		  		"SoftwareSerial.h"
+			],
+			"Wire": [
+		  		"Wire.h"
+			],
+			"ArduinoJson": [
+		  		"ArduinoJson.h",
+		  		"ArduinoJson.hpp"
+			],
+			"EEPROM": [
+		  		"EEPROM.h"
+			],
+			"HID": [
+		  		"HID.h"
+			]
+	  	}`)
+}
+
+func TestLibDownload(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Download a specific lib version
+	_, _, err := cli.Run("lib", "download", "AudioZero@1.0.0")
+	require.NoError(t, err)
+	require.FileExists(t, cli.DownloadDir().Join("libraries", "AudioZero-1.0.0.zip").String())
+
+	// Wrong lib version
+	_, _, err = cli.Run("lib", "download", "AudioZero@69.42.0")
+	require.Error(t, err)
+
+	// Wrong lib
+	_, _, err = cli.Run("lib", "download", "AudioZ")
+	require.Error(t, err)
+}
+
+func TestInstall(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	libs := []string{"Arduino_BQ24195", "CMMC MQTT Connector", "WiFiNINA"}
+	// Should be safe to run install multiple times
+	_, _, err := cli.Run("lib", "install", libs[0], libs[1], libs[2])
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "install", libs[0], libs[1], libs[2])
+	require.NoError(t, err)
+
+	// Test failing-install of library with wrong dependency
+	// (https://github.com/arduino/arduino-cli/issues/534)
+	_, stderr, err := cli.Run("lib", "install", "MD_Parola@3.2.0")
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "No valid dependencies solution found: dependency 'MD_MAX72xx' is not available")
+}
+
+func TestInstallLibraryWithDependencies(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Verifies libraries are not installed
+	stdout, _, err := cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Empty(t, stdout)
+
+	// Install library
+	_, _, err = cli.Run("lib", "install", "MD_Parola@3.5.5")
+	require.NoError(t, err)
+
+	// Verifies library's dependencies are correctly installed
+	stdout, _, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Query(t, stdout, `[ .[] | .library | .name ] | sort`, `["MD_MAX72XX","MD_Parola"]`)
+
+	// Try upgrading with --no-overwrite (should fail) and without --no-overwrite (should succeed)
+	_, _, err = cli.Run("lib", "install", "MD_Parola@3.6.1", "--no-overwrite")
+	require.Error(t, err)
+	_, _, err = cli.Run("lib", "install", "MD_Parola@3.6.1")
+	require.NoError(t, err)
+
+	// Test --no-overwrite with transitive dependencies
+	_, _, err = cli.Run("lib", "install", "SD")
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "install", "Arduino_Builtin", "--no-overwrite")
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "install", "SD@1.2.3")
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "install", "Arduino_Builtin", "--no-overwrite")
+	require.Error(t, err)
+}
+
+func TestInstallNoDeps(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Verifies libraries are not installed
+	stdout, _, err := cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Empty(t, stdout)
+
+	// Install library skipping dependencies installation
+	_, _, err = cli.Run("lib", "install", "MD_Parola@3.5.5", "--no-deps")
+	require.NoError(t, err)
+
+	// Verifies library's dependencies are not installed
+	stdout, _, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Query(t, stdout, `.[] | .library | .name`, `"MD_Parola"`)
+}
+
+func TestInstallWithGitUrl(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Initialize configs to enable --git-url flag
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	_, _, err := cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+
+	// Test git-url library install
+	stdout, _, err := cli.Run("lib", "install", "--git-url", gitUrl)
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+
+	// Verifies library is installed in expected path
+	require.DirExists(t, libInstallDir.String())
+
+	// Reinstall library
+	_, _, err = cli.Run("lib", "install", "--git-url", gitUrl)
+	require.NoError(t, err)
+
+	// Verifies library remains installed
+	require.DirExists(t, libInstallDir.String())
+}
+
+func TestInstallWithGitUrlFragmentAsBranch(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Initialize configs to enable --git-url flag
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	_, _, err := cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+
+	// Test that a bad ref fails
+	_, _, err = cli.Run("lib", "install", "--git-url", gitUrl+"#x-ref-does-not-exist")
+	require.Error(t, err)
+
+	// Verifies library is installed in expected path
+	_, _, err = cli.Run("lib", "install", "--git-url", gitUrl+"#0.16.0")
+	require.NoError(t, err)
+	require.DirExists(t, libInstallDir.String())
+
+	// Reinstall library at an existing ref
+	_, _, err = cli.Run("lib", "install", "--git-url", gitUrl+"#master")
+	require.NoError(t, err)
+
+	// Verifies library remains installed
+	require.DirExists(t, libInstallDir.String())
+}
+
+func TestUpdateIndex(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	stdout, _, err := cli.Run("lib", "update-index")
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "Downloading index: library_index.tar.bz2 downloaded")
+}
+
+func TestUninstall(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	libs := []string{"Arduino_BQ24195", "WiFiNINA"}
+	_, _, err := cli.Run("lib", "install", libs[0], libs[1])
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("lib", "uninstall", libs[0], libs[1])
+	require.NoError(t, err)
+}
diff --git a/test/test_lib.py b/test/test_lib.py
index 7bef2000548..4bfac88f39d 100644
--- a/test/test_lib.py
+++ b/test/test_lib.py
@@ -49,239 +49,6 @@ def download_lib(url, download_dir):
     z.close()
 
 
-def test_list(run_command):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    # When output is empty, nothing is printed out, no matter the output format
-    result = run_command(["lib", "list"])
-    assert result.ok
-    assert "" == result.stderr
-    assert "No libraries installed." in result.stdout.strip()
-    result = run_command(["lib", "list", "--format", "json"], hide=True)
-    assert result.ok
-    assert "" == result.stderr
-    assert 0 == len(json.loads(result.stdout))
-
-    # Install something we can list at a version older than latest
-    result = run_command(["lib", "install", "ArduinoJson@6.11.0"])
-    assert result.ok
-
-    # Look at the plain text output
-    result = run_command(["lib", "list"])
-    assert result.ok
-    assert "" == result.stderr
-    lines = result.stdout.strip().splitlines()
-    assert 2 == len(lines)
-    toks = [t.strip() for t in lines[1].split(maxsplit=4)]
-    # Verifies the expected number of field
-    assert 5 == len(toks)
-    # be sure line contain the current version AND the available version
-    assert "" != toks[1]
-    assert "" != toks[2]
-    # Verifies library sentence
-    assert "An efficient and elegant JSON library..." == toks[4]
-
-    # Look at the JSON output
-    result = run_command(["lib", "list", "--format", "json"], hide=True)
-    assert result.ok
-    assert "" == result.stderr
-    data = json.loads(result.stdout)
-    assert 1 == len(data)
-    # be sure data contains the available version
-    assert "" != data[0]["release"]["version"]
-
-    # Install something we can list without provides_includes field given in library.properties
-    result = run_command(["lib", "install", "Arduino_APDS9960@1.0.3"])
-    assert result.ok
-    # Look at the JSON output
-    result = run_command(["lib", "list", "Arduino_APDS9960", "--format", "json"])
-    assert result.ok
-    assert "" == result.stderr
-    data = json.loads(result.stdout)
-    assert 1 == len(data)
-    # be sure data contains the correct provides_includes field
-    assert "Arduino_APDS9960.h" == data[0]["library"]["provides_includes"][0]
-
-
-def test_list_exit_code(run_command):
-    # Init the environment explicitly
-    assert run_command(["core", "update-index"])
-
-    assert run_command(["core", "list"])
-
-    # Verifies lib list doesn't fail when platform is not specified
-    result = run_command(["lib", "list"])
-    assert result.ok
-    assert result.stderr.strip() == ""
-
-    # Verify lib list command fails because specified platform is not installed
-    result = run_command(["lib", "list", "-b", "arduino:samd:mkr1000"])
-    assert result.failed
-    assert result.stderr.strip() == "Error listing Libraries: Unknown FQBN: platform arduino:samd is not installed"
-
-    assert run_command(["lib", "install", "AllThingsTalk LoRaWAN SDK"])
-
-    # Verifies lib list command keeps failing
-    result = run_command(["lib", "list", "-b", "arduino:samd:mkr1000"])
-    assert result.failed
-    assert result.stderr.strip() == "Error listing Libraries: Unknown FQBN: platform arduino:samd is not installed"
-
-    assert run_command(["core", "install", "arduino:samd"])
-
-    # Verifies lib list command now works since platform has been installed
-    result = run_command(["lib", "list", "-b", "arduino:samd:mkr1000"])
-    assert result.ok
-    assert result.stderr.strip() == ""
-
-
-def test_list_with_fqbn(run_command):
-    # Init the environment explicitly
-    assert run_command(["core", "update-index"])
-
-    # Install core
-    assert run_command(["core", "install", "arduino:avr"])
-
-    # Install some library
-    assert run_command(["lib", "install", "ArduinoJson"])
-    assert run_command(["lib", "install", "wm8978-esp32"])
-
-    # Look at the plain text output
-    result = run_command(["lib", "list", "-b", "arduino:avr:uno"])
-    assert result.ok
-    assert "" == result.stderr
-    lines = result.stdout.strip().splitlines()
-    assert 2 == len(lines)
-
-    # Verifies library is compatible
-    toks = [t.strip() for t in lines[1].split(maxsplit=4)]
-    assert 5 == len(toks)
-    assert "ArduinoJson" == toks[0]
-
-    # Look at the JSON output
-    result = run_command(["lib", "list", "-b", "arduino:avr:uno", "--format", "json"], hide=True)
-    assert result.ok
-    assert "" == result.stderr
-    data = json.loads(result.stdout)
-    assert 1 == len(data)
-
-    # Verifies library is compatible
-    assert data[0]["library"]["name"] == "ArduinoJson"
-    assert data[0]["library"]["compatible_with"]["arduino:avr:uno"]
-
-
-def test_list_provides_includes_fallback(run_command):
-    # Verifies "provides_includes" field is returned even if libraries don't declare
-    # the "includes" property in their "library.properties" file
-    assert run_command(["update"])
-
-    # Install core
-    assert run_command(["core", "install", "arduino:avr@1.8.3"])
-    assert run_command(["lib", "install", "ArduinoJson@6.17.2"])
-
-    # List all libraries, even the ones installed with the above core
-    result = run_command(["lib", "list", "--all", "--fqbn", "arduino:avr:uno", "--format", "json"], hide=True)
-    assert result.ok
-    assert "" == result.stderr
-
-    data = json.loads(result.stdout)
-    assert 6 == len(data)
-
-    libs = {l["library"]["name"]: l["library"]["provides_includes"] for l in data}
-    assert ["SoftwareSerial.h"] == libs["SoftwareSerial"]
-    assert ["Wire.h"] == libs["Wire"]
-    assert ["EEPROM.h"] == libs["EEPROM"]
-    assert ["HID.h"] == libs["HID"]
-    assert ["SPI.h"] == libs["SPI"]
-    assert ["ArduinoJson.h", "ArduinoJson.hpp"] == libs["ArduinoJson"]
-
-
-def test_lib_download(run_command, downloads_dir):
-
-    # Download a specific lib version
-    assert run_command(["lib", "download", "AudioZero@1.0.0"])
-    assert Path(downloads_dir, "libraries", "AudioZero-1.0.0.zip").exists()
-
-    # Wrong lib version
-    result = run_command(["lib", "download", "AudioZero@69.42.0"])
-    assert result.failed
-
-    # Wrong lib
-    result = run_command(["lib", "download", "AudioZ"])
-    assert result.failed
-
-
-def test_install(run_command):
-    libs = ["Arduino_BQ24195", "CMMC MQTT Connector", "WiFiNINA"]
-    # Should be safe to run install multiple times
-    assert run_command(["lib", "install"] + libs)
-    assert run_command(["lib", "install"] + libs)
-
-    # Test failing-install of library with wrong dependency
-    # (https://github.com/arduino/arduino-cli/issues/534)
-    res = run_command(["lib", "install", "MD_Parola@3.2.0"])
-    assert res.failed
-    assert "No valid dependencies solution found: dependency 'MD_MAX72xx' is not available" in res.stderr
-
-
-def test_install_library_with_dependencies(run_command):
-    assert run_command(["update"])
-
-    # Verifies libraries are not installed
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    installed_libraries = [l["library"]["name"] for l in data]
-    assert "MD_Parola" not in installed_libraries
-    assert "MD_MAX72XX" not in installed_libraries
-
-    # Install library
-    assert run_command(["lib", "install", "MD_Parola@3.5.5"])
-
-    # Verifies library's dependencies are correctly installed
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    installed_libraries = [l["library"]["name"] for l in data]
-    assert "MD_Parola" in installed_libraries
-    assert "MD_MAX72XX" in installed_libraries
-
-    # Try upgrading with --no-overwrite (should fail) and without --no-overwrite (should succeed)
-    res = run_command(["lib", "install", "MD_Parola@3.6.1", "--no-overwrite"])
-    assert res.failed
-    assert run_command(["lib", "install", "MD_Parola@3.6.1"])
-
-    # Test --no-overwrite with transitive dependencies
-    assert run_command(["lib", "install", "SD"])
-    assert run_command(["lib", "install", "Arduino_Builtin", "--no-overwrite"])
-    assert run_command(["lib", "install", "SD@1.2.3"])
-    res = run_command(["lib", "install", "Arduino_Builtin", "--no-overwrite"])
-    assert res.failed
-
-
-def test_install_no_deps(run_command):
-    assert run_command(["update"])
-
-    # Verifies libraries are not installed
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    installed_libraries = [l["library"]["name"] for l in data]
-    assert "MD_Parola" not in installed_libraries
-    assert "MD_MAX72XX" not in installed_libraries
-
-    # Install library skipping dependencies installation
-    assert run_command(["lib", "install", "MD_Parola@3.5.5", "--no-deps"])
-
-    # Verifies library's dependencies are not installed
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    installed_libraries = [l["library"]["name"] for l in data]
-    assert "MD_Parola" in installed_libraries
-    assert "MD_MAX72XX" not in installed_libraries
-
-
 def test_install_git_url_and_zip_path_flags_visibility(run_command, data_dir, downloads_dir):
     # Verifies installation fail because flags are not found
     git_url = "https://github.com/arduino-libraries/WiFi101.git"
@@ -329,70 +96,6 @@ def test_install_git_url_and_zip_path_flags_visibility(run_command, data_dir, do
     assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
 
 
-def test_install_with_git_url(run_command, data_dir, downloads_dir):
-    # Initialize configs to enable --git-url flag
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-
-    # Test git-url library install
-    res = run_command(["lib", "install", "--git-url", git_url])
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-    # Verifies library is installed in expected path
-    assert lib_install_dir.exists()
-
-    # Reinstall library
-    assert run_command(["lib", "install", "--git-url", git_url])
-
-    # Verifies library remains installed
-    assert lib_install_dir.exists()
-
-
-def test_install_with_git_url_fragment_as_branch(run_command, data_dir, downloads_dir):
-    # Initialize configs to enable --git-url flag
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-
-    # Test that a bad ref fails
-    res = run_command(["lib", "install", "--git-url", git_url + "#x-ref-does-not-exist"])
-    assert res.failed
-
-    # Verifies library is installed in expected path
-    res = run_command(["lib", "install", "--git-url", git_url + "#0.16.0"])
-    assert res.ok
-    assert lib_install_dir.exists()
-
-    # Reinstall library at an existing ref
-    assert run_command(["lib", "install", "--git-url", git_url + "#master"])
-    assert res.ok
-
-    # Verifies library remains installed
-    assert lib_install_dir.exists()
-
-
 def test_install_with_zip_path(run_command, data_dir, downloads_dir):
     # Initialize configs to enable --zip-path flag
     env = {
@@ -443,21 +146,6 @@ def test_install_with_zip_path(run_command, data_dir, downloads_dir):
     assert lib_install_dir / "README.adoc" in files
 
 
-def test_update_index(run_command):
-    result = run_command(["lib", "update-index"])
-    assert result.ok
-    lines = [l.strip() for l in result.stdout.splitlines()]
-    assert "Downloading index: library_index.tar.bz2 downloaded" in lines
-
-
-def test_uninstall(run_command):
-    libs = ["Arduino_BQ24195", "WiFiNINA"]
-    assert run_command(["lib", "install"] + libs)
-
-    result = run_command(["lib", "uninstall"] + libs)
-    assert result.ok
-
-
 def test_uninstall_spaces(run_command):
     key = "LiquidCrystal I2C"
     assert run_command(["lib", "install", key])

From bc5cf6d7c0730e5ead4ea294325abca0f1315da3 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Wed, 7 Dec 2022 08:56:36 +0100
Subject: [PATCH 014/606] [skip-changelog] Avoid running publish-go-tester-task
 if tag is set (#1984)

* Avoid running publish-go-tester-task if tag is set

* Update .github/workflows/publish-go-tester-task.yml

Co-authored-by: per1234 <accounts@perglass.com>

* Update .github/workflows/publish-go-tester-task.yml

Co-authored-by: per1234 <accounts@perglass.com>

Co-authored-by: per1234 <accounts@perglass.com>
---
 .github/workflows/publish-go-tester-task.yml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/publish-go-tester-task.yml b/.github/workflows/publish-go-tester-task.yml
index 7635da8ba55..73a6c57491a 100644
--- a/.github/workflows/publish-go-tester-task.yml
+++ b/.github/workflows/publish-go-tester-task.yml
@@ -39,10 +39,12 @@ jobs:
         id: determination
         run: |
           RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x"
+          TAG_REGEX="refs/tags/.*"
           # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead.
           if [[ \
-            "${{ github.event_name }}" != "create" || \
-            "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX \
+            ("${{ github.event_name }}" != "create" || \
+            "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX) && \
+            ! "${{ github.ref }}" =~ $TAG_REGEX \
           ]]; then
             # Run the other jobs.
             RESULT="true"

From 90771beba44cce5f526f7ba9bbf7a77d741e1dd0 Mon Sep 17 00:00:00 2001
From: per1234 <accounts@perglass.com>
Date: Wed, 7 Dec 2022 02:25:36 -0800
Subject: [PATCH 015/606] [skip changelog] Restore certificate check
 compatibility w/ RC2-40-CBC encrypted PKS #12 (#2002)

The "Check Certificates" GitHub Actions workflow uses OpenSSL to check for problems with the project's signing
certificates.

Certificates exported to PKS #12 archive files using older tools may have been encrypted using the "RC2-40-CBC"
algorithm.

Due to the availability of more secure modern alternatives, default support for RC2-40-CBC encryption was dropped in
OpenSSL 3.x.

The macOS signing certificate uses this RC2-40-CBC encryption.

The "Check Certificates" GitHub Actions workflow runs on the `ubuntu-latest` runner. Previously, this runner used Ubuntu
20.04. This has now changed to Ubuntu 22.04. With the operating system update came an OpenSSL update from 1.1.1f to
3.0.2. This caused the workflow runs to fail on the macOS certificate job:

Error outputting keys and certificates
80FBB0C5087F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:../crypto/evp/evp_fetch.c:349:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()

Even though no longer done by default, OpenSSL still supports RC2-40-CBC encryption via its "legacy" provider. So
compatibility with the certificate is restored by adding the `-legacy` flag to the `openssl pkcs12` commands.
---
 .github/workflows/check-certificates.yml | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/check-certificates.yml b/.github/workflows/check-certificates.yml
index 85bc015c632..a3ecf724fd6 100644
--- a/.github/workflows/check-certificates.yml
+++ b/.github/workflows/check-certificates.yml
@@ -59,7 +59,9 @@ jobs:
           (
             openssl pkcs12 \
               -in "${{ env.CERTIFICATE_PATH }}" \
-              -noout -passin env:CERTIFICATE_PASSWORD
+              -legacy \
+              -noout \
+              -passin env:CERTIFICATE_PASSWORD
           ) || (
             echo "::error::Verification of ${{ matrix.certificate.identifier }} failed!!!"
             exit 1
@@ -87,6 +89,7 @@ jobs:
               openssl pkcs12 \
                 -in "${{ env.CERTIFICATE_PATH }}" \
                 -clcerts \
+                -legacy \
                 -nodes \
                 -passin env:CERTIFICATE_PASSWORD
             ) | (

From 9193353b37fafa05d0ab54ec4653c95b14e15208 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Fri, 9 Dec 2022 12:48:38 +0100
Subject: [PATCH 016/606] [skip-changelog] Let integration test choose the
 latest minor version of python (#2007)

---
 .github/workflows/test-go-integration-task.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test-go-integration-task.yml b/.github/workflows/test-go-integration-task.yml
index d8450c08599..8964517f84d 100644
--- a/.github/workflows/test-go-integration-task.yml
+++ b/.github/workflows/test-go-integration-task.yml
@@ -5,7 +5,7 @@ env:
   # See: https://github.com/actions/setup-go/tree/main#supported-version-syntax
   GO_VERSION: "1.17"
   # See: https://github.com/actions/setup-python/tree/main#available-versions-of-python
-  PYTHON_VERSION: "3.9.6"
+  PYTHON_VERSION: "3.9"
 
 # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
 on:

From 321372c2375e05bae70e81b4409acec10db6e054 Mon Sep 17 00:00:00 2001
From: Cristian Maglie <c.maglie@arduino.cc>
Date: Fri, 9 Dec 2022 13:35:06 +0100
Subject: [PATCH 017/606] [skip-changelog] Some minor adjustments in the
 codebase (#2006)

* Updated go-paths-helper to v1.8.0

* Pass of go-fmt

* Removed unused functions

* Removed dep golang.org/x/crypto/ssh/terminal in favor of golang.org/x/term

* Fixed wrong error message
---
 .../arduino/go-paths-helper.dep.yml           |  2 +-
 .../golang.org/x/crypto/ssh/terminal.dep.yml  | 63 -------------------
 arduino/discovery/discovery_client/go.mod     |  2 +-
 arduino/discovery/discovery_client/go.sum     |  4 +-
 arduino/errors.go                             |  2 +-
 cli/arguments/user_fields.go                  |  4 +-
 cli/output/rpc_progress.go                    | 10 ---
 client_example/go.sum                         |  2 +-
 commands/upload/upload.go                     |  2 +
 docsgen/go.mod                                |  2 +-
 docsgen/go.sum                                |  4 +-
 go.mod                                        |  4 +-
 go.sum                                        |  4 +-
 13 files changed, 17 insertions(+), 88 deletions(-)
 delete mode 100644 .licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml

diff --git a/.licenses/go/github.com/arduino/go-paths-helper.dep.yml b/.licenses/go/github.com/arduino/go-paths-helper.dep.yml
index a85b5285431..53141215dab 100644
--- a/.licenses/go/github.com/arduino/go-paths-helper.dep.yml
+++ b/.licenses/go/github.com/arduino/go-paths-helper.dep.yml
@@ -1,6 +1,6 @@
 ---
 name: github.com/arduino/go-paths-helper
-version: v1.7.0
+version: v1.8.0
 type: go
 summary: 
 homepage: https://pkg.go.dev/github.com/arduino/go-paths-helper
diff --git a/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml b/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml
deleted file mode 100644
index 43a34ca6961..00000000000
--- a/.licenses/go/golang.org/x/crypto/ssh/terminal.dep.yml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-name: golang.org/x/crypto/ssh/terminal
-version: v0.0.0-20210921155107-089bfa567519
-type: go
-summary: Package terminal provides support functions for dealing with terminals, as
-  commonly found on UNIX systems.
-homepage: https://pkg.go.dev/golang.org/x/crypto/ssh/terminal
-license: bsd-3-clause
-licenses:
-- sources: crypto@v0.0.0-20210921155107-089bfa567519/LICENSE
-  text: |
-    Copyright (c) 2009 The Go Authors. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are
-    met:
-
-       * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-    copyright notice, this list of conditions and the following disclaimer
-    in the documentation and/or other materials provided with the
-    distribution.
-       * Neither the name of Google Inc. nor the names of its
-    contributors may be used to endorse or promote products derived from
-    this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- sources: crypto@v0.0.0-20210921155107-089bfa567519/PATENTS
-  text: |
-    Additional IP Rights Grant (Patents)
-
-    "This implementation" means the copyrightable works distributed by
-    Google as part of the Go project.
-
-    Google hereby grants to You a perpetual, worldwide, non-exclusive,
-    no-charge, royalty-free, irrevocable (except as stated in this section)
-    patent license to make, have made, use, offer to sell, sell, import,
-    transfer and otherwise run, modify and propagate the contents of this
-    implementation of Go, where such license applies only to those patent
-    claims, both currently owned or controlled by Google and acquired in
-    the future, licensable by Google that are necessarily infringed by this
-    implementation of Go.  This grant does not include claims that would be
-    infringed only as a consequence of further modification of this
-    implementation.  If you or your agent or exclusive licensee institute or
-    order or agree to the institution of patent litigation against any
-    entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that this implementation of Go or any code incorporated within this
-    implementation of Go constitutes direct or contributory patent
-    infringement, or inducement of patent infringement, then any patent
-    rights granted to you under this License for this implementation of Go
-    shall terminate as of the date such litigation is filed.
-notices: []
diff --git a/arduino/discovery/discovery_client/go.mod b/arduino/discovery/discovery_client/go.mod
index 6d1c6b6a9f4..6652c9852b6 100644
--- a/arduino/discovery/discovery_client/go.mod
+++ b/arduino/discovery/discovery_client/go.mod
@@ -11,7 +11,7 @@ require (
 )
 
 require (
-	github.com/arduino/go-paths-helper v1.7.0 // indirect
+	github.com/arduino/go-paths-helper v1.8.0 // indirect
 	github.com/arduino/go-properties-orderedmap v1.7.1 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
diff --git a/arduino/discovery/discovery_client/go.sum b/arduino/discovery/discovery_client/go.sum
index 6ad8d7bdc4d..316c421e9fd 100644
--- a/arduino/discovery/discovery_client/go.sum
+++ b/arduino/discovery/discovery_client/go.sum
@@ -44,8 +44,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
-github.com/arduino/go-paths-helper v1.7.0 h1:S9l5BP2aogz1CgyqqnncXt0PLpK4yvwOW/wu/LaR3tc=
-github.com/arduino/go-paths-helper v1.7.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
+github.com/arduino/go-paths-helper v1.8.0 h1:BfA1bq1XktnlqwfUDCoKbUqB3YFPe6X7szPSZj6Rdpk=
+github.com/arduino/go-paths-helper v1.8.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
 github.com/arduino/go-properties-orderedmap v1.7.1 h1:HQ9Pn/mk3+XyfrE39EEvaZwJkrvgiVSY5Oq3JSEfOR4=
 github.com/arduino/go-properties-orderedmap v1.7.1/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
 github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b/go.mod h1:uwGy5PpN4lqW97FiLnbcx+xx8jly5YuPMJWfVwwjJiQ=
diff --git a/arduino/errors.go b/arduino/errors.go
index 823c2ed99bf..1fbb18841cd 100644
--- a/arduino/errors.go
+++ b/arduino/errors.go
@@ -235,7 +235,7 @@ func (e *InvalidProfileError) ToRPCStatus() *status.Status {
 type MissingPortAddressError struct{}
 
 func (e *MissingPortAddressError) Error() string {
-	return tr("Missing port protocol")
+	return tr("Missing port address")
 }
 
 // ToRPCStatus converts the error into a *status.Status
diff --git a/cli/arguments/user_fields.go b/cli/arguments/user_fields.go
index 480ab38b599..edef603e809 100644
--- a/cli/arguments/user_fields.go
+++ b/cli/arguments/user_fields.go
@@ -22,7 +22,7 @@ import (
 
 	"github.com/arduino/arduino-cli/cli/feedback"
 	rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
-	"golang.org/x/crypto/ssh/terminal"
+	"golang.org/x/term"
 )
 
 // AskForUserFields prompts the user to input the provided user fields.
@@ -36,7 +36,7 @@ func AskForUserFields(userFields []*rpc.UserField) map[string]string {
 		var value []byte
 		var err error
 		if f.Secret {
-			value, err = terminal.ReadPassword(int(os.Stdin.Fd()))
+			value, err = term.ReadPassword(int(os.Stdin.Fd()))
 		} else {
 			value, err = reader.ReadBytes('\n')
 		}
diff --git a/cli/output/rpc_progress.go b/cli/output/rpc_progress.go
index f2e478d67fc..880ab26fa56 100644
--- a/cli/output/rpc_progress.go
+++ b/cli/output/rpc_progress.go
@@ -93,11 +93,6 @@ func NewDownloadProgressBarCB() func(*rpc.DownloadProgress) {
 	}
 }
 
-// NewNullDownloadProgressCB returns a progress bar callback that outputs nothing.
-func NewNullDownloadProgressCB() func(*rpc.DownloadProgress) {
-	return func(*rpc.DownloadProgress) {}
-}
-
 // NewTaskProgressCB returns a commands.TaskProgressCB progress listener
 // that outputs to terminal
 func NewTaskProgressCB() func(curr *rpc.TaskProgress) {
@@ -121,8 +116,3 @@ func NewTaskProgressCB() func(curr *rpc.TaskProgress) {
 		}
 	}
 }
-
-// NewNullTaskProgressCB returns a progress bar callback that outputs nothing.
-func NewNullTaskProgressCB() func(curr *rpc.TaskProgress) {
-	return func(curr *rpc.TaskProgress) {}
-}
diff --git a/client_example/go.sum b/client_example/go.sum
index cd793e04060..a8ad790d6cb 100644
--- a/client_example/go.sum
+++ b/client_example/go.sum
@@ -44,7 +44,7 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
-github.com/arduino/go-paths-helper v1.7.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
+github.com/arduino/go-paths-helper v1.8.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
 github.com/arduino/go-properties-orderedmap v1.7.1/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
 github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b/go.mod h1:uwGy5PpN4lqW97FiLnbcx+xx8jly5YuPMJWfVwwjJiQ=
 github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b/go.mod h1:iIPnclBMYm1g32Q5kXoqng4jLhMStReIP7ZxaoUC2y8=
diff --git a/commands/upload/upload.go b/commands/upload/upload.go
index 95631369991..b026e45ff2d 100644
--- a/commands/upload/upload.go
+++ b/commands/upload/upload.go
@@ -629,11 +629,13 @@ func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) {
 // specified protocol properties.
 //
 // For example passing the below properties and "upload" as action and "serial" as protocol:
+//
 //	upload.speed=256
 //	upload.serial.speed=57600
 //	upload.network.speed=19200
 //
 // will return:
+//
 //	upload.speed=57600
 //	upload.serial.speed=57600
 //	upload.network.speed=19200
diff --git a/docsgen/go.mod b/docsgen/go.mod
index 4c91e2749f7..8a0f379a82c 100644
--- a/docsgen/go.mod
+++ b/docsgen/go.mod
@@ -11,7 +11,7 @@ require (
 )
 
 require (
-	github.com/arduino/go-paths-helper v1.7.0 // indirect
+	github.com/arduino/go-paths-helper v1.8.0 // indirect
 	github.com/arduino/go-properties-orderedmap v1.7.1 // indirect
 	github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b // indirect
 	github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b // indirect
diff --git a/docsgen/go.sum b/docsgen/go.sum
index 42a082e6c5f..c49f0d7c8a4 100644
--- a/docsgen/go.sum
+++ b/docsgen/go.sum
@@ -46,8 +46,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
-github.com/arduino/go-paths-helper v1.7.0 h1:S9l5BP2aogz1CgyqqnncXt0PLpK4yvwOW/wu/LaR3tc=
-github.com/arduino/go-paths-helper v1.7.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
+github.com/arduino/go-paths-helper v1.8.0 h1:BfA1bq1XktnlqwfUDCoKbUqB3YFPe6X7szPSZj6Rdpk=
+github.com/arduino/go-paths-helper v1.8.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
 github.com/arduino/go-properties-orderedmap v1.7.1 h1:HQ9Pn/mk3+XyfrE39EEvaZwJkrvgiVSY5Oq3JSEfOR4=
 github.com/arduino/go-properties-orderedmap v1.7.1/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
 github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b h1:9hDi4F2st6dbLC3y4i02zFT5quS4X6iioWifGlVwfy4=
diff --git a/go.mod b/go.mod
index b4532e290c8..b0047c9301e 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ go 1.17
 replace github.com/mailru/easyjson => github.com/cmaglie/easyjson v0.8.1
 
 require (
-	github.com/arduino/go-paths-helper v1.7.0
+	github.com/arduino/go-paths-helper v1.8.0
 	github.com/arduino/go-properties-orderedmap v1.7.1
 	github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b
 	github.com/arduino/go-win32-utils v0.0.0-20180330194947-ed041402e83b
@@ -51,6 +51,7 @@ require (
 require (
 	github.com/rogpeppe/go-internal v1.3.0
 	go.bug.st/testifyjson v1.1.1
+	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
 	gopkg.in/yaml.v3 v3.0.1
 )
 
@@ -87,7 +88,6 @@ require (
 	github.com/xanzy/ssh-agent v0.2.1 // indirect
 	golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
 	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
-	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	gopkg.in/ini.v1 v1.62.0 // indirect
 	gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
diff --git a/go.sum b/go.sum
index 572bdc4dc65..ffc54d2c315 100644
--- a/go.sum
+++ b/go.sum
@@ -46,8 +46,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
 github.com/arduino/go-paths-helper v1.2.0/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
-github.com/arduino/go-paths-helper v1.7.0 h1:S9l5BP2aogz1CgyqqnncXt0PLpK4yvwOW/wu/LaR3tc=
-github.com/arduino/go-paths-helper v1.7.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
+github.com/arduino/go-paths-helper v1.8.0 h1:BfA1bq1XktnlqwfUDCoKbUqB3YFPe6X7szPSZj6Rdpk=
+github.com/arduino/go-paths-helper v1.8.0/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
 github.com/arduino/go-properties-orderedmap v1.7.1 h1:HQ9Pn/mk3+XyfrE39EEvaZwJkrvgiVSY5Oq3JSEfOR4=
 github.com/arduino/go-properties-orderedmap v1.7.1/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
 github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b h1:9hDi4F2st6dbLC3y4i02zFT5quS4X6iioWifGlVwfy4=

From f79974b3b75dfc09022c690eaa059afefa00a6d6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 9 Dec 2022 13:37:05 +0100
Subject: [PATCH 018/606] [skip-changelog] Bump certifi from 2022.5.18.1 to
 2022.12.7 (#2005)

Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.5.18.1 to 2022.12.7.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2022.05.18.1...2022.12.07)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 poetry.lock | 56 +++++++++++++++++++++--------------------------------
 1 file changed, 22 insertions(+), 34 deletions(-)

diff --git a/poetry.lock b/poetry.lock
index ba503ab7f50..0f0f5465be0 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -15,10 +15,10 @@ optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [package.extras]
-dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
-docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
-tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
-tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
+dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"]
+docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
+tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"]
+tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"]
 
 [[package]]
 name = "black"
@@ -44,7 +44,7 @@ uvloop = ["uvloop (>=0.15.2)"]
 
 [[package]]
 name = "certifi"
-version = "2022.5.18.1"
+version = "2022.12.7"
 description = "Python package for providing Mozilla's CA Bundle."
 category = "main"
 optional = false
@@ -59,7 +59,7 @@ optional = false
 python-versions = ">=3.5.0"
 
 [package.extras]
-unicode_backport = ["unicodedata2"]
+unicode-backport = ["unicodedata2"]
 
 [[package]]
 name = "click"
@@ -139,7 +139,7 @@ python-versions = "*"
 python-dateutil = ">=2.8.1"
 
 [package.extras]
-dev = ["twine", "markdown", "flake8", "wheel"]
+dev = ["flake8", "markdown", "twine", "wheel"]
 
 [[package]]
 name = "gitdb"
@@ -183,9 +183,9 @@ python-versions = ">=3.7"
 zipp = ">=0.5"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
+docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
 perf = ["ipython"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
+testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
 
 [[package]]
 name = "iniconfig"
@@ -387,8 +387,8 @@ optional = false
 python-versions = ">=3.7"
 
 [package.extras]
-docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
-test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
+docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
 
 [[package]]
 name = "pluggy"
@@ -453,7 +453,7 @@ optional = false
 python-versions = ">=3.6.8"
 
 [package.extras]
-diagrams = ["railroad-diagrams", "jinja2"]
+diagrams = ["jinja2", "railroad-diagrams"]
 
 [[package]]
 name = "pyserial"
@@ -483,7 +483,7 @@ py = ">=1.8.2"
 toml = "*"
 
 [package.extras]
-checkqa_mypy = ["mypy (==0.780)"]
+checkqa-mypy = ["mypy (==0.780)"]
 testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
 
 [[package]]
@@ -510,8 +510,8 @@ python-versions = ">=3.4"
 werkzeug = "*"
 
 [package.extras]
-dev = ["flake8", "wheel", "pytest", "pytest-cov", "coverage", "ipdb", "requests", "sphinx", "sphinx-rtd-theme", "reno", "autopep8"]
-test = ["pytest", "pytest-cov", "coverage", "requests"]
+dev = ["autopep8", "coverage", "flake8", "ipdb", "pytest", "pytest-cov", "reno", "requests", "sphinx", "sphinx-rtd-theme", "wheel"]
+test = ["coverage", "pytest", "pytest-cov", "requests"]
 
 [[package]]
 name = "pytest-timeout"
@@ -588,7 +588,7 @@ urllib3 = ">=1.21.1,<1.27"
 
 [package.extras]
 socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
-use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<5)"]
 
 [[package]]
 name = "semver"
@@ -655,8 +655,8 @@ optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
 
 [package.extras]
-brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
-secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"]
 socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
 
 [[package]]
@@ -701,8 +701,8 @@ optional = false
 python-versions = ">=3.7"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
+docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
+testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
 
 [metadata]
 lock-version = "1.1"
@@ -744,8 +744,8 @@ black = [
     {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"},
 ]
 certifi = [
-    {file = "certifi-2022.5.18.1-py3-none-any.whl", hash = "sha256:f1d53542ee8cbedbe2118b5686372fb33c297fcd6379b050cca0ef13a597382a"},
-    {file = "certifi-2022.5.18.1.tar.gz", hash = "sha256:9c5705e395cd70084351dd8ad5c41e65655e08ce46f2ec9cf6c2c08390f71eb7"},
+    {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
+    {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
 ]
 charset-normalizer = [
     {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"},
@@ -1014,18 +1014,6 @@ simplejson = [
     {file = "simplejson-3.17.0-cp37-cp37m-win32.whl", hash = "sha256:fc046afda0ed8f5295212068266c92991ab1f4a50c6a7144b69364bdee4a0159"},
     {file = "simplejson-3.17.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7cce4bac7e0d66f3a080b80212c2238e063211fe327f98d764c6acbc214497fc"},
     {file = "simplejson-3.17.0.tar.gz", hash = "sha256:2b4b2b738b3b99819a17feaf118265d0753d5536049ea570b3c43b51c4701e81"},
-    {file = "simplejson-3.17.0.win-amd64-py2.7.exe", hash = "sha256:1d346c2c1d7dd79c118f0cc7ec5a1c4127e0c8ffc83e7b13fc5709ff78c9bb84"},
-    {file = "simplejson-3.17.0.win-amd64-py3.3.exe", hash = "sha256:5cfd495527f8b85ce21db806567de52d98f5078a8e9427b18e251c68bd573a26"},
-    {file = "simplejson-3.17.0.win-amd64-py3.4.exe", hash = "sha256:8de378d589eccbc75941e480b4d5b4db66f22e4232f87543b136b1f093fff342"},
-    {file = "simplejson-3.17.0.win-amd64-py3.5.exe", hash = "sha256:f4b64a1031acf33e281fd9052336d6dad4d35eee3404c95431c8c6bc7a9c0588"},
-    {file = "simplejson-3.17.0.win-amd64-py3.6.exe", hash = "sha256:ad8dd3454d0c65c0f92945ac86f7b9efb67fa2040ba1b0189540e984df904378"},
-    {file = "simplejson-3.17.0.win-amd64-py3.7.exe", hash = "sha256:229edb079d5dd81bf12da952d4d825bd68d1241381b37d3acf961b384c9934de"},
-    {file = "simplejson-3.17.0.win32-py2.7.exe", hash = "sha256:4fd5f79590694ebff8dc980708e1c182d41ce1fda599a12189f0ca96bf41ad70"},
-    {file = "simplejson-3.17.0.win32-py3.3.exe", hash = "sha256:d140e9376e7f73c1f9e0a8e3836caf5eec57bbafd99259d56979da05a6356388"},
-    {file = "simplejson-3.17.0.win32-py3.4.exe", hash = "sha256:da00675e5e483ead345429d4f1374ab8b949fba4429d60e71ee9d030ced64037"},
-    {file = "simplejson-3.17.0.win32-py3.5.exe", hash = "sha256:7739940d68b200877a15a5ff5149e1599737d6dd55e302625650629350466418"},
-    {file = "simplejson-3.17.0.win32-py3.6.exe", hash = "sha256:60aad424e47c5803276e332b2a861ed7a0d46560e8af53790c4c4fb3420c26c2"},
-    {file = "simplejson-3.17.0.win32-py3.7.exe", hash = "sha256:1fbba86098bbfc1f85c5b69dc9a6d009055104354e0d9880bb00b692e30e0078"},
 ]
 six = [
     {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},

From 53a276832f017f1424c563d3c5d9b74d1000e93c Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Mon, 12 Dec 2022 11:23:12 +0100
Subject: [PATCH 019/606] [skip-changelog] Migrate `lib_test.py` to
 `test_lib.go` part two (#1999)

* Migrate TestUninstallSpaces from test_lib.py to lib_test.go

* Migrate TestLibOpsCaseInsensitive from test_lib.py to lib_test.go

* Migrate TestSearch from test_lib.py to lib_test.go

* Migrate TestSearchParagraph from test_lib.py to lib_test.go

* Migrate TestLibListWithUpdatableFlag from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrlFromCurrentDirectory from test_lib.py to lib_test.go

* Migrate TestInstallWithGitLocalUrl from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrlRelativePath from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrlDoesNotCreateGitRepo from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrlMultipleLibraries from test_lib.py to lib_test.go

* Migrate TestLibExamples from test_lib.py to lib_test.go

* Migrate TestLibExamplesWithPdeFile from test_lib.py to lib_test.go
---
 internal/integrationtest/lib/lib_test.go | 348 +++++++++++++++++++++++
 test/test_lib.py                         | 300 -------------------
 2 files changed, 348 insertions(+), 300 deletions(-)

diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go
index f8993925a28..a09220d04a1 100644
--- a/internal/integrationtest/lib/lib_test.go
+++ b/internal/integrationtest/lib/lib_test.go
@@ -17,6 +17,7 @@ package lib_test
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
 	"net/http"
 	"strings"
@@ -26,6 +27,7 @@ import (
 	"github.com/arduino/go-paths-helper"
 	"github.com/stretchr/testify/require"
 	"go.bug.st/testifyjson/requirejson"
+	"gopkg.in/src-d/go-git.v4"
 )
 
 func TestLibUpgradeCommand(t *testing.T) {
@@ -676,3 +678,349 @@ func TestUninstall(t *testing.T) {
 	_, _, err = cli.Run("lib", "uninstall", libs[0], libs[1])
 	require.NoError(t, err)
 }
+
+func TestUninstallSpaces(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	key := "LiquidCrystal I2C"
+	_, _, err := cli.Run("lib", "install", key)
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "uninstall", key)
+	require.NoError(t, err)
+	stdout, _, err := cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 0)
+}
+
+func TestLibOpsCaseInsensitive(t *testing.T) {
+	/*This test is supposed to (un)install the following library,
+	  As you can see the name is all caps:
+
+	  Name: "PCM"
+	    Author: David Mellis <d.mellis@bcmi-labs.cc>, Michael Smith <michael@hurts.ca>
+	    Maintainer: David Mellis <d.mellis@bcmi-labs.cc>
+	    Sentence: Playback of short audio samples.
+	    Paragraph: These samples are encoded directly in the Arduino sketch as an array of numbers.
+	    Website: http://highlowtech.org/?p=1963
+	    Category: Signal Input/Output
+	    Architecture: avr
+	    Types: Contributed
+	    Versions: [1.0.0]*/
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	key := "pcm"
+	_, _, err := cli.Run("lib", "install", key)
+	require.NoError(t, err)
+	_, _, err = cli.Run("lib", "uninstall", key)
+	require.NoError(t, err)
+	stdout, _, err := cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 0)
+}
+
+func TestSearch(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	stdout, _, err := cli.Run("lib", "search", "--names")
+	require.NoError(t, err)
+	lines := strings.Split(strings.TrimSpace(string(stdout)), "\n")
+	var libs []string
+	for i, v := range lines {
+		lines[i] = strings.TrimSpace(v)
+		if strings.Contains(v, "Name:") {
+			libs = append(libs, strings.Trim(strings.SplitN(v, " ", 2)[1], "\""))
+		}
+	}
+
+	expected := []string{"WiFi101", "WiFi101OTA", "Firebase Arduino based on WiFi101", "WiFi101_Generic"}
+	require.Subset(t, libs, expected)
+
+	stdout, _, err = cli.Run("lib", "search", "--names", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Query(t, stdout, ".libraries | length", fmt.Sprint(len(libs)))
+
+	runSearch := func(args string, expectedLibs []string) {
+		stdout, _, err = cli.Run("lib", "search", "--names", "--format", "json", args)
+		require.NoError(t, err)
+		libraries := requirejson.Parse(t, stdout).Query("[ .libraries | .[] | .name ]").String()
+		for _, l := range expectedLibs {
+			require.Contains(t, libraries, l)
+		}
+	}
+	runSearch("Arduino_MKRIoTCarrier", []string{"Arduino_MKRIoTCarrier"})
+	runSearch("Arduino mkr iot carrier", []string{"Arduino_MKRIoTCarrier"})
+	runSearch("mkr iot carrier", []string{"Arduino_MKRIoTCarrier"})
+	runSearch("mkriotcarrier", []string{"Arduino_MKRIoTCarrier"})
+	runSearch("dht", []string{"DHT sensor library", "DHT sensor library for ESPx", "DHT12", "SimpleDHT", "TinyDHT sensor library", "SDHT"})
+	runSearch("dht11", []string{"DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"})
+	runSearch("dht12", []string{"DHT12", "DHT12 sensor library", "SDHT"})
+	runSearch("dht22", []string{"DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"})
+	runSearch("dht sensor", []string{"DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"})
+	runSearch("sensor dht", []string{})
+	runSearch("arduino json", []string{"ArduinoJson", "Arduino_JSON"})
+	runSearch("arduinojson", []string{"ArduinoJson"})
+	runSearch("json", []string{"ArduinoJson", "Arduino_JSON"})
+}
+
+func TestSearchParagraph(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Search for a string that's only present in the `paragraph` field
+	// within the index file.
+	_, _, err := cli.Run("lib", "update-index")
+	require.NoError(t, err)
+	stdout, _, err := cli.Run("lib", "search", "A simple and efficient JSON library", "--names", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Contains(t, stdout, `{
+		"libraries": [
+			{
+				"name": "ArduinoJson"
+			}
+		]
+	}`)
+}
+
+func TestLibListWithUpdatableFlag(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("lib", "update-index")
+	require.NoError(t, err)
+
+	// No libraries to update
+	stdout, stderr, err := cli.Run("lib", "list", "--updatable")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	require.Contains(t, string(stdout), "No libraries update is available.")
+	// No library to update in json
+	stdout, stderr, err = cli.Run("lib", "list", "--updatable", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	requirejson.Empty(t, stdout)
+
+	// Install outdated library
+	_, _, err = cli.Run("lib", "install", "ArduinoJson@6.11.0")
+	require.NoError(t, err)
+	// Install latest version of library
+	_, _, err = cli.Run("lib", "install", "WiFi101")
+	require.NoError(t, err)
+
+	stdout, stderr, err = cli.Run("lib", "list", "--updatable")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	var lines [][]string
+	for _, v := range strings.Split(strings.TrimSpace(string(stdout)), "\n") {
+		v = strings.Join(strings.Fields(v), " ")
+		lines = append(lines, strings.SplitN(v, " ", 5))
+	}
+	require.Len(t, lines, 2)
+	require.Subset(t, lines[0], []string{"Name", "Installed", "Available", "Location", "Description"})
+	require.Equal(t, "ArduinoJson", lines[1][0])
+	require.Equal(t, "6.11.0", lines[1][1])
+	// Verifies available version is not equal to installed one and not empty
+	require.NotEqual(t, "6.11.0", lines[1][2])
+	require.NotEmpty(t, lines[1][2])
+	require.Equal(t, "An efficient and elegant JSON library...", lines[1][4])
+
+	// Look at the JSON output
+	stdout, stderr, err = cli.Run("lib", "list", "--updatable", "--format", "json")
+	require.NoError(t, err)
+	require.Empty(t, stderr)
+	requirejson.Len(t, stdout, 1)
+	// be sure data contains the available version
+	requirejson.Query(t, stdout, `.[0] | .library | .version`, `"6.11.0"`)
+	requirejson.Query(t, stdout, `.[0] | .release | .version != "6.11.0"`, `true`)
+	requirejson.Query(t, stdout, `.[0] | .release | .version != ""`, `true`)
+}
+
+func TestInstallWithGitUrlFromCurrentDirectory(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Clone repository locally
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	repoDir := cli.SketchbookDir().Join("WiFi101")
+	_, err = git.PlainClone(repoDir.String(), false, &git.CloneOptions{
+		URL: gitUrl,
+	})
+	require.NoError(t, err)
+
+	cli.SetWorkingDir(repoDir)
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", ".")
+	require.NoError(t, err)
+
+	// Verifies library is installed to correct folder
+	require.DirExists(t, libInstallDir.String())
+}
+
+func TestInstallWithGitLocalUrl(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Clone repository locally
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	repoDir := cli.SketchbookDir().Join("WiFi101")
+	_, err = git.PlainClone(repoDir.String(), false, &git.CloneOptions{
+		URL: gitUrl,
+	})
+	require.NoError(t, err)
+
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", repoDir.String())
+	require.NoError(t, err)
+
+	// Verifies library is installed
+	require.DirExists(t, libInstallDir.String())
+}
+
+func TestInstallWithGitUrlRelativePath(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Clone repository locally
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	repoDir := cli.SketchbookDir().Join("WiFi101")
+	_, err = git.PlainClone(repoDir.String(), false, &git.CloneOptions{
+		URL: gitUrl,
+	})
+	require.NoError(t, err)
+
+	cli.SetWorkingDir(cli.SketchbookDir())
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", "./WiFi101")
+	require.NoError(t, err)
+
+	// Verifies library is installed
+	require.DirExists(t, libInstallDir.String())
+}
+
+func TestInstallWithGitUrlDoesNotCreateGitRepo(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Clone repository locally
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	repoDir := cli.SketchbookDir().Join("WiFi101")
+	_, err = git.PlainClone(repoDir.String(), false, &git.CloneOptions{
+		URL: gitUrl,
+	})
+	require.NoError(t, err)
+
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", repoDir.String())
+	require.NoError(t, err)
+
+	// Verifies installed library is not a git repository
+	require.NoDirExists(t, libInstallDir.Join(".git").String())
+}
+
+func TestInstallWithGitUrlMultipleLibraries(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	wifiInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	bleInstallDir := cli.SketchbookDir().Join("libraries", "ArduinoBLE")
+	// Verifies library are not installed
+	require.NoDirExists(t, wifiInstallDir.String())
+	require.NoDirExists(t, bleInstallDir.String())
+
+	wifiUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	bleUrl := "https://github.com/arduino-libraries/ArduinoBLE.git"
+
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", wifiUrl, bleUrl)
+	require.NoError(t, err)
+
+	// Verifies library are installed
+	require.DirExists(t, wifiInstallDir.String())
+	require.DirExists(t, bleInstallDir.String())
+}
+
+func TestLibExamples(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("lib", "install", "Arduino_JSON@0.1.0")
+	require.NoError(t, err)
+
+	stdout, _, err := cli.Run("lib", "examples", "Arduino_JSON", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 1)
+	examples := requirejson.Parse(t, stdout).Query(".[0] | .examples").String()
+	examples = strings.ReplaceAll(examples, "\\\\", "\\")
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Arduino_JSON", "examples", "JSONArray").String())
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Arduino_JSON", "examples", "JSONKitchenSink").String())
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Arduino_JSON", "examples", "JSONObject").String())
+}
+
+func TestLibExamplesWithPdeFile(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("lib", "install", "Encoder@1.4.1")
+	require.NoError(t, err)
+
+	stdout, _, err := cli.Run("lib", "examples", "Encoder", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 1)
+	examples := requirejson.Parse(t, stdout).Query(".[0] | .examples").String()
+	examples = strings.ReplaceAll(examples, "\\\\", "\\")
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Encoder", "examples", "Basic").String())
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Encoder", "examples", "NoInterrupts").String())
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Encoder", "examples", "SpeedTest").String())
+	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Encoder", "examples", "TwoKnobs").String())
+}
diff --git a/test/test_lib.py b/test/test_lib.py
index 4bfac88f39d..8446ea1dbe5 100644
--- a/test/test_lib.py
+++ b/test/test_lib.py
@@ -146,172 +146,6 @@ def test_install_with_zip_path(run_command, data_dir, downloads_dir):
     assert lib_install_dir / "README.adoc" in files
 
 
-def test_uninstall_spaces(run_command):
-    key = "LiquidCrystal I2C"
-    assert run_command(["lib", "install", key])
-    assert run_command(["lib", "uninstall", key])
-    result = run_command(["lib", "list", "--format", "json"])
-    assert result.ok
-    assert len(json.loads(result.stdout)) == 0
-
-
-def test_lib_ops_caseinsensitive(run_command):
-    """
-    This test is supposed to (un)install the following library,
-    As you can see the name is all caps:
-
-    Name: "PCM"
-      Author: David Mellis <d.mellis@bcmi-labs.cc>, Michael Smith <michael@hurts.ca>
-      Maintainer: David Mellis <d.mellis@bcmi-labs.cc>
-      Sentence: Playback of short audio samples.
-      Paragraph: These samples are encoded directly in the Arduino sketch as an array of numbers.
-      Website: http://highlowtech.org/?p=1963
-      Category: Signal Input/Output
-      Architecture: avr
-      Types: Contributed
-      Versions: [1.0.0]
-    """
-    key = "pcm"
-    assert run_command(["lib", "install", key])
-    assert run_command(["lib", "uninstall", key])
-    result = run_command(["lib", "list", "--format", "json"])
-    assert result.ok
-    assert len(json.loads(result.stdout)) == 0
-
-
-def test_search(run_command):
-    assert run_command(["update"])
-
-    result = run_command(["lib", "search", "--names"])
-    assert result.ok
-    lines = [l.strip() for l in result.stdout.strip().splitlines()]
-    assert "Downloading index: library_index.tar.bz2 downloaded" in lines
-    libs = [l[6:].strip('"') for l in lines if "Name:" in l]
-
-    expected = {"WiFi101", "WiFi101OTA", "Firebase Arduino based on WiFi101", "WiFi101_Generic"}
-    assert expected == {lib for lib in libs if "WiFi101" in lib}
-
-    result = run_command(["lib", "search", "--names", "--format", "json"])
-    assert result.ok
-    libs_json = json.loads(result.stdout)
-    assert len(libs) == len(libs_json.get("libraries"))
-
-    result = run_command(["lib", "search", "--names"])
-    assert result.ok
-
-    def run_search(search_args, expected_libraries):
-        res = run_command(["lib", "search", "--names", "--format", "json"] + search_args.split(" "))
-        assert res.ok
-        data = json.loads(res.stdout)
-        libraries = [l["name"] for l in data["libraries"]]
-        for l in expected_libraries:
-            assert l in libraries
-
-    run_search("Arduino_MKRIoTCarrier", ["Arduino_MKRIoTCarrier"])
-    run_search("Arduino mkr iot carrier", ["Arduino_MKRIoTCarrier"])
-    run_search("mkr iot carrier", ["Arduino_MKRIoTCarrier"])
-    run_search("mkriotcarrier", ["Arduino_MKRIoTCarrier"])
-
-    run_search(
-        "dht",
-        ["DHT sensor library", "DHT sensor library for ESPx", "DHT12", "SimpleDHT", "TinyDHT sensor library", "SDHT"],
-    )
-    run_search("dht11", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"])
-    run_search("dht12", ["DHT12", "DHT12 sensor library", "SDHT"])
-    run_search("dht22", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"])
-    run_search("dht sensor", ["DHT sensor library", "DHT sensor library for ESPx", "SimpleDHT", "SDHT"])
-    run_search("sensor dht", [])
-
-    run_search("arduino json", ["ArduinoJson", "Arduino_JSON"])
-    run_search("arduinojson", ["ArduinoJson"])
-    run_search("json", ["ArduinoJson", "Arduino_JSON"])
-
-
-def test_search_paragraph(run_command):
-    """
-    Search for a string that's only present in the `paragraph` field
-    within the index file.
-    """
-    assert run_command(["lib", "update-index"])
-    result = run_command(["lib", "search", "A simple and efficient JSON library", "--names", "--format", "json"])
-    assert result.ok
-    data = json.loads(result.stdout)
-    libraries = [l["name"] for l in data["libraries"]]
-    assert "ArduinoJson" in libraries
-
-
-def test_lib_list_with_updatable_flag(run_command):
-    # Init the environment explicitly
-    run_command(["lib", "update-index"])
-
-    # No libraries to update
-    result = run_command(["lib", "list", "--updatable"])
-    assert result.ok
-    assert "" == result.stderr
-    assert "No libraries update is available." in result.stdout.strip()
-    # No library to update in json
-    result = run_command(["lib", "list", "--updatable", "--format", "json"])
-    assert result.ok
-    assert "" == result.stderr
-    assert 0 == len(json.loads(result.stdout))
-
-    # Install outdated library
-    assert run_command(["lib", "install", "ArduinoJson@6.11.0"])
-    # Install latest version of library
-    assert run_command(["lib", "install", "WiFi101"])
-
-    res = run_command(["lib", "list", "--updatable"])
-    assert res.ok
-    assert "" == res.stderr
-    # lines = res.stdout.strip().splitlines()
-    lines = [l.strip().split(maxsplit=4) for l in res.stdout.strip().splitlines()]
-    assert 2 == len(lines)
-    assert ["Name", "Installed", "Available", "Location", "Description"] in lines
-    line = lines[1]
-    assert "ArduinoJson" == line[0]
-    assert "6.11.0" == line[1]
-    # Verifies available version is not equal to installed one and not empty
-    assert "6.11.0" != line[2]
-    assert "" != line[2]
-    assert "An efficient and elegant JSON library..." == line[4]
-
-    # Look at the JSON output
-    res = run_command(["lib", "list", "--updatable", "--format", "json"], hide=True)
-    assert res.ok
-    assert "" == res.stderr
-    data = json.loads(res.stdout)
-    assert 1 == len(data)
-    # be sure data contains the available version
-    assert "6.11.0" == data[0]["library"]["version"]
-    assert "6.11.0" != data[0]["release"]["version"]
-    assert "" != data[0]["release"]["version"]
-
-
-def test_install_with_git_url_from_current_directory(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not installed
-    assert not lib_install_dir.exists()
-
-    # Clone repository locally
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-    repo_dir = Path(data_dir, "WiFi101")
-    assert Repo.clone_from(git_url, repo_dir)
-
-    assert run_command(["lib", "install", "--git-url", "."], custom_working_dir=repo_dir, custom_env=env)
-
-    # Verifies library is installed to correct folder
-    assert lib_install_dir.exists()
-
-
 @pytest.mark.skipif(
     platform.system() == "Windows",
     reason="Using a file uri as git url doesn't work on Windows, "
@@ -342,107 +176,6 @@ def test_install_with_git_url_local_file_uri(run_command, downloads_dir, data_di
     assert lib_install_dir.exists()
 
 
-def test_install_with_git_local_url(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not installed
-    assert not lib_install_dir.exists()
-
-    # Clone repository locally
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-    repo_dir = Path(data_dir, "WiFi101")
-    assert Repo.clone_from(git_url, repo_dir)
-
-    assert run_command(["lib", "install", "--git-url", repo_dir], custom_env=env)
-
-    # Verifies library is installed
-    assert lib_install_dir.exists()
-
-
-def test_install_with_git_url_relative_path(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not installed
-    assert not lib_install_dir.exists()
-
-    # Clone repository locally
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-    repo_dir = Path(data_dir, "WiFi101")
-    assert Repo.clone_from(git_url, repo_dir)
-
-    assert run_command(["lib", "install", "--git-url", "./WiFi101"], custom_working_dir=data_dir, custom_env=env)
-
-    # Verifies library is installed
-    assert lib_install_dir.exists()
-
-
-def test_install_with_git_url_does_not_create_git_repo(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not installed
-    assert not lib_install_dir.exists()
-
-    # Clone repository locally
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-    repo_dir = Path(data_dir, "WiFi101")
-    assert Repo.clone_from(git_url, repo_dir)
-
-    assert run_command(["lib", "install", "--git-url", repo_dir], custom_env=env)
-
-    # Verifies installed library is not a git repository
-    assert not Path(lib_install_dir, ".git").exists()
-
-
-def test_install_with_git_url_multiple_libraries(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    wifi_install_dir = Path(data_dir, "libraries", "WiFi101")
-    ble_install_dir = Path(data_dir, "libraries", "ArduinoBLE")
-    # Verifies libraries are not installed
-    assert not wifi_install_dir.exists()
-    assert not ble_install_dir.exists()
-
-    wifi_url = "https://github.com/arduino-libraries/WiFi101.git"
-    ble_url = "https://github.com/arduino-libraries/ArduinoBLE.git"
-
-    assert run_command(["lib", "install", "--git-url", wifi_url, ble_url], custom_env=env)
-
-    # Verifies library are installed
-    assert wifi_install_dir.exists()
-    assert ble_install_dir.exists()
-
-
 def test_install_with_zip_path_multiple_libraries(run_command, downloads_dir, data_dir):
     assert run_command(["update"])
 
@@ -473,39 +206,6 @@ def test_install_with_zip_path_multiple_libraries(run_command, downloads_dir, da
     assert ble_install_dir.exists()
 
 
-def test_lib_examples(run_command, data_dir):
-    assert run_command(["update"])
-
-    assert run_command(["lib", "install", "Arduino_JSON@0.1.0"])
-
-    res = run_command(["lib", "examples", "Arduino_JSON", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    examples = data[0]["examples"]
-
-    assert str(Path(data_dir, "libraries", "Arduino_JSON", "examples", "JSONArray")) in examples
-    assert str(Path(data_dir, "libraries", "Arduino_JSON", "examples", "JSONKitchenSink")) in examples
-    assert str(Path(data_dir, "libraries", "Arduino_JSON", "examples", "JSONObject")) in examples
-
-
-def test_lib_examples_with_pde_file(run_command, data_dir):
-    assert run_command(["update"])
-
-    assert run_command(["lib", "install", "Encoder@1.4.1"])
-
-    res = run_command(["lib", "examples", "Encoder", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    examples = data[0]["examples"]
-
-    assert str(Path(data_dir, "libraries", "Encoder", "examples", "Basic")) in examples
-    assert str(Path(data_dir, "libraries", "Encoder", "examples", "NoInterrupts")) in examples
-    assert str(Path(data_dir, "libraries", "Encoder", "examples", "SpeedTest")) in examples
-    assert str(Path(data_dir, "libraries", "Encoder", "examples", "TwoKnobs")) in examples
-
-
 def test_lib_examples_with_case_mismatch(run_command, data_dir):
     assert run_command(["update"])
 

From 320a22c630a6c150a74b8bb806aff0872f547651 Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Tue, 13 Dec 2022 11:45:19 +0100
Subject: [PATCH 020/606] [skip-changelog] Migrate Lib tests for `test_lib.py`
 to `lib_test.go` (#1964)

* Migrate TestLibExamplesWithCaseMismatch from test_lib.py to lib_test.go

* Migrate TestLibCommandsWithLibraryHavingInvalidVersion from test_lib.py to lib_test.go

* Migrate TestInstallZipLibWithMacosMetadata from test_lib.py to lib_test.go

* Migrate TestInstallZipInvalidLibrary from test_lib.py to lib_test.go

* Migrate TestInstallGitInvalidLibrary from test_lib.py to lib_test.go

* Migrate TestUpgradeDoesNotTryToUpgradeBundledCoreLibrariesInSketchbook from test_lib.py to lib_test.go

* Migrate TestUpgradeDoesNotTryToUpgradeBundledCoreLibraries from test_lib.py to lib_test.go

* Migrate TestInstallGitUrlAndZipPathFlagsVisibility from test_lib.py to lib_test.go

* Migrate TestInstallWithZipPath from test_lib.py to lib_test.go

* Migrate TestInstallWithZipPathMultipleLibraries from test_lib.py to lib_test.go

* Migrate TestInstallWithGitUrlLocalFileUri to lib_test.go and delete test_lib.py

* Improve style and readability
---
 internal/integrationtest/lib/lib_test.go      | 449 ++++++++++++++++
 .../integrationtest}/testdata/fake-lib.zip    | Bin
 .../testdata/lib-without-header.zip           | Bin
 .../testdata/lib-without-properties.zip       | Bin
 .../platform_with_bundled_library/boards.txt  |   0
 .../libraries/USBHost/library.properties      |   0
 .../platform.txt                              |   0
 test/test_lib.py                              | 480 ------------------
 8 files changed, 449 insertions(+), 480 deletions(-)
 rename {test => internal/integrationtest}/testdata/fake-lib.zip (100%)
 rename {test => internal/integrationtest}/testdata/lib-without-header.zip (100%)
 rename {test => internal/integrationtest}/testdata/lib-without-properties.zip (100%)
 rename {test => internal/integrationtest}/testdata/platform_with_bundled_library/boards.txt (100%)
 rename {test => internal/integrationtest}/testdata/platform_with_bundled_library/libraries/USBHost/library.properties (100%)
 rename {test => internal/integrationtest}/testdata/platform_with_bundled_library/platform.txt (100%)
 delete mode 100644 test/test_lib.py

diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go
index a09220d04a1..a554da03132 100644
--- a/internal/integrationtest/lib/lib_test.go
+++ b/internal/integrationtest/lib/lib_test.go
@@ -20,14 +20,17 @@ import (
 	"fmt"
 	"io"
 	"net/http"
+	"runtime"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/arduino/arduino-cli/internal/integrationtest"
 	"github.com/arduino/go-paths-helper"
 	"github.com/stretchr/testify/require"
 	"go.bug.st/testifyjson/requirejson"
 	"gopkg.in/src-d/go-git.v4"
+	"gopkg.in/src-d/go-git.v4/plumbing/object"
 )
 
 func TestLibUpgradeCommand(t *testing.T) {
@@ -1024,3 +1027,449 @@ func TestLibExamplesWithPdeFile(t *testing.T) {
 	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Encoder", "examples", "SpeedTest").String())
 	require.Contains(t, examples, cli.SketchbookDir().Join("libraries", "Encoder", "examples", "TwoKnobs").String())
 }
+
+func TestLibExamplesWithCaseMismatch(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	_, _, err = cli.Run("lib", "install", "WiFiManager@2.0.3-alpha")
+	require.NoError(t, err)
+
+	stdout, _, err := cli.Run("lib", "examples", "WiFiManager", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 1)
+	requirejson.Query(t, stdout, ".[0] | .examples | length", "14")
+
+	examples := requirejson.Parse(t, stdout).Query(".[0] | .examples").String()
+	examples = strings.ReplaceAll(examples, "\\\\", "\\")
+	examplesPath := cli.SketchbookDir().Join("libraries", "WiFiManager", "examples")
+	// Verifies sketches with correct casing are listed
+	require.Contains(t, examples, examplesPath.Join("Advanced").String())
+	require.Contains(t, examples, examplesPath.Join("AutoConnect", "AutoConnectWithFeedbackLED").String())
+	require.Contains(t, examples, examplesPath.Join("AutoConnect", "AutoConnectWithFSParameters").String())
+	require.Contains(t, examples, examplesPath.Join("AutoConnect", "AutoConnectWithFSParametersAndCustomIP").String())
+	require.Contains(t, examples, examplesPath.Join("Basic").String())
+	require.Contains(t, examples, examplesPath.Join("DEV", "OnDemandConfigPortal").String())
+	require.Contains(t, examples, examplesPath.Join("NonBlocking", "AutoConnectNonBlocking").String())
+	require.Contains(t, examples, examplesPath.Join("NonBlocking", "AutoConnectNonBlockingwParams").String())
+	require.Contains(t, examples, examplesPath.Join("Old_examples", "AutoConnectWithFeedback").String())
+	require.Contains(t, examples, examplesPath.Join("Old_examples", "AutoConnectWithReset").String())
+	require.Contains(t, examples, examplesPath.Join("Old_examples", "AutoConnectWithStaticIP").String())
+	require.Contains(t, examples, examplesPath.Join("Old_examples", "AutoConnectWithTimeout").String())
+	require.Contains(t, examples, examplesPath.Join("OnDemand", "OnDemandConfigPortal").String())
+	require.Contains(t, examples, examplesPath.Join("ParamsChildClass").String())
+	// Verifies sketches with wrong casing are not returned
+	require.NotContains(t, examples, examplesPath.Join("NonBlocking", "OnDemandNonBlocking").String())
+	require.NotContains(t, examples, examplesPath.Join("OnDemand", "OnDemandWebPortal").String())
+}
+
+func TestLibCommandsWithLibraryHavingInvalidVersion(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Install a library
+	_, _, err = cli.Run("lib", "install", "WiFi101@0.16.1")
+	require.NoError(t, err)
+
+	// Verifies library is correctly returned
+	stdout, _, err := cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 1)
+	requirejson.Query(t, stdout, ".[0] | .library | .version", `"0.16.1"`)
+
+	// Changes the version of the currently installed library so that it's
+	// invalid
+	libPath := cli.SketchbookDir().Join("libraries", "WiFi101", "library.properties")
+	require.NoError(t, libPath.WriteFile([]byte("name=WiFi101\nversion=1.0001")))
+
+	// Verifies version is now empty
+	stdout, _, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 1)
+	requirejson.Query(t, stdout, ".[0] | .library | .version", "null")
+
+	// Upgrade library
+	_, _, err = cli.Run("lib", "upgrade", "WiFi101")
+	require.NoError(t, err)
+
+	// Verifies library has been updated
+	stdout, _, err = cli.Run("lib", "list", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 1)
+	requirejson.Query(t, stdout, ".[0] | .library | .version != \"\"", "true")
+}
+
+func TestInstallZipLibWithMacosMetadata(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Initialize configs to enable --zip-path flag
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	_, _, err := cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "fake-lib")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	zipPath, err := paths.New("..", "testdata", "fake-lib.zip").Abs()
+	require.NoError(t, err)
+	// Test zip-path install
+	stdout, _, err := cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+
+	// Verifies library is installed in expected path
+	require.DirExists(t, libInstallDir.String())
+	require.FileExists(t, libInstallDir.Join("library.properties").String())
+	require.FileExists(t, libInstallDir.Join("src", "fake-lib.h").String())
+
+	// Reinstall library
+	_, _, err = cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.NoError(t, err)
+
+	// Verifies library remains installed
+	require.DirExists(t, libInstallDir.String())
+	require.FileExists(t, libInstallDir.Join("library.properties").String())
+	require.FileExists(t, libInstallDir.Join("src", "fake-lib.h").String())
+}
+
+func TestInstallZipInvalidLibrary(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Initialize configs to enable --zip-path flag
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	_, _, err := cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "lib-without-header")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	zipPath, err := paths.New("..", "testdata", "lib-without-header.zip").Abs()
+	require.NoError(t, err)
+	// Test zip-path install
+	_, stderr, err := cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "library not valid")
+
+	libInstallDir = cli.SketchbookDir().Join("libraries", "lib-without-properties")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	zipPath, err = paths.New("..", "testdata", "lib-without-properties.zip").Abs()
+	require.NoError(t, err)
+	// Test zip-path install
+	_, stderr, err = cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "library not valid")
+}
+
+func TestInstallGitInvalidLibrary(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Initialize configs to enable --zip-path flag
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	_, _, err := cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	// Create fake library repository
+	repoDir := cli.SketchbookDir().Join("lib-without-header")
+	repo, err := git.PlainInit(repoDir.String(), false)
+	require.NoError(t, err)
+	libProperties := repoDir.Join("library.properties")
+	f, err := libProperties.Create()
+	require.NoError(t, err)
+	require.NoError(t, f.Close())
+	tree, err := repo.Worktree()
+	require.NoError(t, err)
+	_, err = tree.Add("library.properties")
+	require.NoError(t, err)
+	_, err = tree.Commit("First commit", &git.CommitOptions{
+		All: false, Author: &object.Signature{Name: "a", Email: "b", When: time.Now()}, Committer: nil, Parents: nil, SignKey: nil})
+	require.NoError(t, err)
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "lib-without-header")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	_, stderr, err := cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", repoDir.String())
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "library not valid")
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Create another fake library repository
+	repoDir = cli.SketchbookDir().Join("lib-without-properties")
+	repo, err = git.PlainInit(repoDir.String(), false)
+	require.NoError(t, err)
+	libHeader := repoDir.Join("src", "lib-without-properties.h")
+	require.NoError(t, libHeader.Parent().MkdirAll())
+	f, err = libHeader.Create()
+	require.NoError(t, err)
+	require.NoError(t, f.Close())
+	tree, err = repo.Worktree()
+	require.NoError(t, err)
+	_, err = tree.Add("src/lib-without-properties.h")
+	require.NoError(t, err)
+	_, err = tree.Commit("First commit", &git.CommitOptions{
+		All: false, Author: &object.Signature{Name: "a", Email: "b", When: time.Now()}, Committer: nil, Parents: nil, SignKey: nil})
+	require.NoError(t, err)
+
+	libInstallDir = cli.SketchbookDir().Join("libraries", "lib-without-properties")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	_, stderr, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", repoDir.String())
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "library not valid")
+	require.NoDirExists(t, libInstallDir.String())
+}
+
+func TestUpgradeDoesNotTryToUpgradeBundledCoreLibrariesInSketchbook(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	testPlatformName := "platform_with_bundled_library"
+	platformInstallDir := cli.SketchbookDir().Join("hardware", "arduino-beta-dev", testPlatformName)
+	require.NoError(t, platformInstallDir.Parent().MkdirAll())
+
+	// Install platform in Sketchbook hardware dir
+	require.NoError(t, paths.New("..", "testdata", testPlatformName).CopyDirTo(platformInstallDir))
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Install latest version of library identical to one
+	// bundled with test platform
+	_, _, err = cli.Run("lib", "install", "USBHost")
+	require.NoError(t, err)
+
+	stdout, _, err := cli.Run("lib", "list", "--all", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 2)
+	// Verify both libraries have the same name
+	requirejson.Query(t, stdout, ".[0] | .library | .name", `"USBHost"`)
+	requirejson.Query(t, stdout, ".[1] | .library | .name", `"USBHost"`)
+
+	stdout, _, err = cli.Run("lib", "upgrade")
+	require.NoError(t, err)
+	// Empty output means nothing has been updated as expected
+	require.Empty(t, stdout)
+}
+
+func TestUpgradeDoesNotTryToUpgradeBundledCoreLibraries(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	testPlatformName := "platform_with_bundled_library"
+	platformInstallDir := cli.DataDir().Join("packages", "arduino", "hardware", "arch", "4.2.0")
+	require.NoError(t, platformInstallDir.Parent().MkdirAll())
+
+	// Install platform in Sketchbook hardware dir
+	require.NoError(t, paths.New("..", "testdata", testPlatformName).CopyDirTo(platformInstallDir))
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Install latest version of library identical to one
+	// bundled with test platform
+	_, _, err = cli.Run("lib", "install", "USBHost")
+	require.NoError(t, err)
+
+	stdout, _, err := cli.Run("lib", "list", "--all", "--format", "json")
+	require.NoError(t, err)
+	requirejson.Len(t, stdout, 2)
+	// Verify both libraries have the same name
+	requirejson.Query(t, stdout, ".[0] | .library | .name", `"USBHost"`)
+	requirejson.Query(t, stdout, ".[1] | .library | .name", `"USBHost"`)
+
+	stdout, _, err = cli.Run("lib", "upgrade")
+	require.NoError(t, err)
+	// Empty output means nothing has been updated as expected
+	require.Empty(t, stdout)
+}
+
+func downloadLib(t *testing.T, url string, zipPath *paths.Path) {
+	response, err := http.Get(url)
+	require.NoError(t, err)
+	require.Equal(t, response.StatusCode, 200)
+	zip, err := zipPath.Create()
+	require.NoError(t, err)
+	_, err = io.Copy(zip, response.Body)
+	require.NoError(t, err)
+	require.NoError(t, response.Body.Close())
+	require.NoError(t, zip.Close())
+}
+
+func TestInstallGitUrlAndZipPathFlagsVisibility(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Verifies installation fail because flags are not found
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	_, stderr, err := cli.Run("lib", "install", "--git-url", gitUrl)
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "--git-url and --zip-path are disabled by default, for more information see:")
+
+	// Download library
+	url := "https://github.com/arduino-libraries/AudioZero/archive/refs/tags/1.1.1.zip"
+	zipPath := cli.DownloadDir().Join("libraries", "AudioZero.zip")
+	require.NoError(t, zipPath.Parent().MkdirAll())
+	downloadLib(t, url, zipPath)
+
+	_, stderr, err = cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.Error(t, err)
+	require.Contains(t, string(stderr), "--git-url and --zip-path are disabled by default, for more information see:")
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	// Verifies installation is successful when flags are enabled with env var
+	stdout, _, err := cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", gitUrl)
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+
+	stdout, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--zip-path", zipPath.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+
+	// Uninstall libraries to install them again
+	_, _, err = cli.Run("lib", "uninstall", "WiFi101", "AudioZero")
+	require.NoError(t, err)
+
+	// Verifies installation is successful when flags are enabled with settings file
+	_, _, err = cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	stdout, _, err = cli.Run("lib", "install", "--git-url", gitUrl)
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+
+	stdout, _, err = cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+}
+
+func TestInstallWithZipPath(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Initialize configs to enable --zip-path flag
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+	_, _, err := cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
+	require.NoError(t, err)
+
+	// Download a specific lib version
+	// Download library
+	url := "https://github.com/arduino-libraries/AudioZero/archive/refs/tags/1.1.1.zip"
+	zipPath := cli.DownloadDir().Join("libraries", "AudioZero.zip")
+	require.NoError(t, zipPath.Parent().MkdirAll())
+	downloadLib(t, url, zipPath)
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "AudioZero")
+	// Verifies library is not already installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Test zip-path install
+	stdout, _, err := cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk.")
+
+	// Verifies library is installed in expected path
+	require.DirExists(t, libInstallDir.String())
+	files, err := libInstallDir.ReadDirRecursive()
+	require.NoError(t, err)
+	require.Contains(t, files, libInstallDir.Join("examples", "SimpleAudioPlayerZero", "SimpleAudioPlayerZero.ino"))
+	require.Contains(t, files, libInstallDir.Join("src", "AudioZero.h"))
+	require.Contains(t, files, libInstallDir.Join("src", "AudioZero.cpp"))
+	require.Contains(t, files, libInstallDir.Join("keywords.txt"))
+	require.Contains(t, files, libInstallDir.Join("library.properties"))
+	require.Contains(t, files, libInstallDir.Join("README.adoc"))
+
+	// Reinstall library
+	_, _, err = cli.Run("lib", "install", "--zip-path", zipPath.String())
+	require.NoError(t, err)
+
+	// Verifies library remains installed
+	require.DirExists(t, libInstallDir.String())
+	files, err = libInstallDir.ReadDirRecursive()
+	require.NoError(t, err)
+	require.Contains(t, files, libInstallDir.Join("examples", "SimpleAudioPlayerZero", "SimpleAudioPlayerZero.ino"))
+	require.Contains(t, files, libInstallDir.Join("src", "AudioZero.h"))
+	require.Contains(t, files, libInstallDir.Join("src", "AudioZero.cpp"))
+	require.Contains(t, files, libInstallDir.Join("keywords.txt"))
+	require.Contains(t, files, libInstallDir.Join("library.properties"))
+	require.Contains(t, files, libInstallDir.Join("README.adoc"))
+}
+
+func TestInstallWithZipPathMultipleLibraries(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	// Downloads zips to be installed later
+	wifiZipPath := cli.DownloadDir().Join("libraries", "WiFi101-0.16.1.zip")
+	bleZipPath := cli.DownloadDir().Join("libraries", "ArduinoBLE-1.1.3.zip")
+	downloadLib(t, "https://github.com/arduino-libraries/WiFi101/archive/refs/tags/0.16.1.zip", wifiZipPath)
+	downloadLib(t, "https://github.com/arduino-libraries/ArduinoBLE/archive/refs/tags/1.1.3.zip", bleZipPath)
+
+	wifiInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	bleInstallDir := cli.SketchbookDir().Join("libraries", "ArduinoBLE")
+	// Verifies libraries are not installed
+	require.NoDirExists(t, wifiInstallDir.String())
+	require.NoDirExists(t, bleInstallDir.String())
+
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--zip-path", wifiZipPath.String(), bleZipPath.String())
+	require.NoError(t, err)
+
+	// Verifies libraries are installed
+	require.DirExists(t, wifiInstallDir.String())
+	require.DirExists(t, bleInstallDir.String())
+}
+
+func TestInstallWithGitUrlLocalFileUri(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("Using a file uri as git url doesn't work on Windows, " +
+			"this must be removed when this issue is fixed: https://github.com/go-git/go-git/issues/247")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	envVar := cli.GetDefaultEnv()
+	envVar["ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL"] = "true"
+
+	libInstallDir := cli.SketchbookDir().Join("libraries", "WiFi101")
+	// Verifies library is not installed
+	require.NoDirExists(t, libInstallDir.String())
+
+	// Clone repository locally
+	gitUrl := "https://github.com/arduino-libraries/WiFi101.git"
+	repoDir := cli.SketchbookDir().Join("WiFi101")
+	_, err := git.PlainClone(repoDir.String(), false, &git.CloneOptions{
+		URL: gitUrl,
+	})
+	require.NoError(t, err)
+
+	_, _, err = cli.RunWithCustomEnv(envVar, "lib", "install", "--git-url", "file://"+repoDir.String())
+	require.NoError(t, err)
+
+	// Verifies library is installed
+	require.DirExists(t, libInstallDir.String())
+}
diff --git a/test/testdata/fake-lib.zip b/internal/integrationtest/testdata/fake-lib.zip
similarity index 100%
rename from test/testdata/fake-lib.zip
rename to internal/integrationtest/testdata/fake-lib.zip
diff --git a/test/testdata/lib-without-header.zip b/internal/integrationtest/testdata/lib-without-header.zip
similarity index 100%
rename from test/testdata/lib-without-header.zip
rename to internal/integrationtest/testdata/lib-without-header.zip
diff --git a/test/testdata/lib-without-properties.zip b/internal/integrationtest/testdata/lib-without-properties.zip
similarity index 100%
rename from test/testdata/lib-without-properties.zip
rename to internal/integrationtest/testdata/lib-without-properties.zip
diff --git a/test/testdata/platform_with_bundled_library/boards.txt b/internal/integrationtest/testdata/platform_with_bundled_library/boards.txt
similarity index 100%
rename from test/testdata/platform_with_bundled_library/boards.txt
rename to internal/integrationtest/testdata/platform_with_bundled_library/boards.txt
diff --git a/test/testdata/platform_with_bundled_library/libraries/USBHost/library.properties b/internal/integrationtest/testdata/platform_with_bundled_library/libraries/USBHost/library.properties
similarity index 100%
rename from test/testdata/platform_with_bundled_library/libraries/USBHost/library.properties
rename to internal/integrationtest/testdata/platform_with_bundled_library/libraries/USBHost/library.properties
diff --git a/test/testdata/platform_with_bundled_library/platform.txt b/internal/integrationtest/testdata/platform_with_bundled_library/platform.txt
similarity index 100%
rename from test/testdata/platform_with_bundled_library/platform.txt
rename to internal/integrationtest/testdata/platform_with_bundled_library/platform.txt
diff --git a/test/test_lib.py b/test/test_lib.py
deleted file mode 100644
index 8446ea1dbe5..00000000000
--- a/test/test_lib.py
+++ /dev/null
@@ -1,480 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
-import platform
-
-import simplejson as json
-import pytest
-import shutil
-from git import Repo
-from pathlib import Path
-import tempfile
-import requests
-import zipfile
-import io
-import re
-
-
-# Util function to download library from URL
-def download_lib(url, download_dir):
-    tmp = Path(tempfile.TemporaryDirectory().name)
-    tmp.mkdir(parents=True, exist_ok=True)
-    regex = re.compile(r"^(.*)-[0-9]+.[0-9]+.[0-9]")
-    response = requests.get(url)
-    # Download and unzips library removing version suffix
-    with zipfile.ZipFile(io.BytesIO(response.content)) as thezip:
-        for zipinfo in thezip.infolist():
-            with thezip.open(zipinfo) as f:
-                dest_dir = tmp / regex.sub("\\g<1>", zipinfo.filename)
-                if zipinfo.is_dir():
-                    dest_dir.mkdir(parents=True, exist_ok=True)
-                else:
-                    dest_dir.write_bytes(f.read())
-
-    # Recreates zip with folder without version suffix
-    z = zipfile.ZipFile(download_dir, "w")
-    for f in tmp.glob("**/*"):
-        z.write(f, arcname=f.relative_to(tmp))
-    z.close()
-
-
-def test_install_git_url_and_zip_path_flags_visibility(run_command, data_dir, downloads_dir):
-    # Verifies installation fail because flags are not found
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-    res = run_command(["lib", "install", "--git-url", git_url])
-    assert res.failed
-    assert "--git-url and --zip-path are disabled by default, for more information see:" in res.stderr
-
-    # Download library
-    url = "https://github.com/arduino-libraries/AudioZero/archive/refs/tags/1.1.1.zip"
-    zip_path = Path(downloads_dir, "libraries", "AudioZero.zip")
-    zip_path.parent.mkdir(parents=True, exist_ok=True)
-    download_lib(url, zip_path)
-
-    res = run_command(["lib", "install", "--zip-path", zip_path])
-    assert res.failed
-    assert "--git-url and --zip-path are disabled by default, for more information see:" in res.stderr
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    # Verifies installation is successful when flags are enabled with env var
-    res = run_command(["lib", "install", "--git-url", git_url], custom_env=env)
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-    res = run_command(["lib", "install", "--zip-path", zip_path], custom_env=env)
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-    # Uninstall libraries to install them again
-    assert run_command(["lib", "uninstall", "WiFi101", "AudioZero"])
-
-    # Verifies installation is successful when flags are enabled with settings file
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    res = run_command(["lib", "install", "--git-url", git_url])
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-    res = run_command(["lib", "install", "--zip-path", zip_path])
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-
-def test_install_with_zip_path(run_command, data_dir, downloads_dir):
-    # Initialize configs to enable --zip-path flag
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    # Download a specific lib version
-    # Download library
-    url = "https://github.com/arduino-libraries/AudioZero/archive/refs/tags/1.1.1.zip"
-    zip_path = Path(downloads_dir, "libraries", "AudioZero.zip")
-    zip_path.parent.mkdir(parents=True, exist_ok=True)
-    download_lib(url, zip_path)
-
-    lib_install_dir = Path(data_dir, "libraries", "AudioZero")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    # Test zip-path install
-    res = run_command(["lib", "install", "--zip-path", zip_path])
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-    # Verifies library is installed in expected path
-    assert lib_install_dir.exists()
-    files = list(lib_install_dir.glob("**/*"))
-    assert lib_install_dir / "examples" / "SimpleAudioPlayerZero" / "SimpleAudioPlayerZero.ino" in files
-    assert lib_install_dir / "src" / "AudioZero.h" in files
-    assert lib_install_dir / "src" / "AudioZero.cpp" in files
-    assert lib_install_dir / "keywords.txt" in files
-    assert lib_install_dir / "library.properties" in files
-    assert lib_install_dir / "README.adoc" in files
-
-    # Reinstall library
-    assert run_command(["lib", "install", "--zip-path", zip_path])
-
-    # Verifies library remains installed
-    assert lib_install_dir.exists()
-    files = list(lib_install_dir.glob("**/*"))
-    assert lib_install_dir / "examples" / "SimpleAudioPlayerZero" / "SimpleAudioPlayerZero.ino" in files
-    assert lib_install_dir / "src" / "AudioZero.h" in files
-    assert lib_install_dir / "src" / "AudioZero.cpp" in files
-    assert lib_install_dir / "keywords.txt" in files
-    assert lib_install_dir / "library.properties" in files
-    assert lib_install_dir / "README.adoc" in files
-
-
-@pytest.mark.skipif(
-    platform.system() == "Windows",
-    reason="Using a file uri as git url doesn't work on Windows, "
-    + "this must be removed when this issue is fixed: https://github.com/go-git/go-git/issues/247",
-)
-def test_install_with_git_url_local_file_uri(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    lib_install_dir = Path(data_dir, "libraries", "WiFi101")
-    # Verifies library is not installed
-    assert not lib_install_dir.exists()
-
-    # Clone repository locally
-    git_url = "https://github.com/arduino-libraries/WiFi101.git"
-    repo_dir = Path(data_dir, "WiFi101")
-    assert Repo.clone_from(git_url, repo_dir)
-
-    assert run_command(["lib", "install", "--git-url", repo_dir.as_uri()], custom_env=env)
-
-    # Verifies library is installed
-    assert lib_install_dir.exists()
-
-
-def test_install_with_zip_path_multiple_libraries(run_command, downloads_dir, data_dir):
-    assert run_command(["update"])
-
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-
-    # Downloads zip to be installed later
-    wifi_zip_path = Path(downloads_dir, "libraries", "WiFi101-0.16.1.zip")
-    ble_zip_path = Path(downloads_dir, "libraries", "ArduinoBLE-1.1.3.zip")
-    download_lib("https://github.com/arduino-libraries/WiFi101/archive/refs/tags/0.16.1.zip", wifi_zip_path)
-    download_lib("https://github.com/arduino-libraries/ArduinoBLE/archive/refs/tags/1.1.3.zip", ble_zip_path)
-
-    wifi_install_dir = Path(data_dir, "libraries", "WiFi101")
-    ble_install_dir = Path(data_dir, "libraries", "ArduinoBLE")
-
-    # Verifies libraries are not installed
-    assert not wifi_install_dir.exists()
-    assert not ble_install_dir.exists()
-
-    assert run_command(["lib", "install", "--zip-path", wifi_zip_path, ble_zip_path], custom_env=env)
-
-    # Verifies library are installed
-    assert wifi_install_dir.exists()
-    assert ble_install_dir.exists()
-
-
-def test_lib_examples_with_case_mismatch(run_command, data_dir):
-    assert run_command(["update"])
-
-    assert run_command(["lib", "install", "WiFiManager@2.0.3-alpha"])
-
-    res = run_command(["lib", "examples", "WiFiManager", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    examples = data[0]["examples"]
-
-    assert len(examples) == 14
-
-    examples_path = Path(data_dir, "libraries", "WiFiManager", "examples")
-    # Verifies sketches with correct casing are listed
-    assert str(examples_path / "Advanced") in examples
-    assert str(examples_path / "AutoConnect" / "AutoConnectWithFeedbackLED") in examples
-    assert str(examples_path / "AutoConnect" / "AutoConnectWithFSParameters") in examples
-    assert str(examples_path / "AutoConnect" / "AutoConnectWithFSParametersAndCustomIP") in examples
-    assert str(examples_path / "Basic") in examples
-    assert str(examples_path / "DEV" / "OnDemandConfigPortal") in examples
-    assert str(examples_path / "NonBlocking" / "AutoConnectNonBlocking") in examples
-    assert str(examples_path / "NonBlocking" / "AutoConnectNonBlockingwParams") in examples
-    assert str(examples_path / "Old_examples" / "AutoConnectWithFeedback") in examples
-    assert str(examples_path / "Old_examples" / "AutoConnectWithReset") in examples
-    assert str(examples_path / "Old_examples" / "AutoConnectWithStaticIP") in examples
-    assert str(examples_path / "Old_examples" / "AutoConnectWithTimeout") in examples
-    assert str(examples_path / "OnDemand" / "OnDemandConfigPortal") in examples
-    assert str(examples_path / "ParamsChildClass") in examples
-
-    # Verifies sketches with wrong casing are not returned
-    assert str(examples_path / "NonBlocking" / "OnDemandNonBlocking") not in examples
-    assert str(examples_path / "OnDemand" / "OnDemandWebPortal") not in examples
-
-
-def test_lib_list_using_library_with_invalid_version(run_command, data_dir):
-    assert run_command(["update"])
-
-    # Install a library
-    assert run_command(["lib", "install", "WiFi101@0.16.1"])
-
-    # Verifies library is correctly returned
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    assert "0.16.1" == data[0]["library"]["version"]
-
-    # Changes the version of the currently installed library so that it's
-    # invalid
-    lib_path = Path(data_dir, "libraries", "WiFi101")
-    Path(lib_path, "library.properties").write_text("name=WiFi101\nversion=1.0001")
-
-    # Verifies version is now empty
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    assert "version" not in data[0]["library"]
-
-
-def test_lib_upgrade_using_library_with_invalid_version(run_command, data_dir):
-    assert run_command(["update"])
-
-    # Install a library
-    assert run_command(["lib", "install", "WiFi101@0.16.1"])
-
-    # Verifies library is correctly returned
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    assert "0.16.1" == data[0]["library"]["version"]
-
-    # Changes the version of the currently installed library so that it's
-    # invalid
-    lib_path = Path(data_dir, "libraries", "WiFi101")
-    Path(lib_path, "library.properties").write_text("name=WiFi101\nversion=1.0001")
-
-    # Verifies version is now empty
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    assert "version" not in data[0]["library"]
-
-    # Upgrade library
-    assert run_command(["lib", "upgrade", "WiFi101"])
-
-    # Verifies library has been updated
-    res = run_command(["lib", "list", "--format", "json"])
-    assert res.ok
-    data = json.loads(res.stdout)
-    assert len(data) == 1
-    assert "" != data[0]["library"]["version"]
-
-
-def test_install_zip_lib_with_macos_metadata(run_command, data_dir, downloads_dir):
-    # Initialize configs to enable --zip-path flag
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    lib_install_dir = Path(data_dir, "libraries", "fake-lib")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    zip_path = Path(__file__).parent / "testdata" / "fake-lib.zip"
-    # Test zip-path install
-    res = run_command(["lib", "install", "--zip-path", zip_path])
-    assert res.ok
-    assert "--git-url and --zip-path flags allow installing untrusted files, use it at your own risk." in res.stdout
-
-    # Verifies library is installed in expected path
-    assert lib_install_dir.exists()
-    files = list(lib_install_dir.glob("**/*"))
-    assert lib_install_dir / "library.properties" in files
-    assert lib_install_dir / "src" / "fake-lib.h" in files
-
-    # Reinstall library
-    assert run_command(["lib", "install", "--zip-path", zip_path])
-
-    # Verifies library remains installed
-    assert lib_install_dir.exists()
-    files = list(lib_install_dir.glob("**/*"))
-    assert lib_install_dir / "library.properties" in files
-    assert lib_install_dir / "src" / "fake-lib.h" in files
-
-
-def test_install_zip_invalid_library(run_command, data_dir, downloads_dir):
-    # Initialize configs to enable --zip-path flag
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    lib_install_dir = Path(data_dir, "libraries", "lib-without-header")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    zip_path = Path(__file__).parent / "testdata" / "lib-without-header.zip"
-    # Test zip-path install
-    res = run_command(["lib", "install", "--zip-path", zip_path])
-    assert res.failed
-    assert "library not valid" in res.stderr
-
-    lib_install_dir = Path(data_dir, "libraries", "lib-without-properties")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    zip_path = Path(__file__).parent / "testdata" / "lib-without-properties.zip"
-    # Test zip-path install
-    res = run_command(["lib", "install", "--zip-path", zip_path])
-    assert res.failed
-    assert "library not valid" in res.stderr
-
-
-def test_install_git_invalid_library(run_command, data_dir, downloads_dir):
-    # Initialize configs to enable --zip-path flag
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-        "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
-    }
-    assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
-
-    # Create fake library repository
-    repo_dir = Path(data_dir, "lib-without-header")
-    with Repo.init(repo_dir) as repo:
-        lib_properties = Path(repo_dir, "library.properties")
-        lib_properties.touch()
-        repo.index.add([str(lib_properties)])
-        repo.index.commit("First commit")
-
-    lib_install_dir = Path(data_dir, "libraries", "lib-without-header")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    res = run_command(["lib", "install", "--git-url", repo_dir], custom_env=env)
-    assert res.failed
-    assert "library not valid" in res.stderr
-    assert not lib_install_dir.exists()
-
-    # Create another fake library repository
-    repo_dir = Path(data_dir, "lib-without-properties")
-    with Repo.init(repo_dir) as repo:
-        lib_header = Path(repo_dir, "src", "lib-without-properties.h")
-        lib_header.parent.mkdir(parents=True, exist_ok=True)
-        lib_header.touch()
-        repo.index.add([str(lib_header)])
-        repo.index.commit("First commit")
-
-    lib_install_dir = Path(data_dir, "libraries", "lib-without-properties")
-    # Verifies library is not already installed
-    assert not lib_install_dir.exists()
-
-    res = run_command(["lib", "install", "--git-url", repo_dir], custom_env=env)
-    assert res.failed
-    assert "library not valid" in res.stderr
-    assert not lib_install_dir.exists()
-
-
-def test_upgrade_does_not_try_to_upgrade_bundled_core_libraries_in_sketchbook(run_command, data_dir):
-    test_platform_name = "platform_with_bundled_library"
-    platform_install_dir = Path(data_dir, "hardware", "arduino-beta-dev", test_platform_name)
-    platform_install_dir.mkdir(parents=True)
-
-    # Install platform in Sketchbook hardware dir
-    shutil.copytree(
-        Path(__file__).parent / "testdata" / test_platform_name,
-        platform_install_dir,
-        dirs_exist_ok=True,
-    )
-
-    assert run_command(["update"])
-
-    # Install latest version of library identical to one
-    # bundled with test platform
-    assert run_command(["lib", "install", "USBHost"])
-
-    res = run_command(["lib", "list", "--all", "--format", "json"])
-    assert res.ok
-    libs = json.loads(res.stdout)
-    assert len(libs) == 2
-    # Verify both libraries have the same name
-    assert libs[0]["library"]["name"] == "USBHost"
-    assert libs[1]["library"]["name"] == "USBHost"
-
-    res = run_command(["lib", "upgrade"])
-    assert res.ok
-    # Empty output means nothing has been updated as expected
-    assert res.stdout == ""
-
-
-def test_upgrade_does_not_try_to_upgrade_bundled_core_libraries(run_command, data_dir):
-    test_platform_name = "platform_with_bundled_library"
-    platform_install_dir = Path(data_dir, "packages", "arduino", "hardware", "arch", "4.2.0")
-    platform_install_dir.mkdir(parents=True)
-
-    # Simulate installation of a platform with arduino-cli
-    shutil.copytree(
-        Path(__file__).parent / "testdata" / test_platform_name,
-        platform_install_dir,
-        dirs_exist_ok=True,
-    )
-
-    assert run_command(["update"])
-
-    # Install latest version of library identical to one
-    # bundled with test platform
-    assert run_command(["lib", "install", "USBHost"])
-
-    res = run_command(["lib", "list", "--all", "--format", "json"])
-    assert res.ok
-    libs = json.loads(res.stdout)
-    assert len(libs) == 2
-    # Verify both libraries have the same name
-    assert libs[0]["library"]["name"] == "USBHost"
-    assert libs[1]["library"]["name"] == "USBHost"
-
-    res = run_command(["lib", "upgrade"])
-    assert res.ok
-    # Empty output means nothing has been updated as expected
-    assert res.stdout == ""

From f850706b15b31454afa8d56c79fa92c5e312724e Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Wed, 14 Dec 2022 08:46:28 +0100
Subject: [PATCH 021/606] [skip-changelog]Migrate tests from `upload_test.py`
 to `test_upload.go` (#2001)

* Migrate TestUpload from test_upload.py to upload_test.go

* Migrate TestUploadWithInputDirFlag from test_upload.py to upload_test.go

* Migrate TestUploadWithInputFileFlag from test_upload.py to upload_test.go

* Migrate TestCompileAndUploadCombo from test_upload.py to upload_test.go

* Migrate TestCompileAndUploadComboWithCustomBuildPath from test_upload.py to upload_test.go

* Migrate TestCompileAndUploadComboWithPdeExtension from test_upload.py to upload_test.go

* Migrate TestUploadSketchWithPdeExtension from test_upload.py to upload_test.go

* Migrate TestUploadWithInputDirContainingMultipleBinaries from test_upload.py to upload_test.go

* Migrate TestCompileAndUploadComboSketchWithMismatchedCasing from test_upload.py to upload_test.go

* Migrate TestUploadSketchWithMismatchedCasing from test_upload.py to upload_test.go

* Migrate TestUploadToPortWithBoardAutodetect from test_upload.py to upload_test.go

* Migrate TestCompileAndUploadToPortWithBoardAutodetect to upload_test.go and delete test_upload.py
---
 .../integrationtest/upload/upload_test.go     | 582 ++++++++++++++++++
 test/test_upload.py                           | 426 -------------
 2 files changed, 582 insertions(+), 426 deletions(-)
 create mode 100644 internal/integrationtest/upload/upload_test.go
 delete mode 100644 test/test_upload.py

diff --git a/internal/integrationtest/upload/upload_test.go b/internal/integrationtest/upload/upload_test.go
new file mode 100644
index 00000000000..f240b55c7a7
--- /dev/null
+++ b/internal/integrationtest/upload/upload_test.go
@@ -0,0 +1,582 @@
+// This file is part of arduino-cli.
+//
+// Copyright 2022 ARDUINO SA (http://www.arduino.cc/)
+//
+// This software is released under the GNU General Public License version 3,
+// which covers the main part of arduino-cli.
+// The terms of this license can be found at:
+// https://www.gnu.org/licenses/gpl-3.0.en.html
+//
+// You can be released from the requirements of the above licenses by purchasing
+// a commercial license. Buying such a license is mandatory if you want to
+// modify or otherwise use the software for commercial activities involving the
+// Arduino software without disclosing the source code of your own applications.
+// To purchase a commercial license, send an email to license@arduino.cc.
+
+package upload_test
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/arduino/arduino-cli/internal/integrationtest"
+	"github.com/arduino/go-paths-helper"
+	"github.com/stretchr/testify/require"
+	"go.bug.st/testifyjson/requirejson"
+)
+
+type board struct {
+	address      string
+	fqbn         string
+	pack         string
+	architecture string
+	id           string
+	core         string
+}
+
+func detectedBoards(t *testing.T, cli *integrationtest.ArduinoCLI) []board {
+	// This fixture provides a list of all the boards attached to the host.
+	// This fixture will parse the JSON output of `arduino-cli board list --format json`
+	//to extract all the connected boards data.
+
+	// :returns a list `Board` objects.
+
+	var boards []board
+	stdout, _, err := cli.Run("board", "list", "--format", "json")
+	require.NoError(t, err)
+	len, err := strconv.Atoi(requirejson.Parse(t, stdout).Query(".[] | .matching_boards | length").String())
+	require.NoError(t, err)
+	for i := 0; i < len; i++ {
+		fqbn := strings.Trim(requirejson.Parse(t, stdout).Query(".[] | .matching_boards | .["+fmt.Sprint(i)+"] | .fqbn").String(), "\"")
+		boards = append(boards, board{
+			address:      strings.Trim(requirejson.Parse(t, stdout).Query(".[] | .port | .address").String(), "\""),
+			fqbn:         fqbn,
+			pack:         strings.Split(fqbn, ":")[0],
+			architecture: strings.Split(fqbn, ":")[1],
+			id:           strings.Split(fqbn, ":")[2],
+			core:         strings.Split(fqbn, ":")[0] + ":" + strings.Split(fqbn, ":")[1],
+		})
+	}
+	return boards
+}
+
+func waitForBoard(t *testing.T, cli *integrationtest.ArduinoCLI) {
+	timeEnd := time.Now().Unix() + 10
+	for time.Now().Unix() < timeEnd {
+		stdout, _, err := cli.Run("board", "list", "--format", "json")
+		require.NoError(t, err)
+		len, err := strconv.Atoi(requirejson.Parse(t, stdout).Query("length").String())
+		require.NoError(t, err)
+		numBoards := 0
+		for i := 0; i < len; i++ {
+			numBoards, err = strconv.Atoi(requirejson.Parse(t, stdout).Query(".[] | .matching_boards | length").String())
+			require.NoError(t, err)
+			if numBoards > 0 {
+				break
+			}
+		}
+		if numBoards > 0 {
+			break
+		}
+	}
+}
+
+func TestUpload(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	for _, board := range detectedBoards(t, cli) {
+		// Download platform
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+		// Create a sketch
+		sketchName := "TestUploadSketch" + board.id
+		sketchPath := cli.SketchbookDir().Join(sketchName)
+		fqbn := board.fqbn
+		address := board.address
+		_, _, err = cli.Run("sketch", "new", sketchPath.String())
+		require.NoError(t, err)
+		// Build sketch
+		_, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String())
+		require.NoError(t, err)
+
+		// Verifies binaries are not exported
+		require.NoFileExists(t, sketchPath.Join("build").String())
+
+		// Upload without port must fail
+		_, _, err = cli.Run("upload", "-b", fqbn, sketchPath.String())
+		require.Error(t, err)
+
+		// Upload
+		_, _, err = cli.Run("upload", "-b", fqbn, "-p", address, sketchPath.String())
+		require.NoError(t, err)
+	}
+}
+
+func TestUploadWithInputDirFlag(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	for _, board := range detectedBoards(t, cli) {
+		// Download board platform
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Create a sketch
+		sketchName := "TestUploadSketch" + board.id
+		sketchPath := cli.SketchbookDir().Join(sketchName)
+		fqbn := board.fqbn
+		address := board.address
+		_, _, err = cli.Run("sketch", "new", sketchPath.String())
+		require.NoError(t, err)
+
+		// Build sketch and export binaries to custom directory
+		outputDir := cli.SketchbookDir().Join("test_dir", sketchName, "build")
+		_, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "--output-dir", outputDir.String())
+		require.NoError(t, err)
+
+		// Upload with --input-dir flag
+		_, _, err = cli.Run("upload", "-b", fqbn, "-p", address, "--input-dir", outputDir.String())
+		require.NoError(t, err)
+	}
+}
+
+func TestUploadWithInputFileFlag(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	for _, board := range detectedBoards(t, cli) {
+		// Download board platform
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Create a sketch
+		sketchName := "TestUploadSketch" + board.id
+		sketchPath := cli.SketchbookDir().Join(sketchName)
+		fqbn := board.fqbn
+		address := board.address
+		_, _, err = cli.Run("sketch", "new", sketchPath.String())
+		require.NoError(t, err)
+
+		// Build sketch and export binaries to custom directory
+		outputDir := cli.SketchbookDir().Join("test_dir", sketchName, "build")
+		_, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "--output-dir", outputDir.String())
+		require.NoError(t, err)
+
+		// We don't need a specific file when using the --input-file flag to upload since
+		// it's just used to calculate the directory, so it's enough to get a random file
+		// that's inside that directory
+		inputFile := outputDir.Join(sketchName + ".ino.bin")
+		// Upload using --input-file
+		_, _, err = cli.Run("upload", "-b", fqbn, "-p", address, "--input-file", inputFile.String())
+		require.NoError(t, err)
+	}
+}
+
+func TestCompileAndUploadCombo(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	// Create a test sketch
+	sketchName := "CompileAndUploadIntegrationTest"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+	sketchMainFile := sketchPath.Join(sketchName + ".ino")
+	stdout, _, err := cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+	require.Contains(t, string(stdout), "Sketch created in: "+sketchPath.String())
+
+	// Build sketch for each detected board
+	for _, board := range detectedBoards(t, cli) {
+		logFileName := strings.ReplaceAll(board.fqbn, ":", "-") + "-compile.log"
+		logFilePath := cli.SketchbookDir().Join(logFileName)
+
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		runTest := func(s string) {
+			waitForBoard(t, cli)
+			_, _, err := cli.Run("compile", "-b", board.fqbn, "--upload", "-p", board.address, s,
+				"--log-format", "json", "--log-file", logFilePath.String(), "--log-level", "trace")
+			require.NoError(t, err)
+			logJson, err := logFilePath.ReadFile()
+			require.NoError(t, err)
+
+			// check from the logs if the bin file were uploaded on the current board
+			logJson = []byte("[" + strings.ReplaceAll(strings.TrimSuffix(string(logJson), "\n"), "\n", ",") + "]")
+			traces := requirejson.Parse(t, logJson).Query("[ .[] | select(.level==\"trace\") | .msg ]").String()
+			traces = strings.ReplaceAll(traces, "\\\\", "\\")
+			require.Contains(t, traces, "Compile "+sketchPath.String()+" for "+board.fqbn+" started")
+			require.Contains(t, traces, "Compile "+sketchName+" for "+board.fqbn+" successful")
+			require.Contains(t, traces, "Upload "+sketchPath.String()+" on "+board.fqbn+" started")
+			require.Contains(t, traces, "Upload successful")
+		}
+
+		runTest(sketchPath.String())
+		runTest(sketchMainFile.String())
+	}
+}
+
+func TestCompileAndUploadComboWithCustomBuildPath(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// Init the environment explicitly
+	_, _, err := cli.Run("core", "update-index")
+	require.NoError(t, err)
+
+	// Create a test sketch
+	sketchName := "CompileAndUploadCustomBuildPathIntegrationTest"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	// Build sketch for each detected board
+	for _, board := range detectedBoards(t, cli) {
+		fqbnNormalized := strings.ReplaceAll(board.fqbn, ":", "-")
+		logFileName := fqbnNormalized + "-compile.log"
+		logFilePath := cli.SketchbookDir().Join(logFileName)
+
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		waitForBoard(t, cli)
+
+		buildPath := cli.SketchbookDir().Join("test_dir", fqbnNormalized, "build_dir")
+		_, _, err := cli.Run("compile", "-b", board.fqbn, "--upload", "-p", board.address, "--build-path", buildPath.String(),
+			sketchPath.String(), "--log-format", "json", "--log-file", logFilePath.String(), "--log-level", "trace")
+		require.NoError(t, err)
+		logJson, err := logFilePath.ReadFile()
+		require.NoError(t, err)
+
+		// check from the logs if the bin file were uploaded on the current board
+		logJson = []byte("[" + strings.ReplaceAll(strings.TrimSuffix(string(logJson), "\n"), "\n", ",") + "]")
+		traces := requirejson.Parse(t, logJson).Query("[ .[] | select(.level==\"trace\") | .msg ]").String()
+		traces = strings.ReplaceAll(traces, "\\\\", "\\")
+		require.Contains(t, traces, "Compile "+sketchPath.String()+" for "+board.fqbn+" started")
+		require.Contains(t, traces, "Compile "+sketchName+" for "+board.fqbn+" successful")
+		require.Contains(t, traces, "Upload "+sketchPath.String()+" on "+board.fqbn+" started")
+		require.Contains(t, traces, "Upload successful")
+	}
+}
+
+func TestCompileAndUploadComboSketchWithPdeExtension(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	sketchName := "CompileAndUploadPdeSketch"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+
+	// Create a test sketch
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	// Renames sketch file to pde
+	sketchFile := sketchPath.Join(sketchName + ".pde")
+	require.NoError(t, sketchPath.Join(sketchName+".ino").Rename(sketchFile))
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Build sketch and upload from folder
+		waitForBoard(t, cli)
+		_, stderr, err := cli.Run("compile", "--clean", "-b", board.fqbn, "-u", "-p", board.address, sketchPath.String())
+		require.NoError(t, err)
+		require.Contains(t, string(stderr), "Sketches with .pde extension are deprecated, please rename the following files to .ino")
+		require.Contains(t, string(stderr), sketchFile.String())
+
+		// Build sketch and upload from file
+		waitForBoard(t, cli)
+		_, stderr, err = cli.Run("compile", "--clean", "-b", board.fqbn, "-u", "-p", board.address, sketchFile.String())
+		require.NoError(t, err)
+		require.Contains(t, string(stderr), "Sketches with .pde extension are deprecated, please rename the following files to .ino")
+		require.Contains(t, string(stderr), sketchFile.String())
+	}
+}
+
+func TestUploadSketchWithPdeExtension(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	sketchName := "UploadPdeSketch"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+
+	// Create a test sketch
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	// Renames sketch file to pde
+	sketchFile := sketchPath.Join(sketchName + ".pde")
+	require.NoError(t, sketchPath.Join(sketchName+".ino").Rename(sketchFile))
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Compile sketch first
+		stdout, _, err := cli.Run("compile", "--clean", "-b", board.fqbn, sketchPath.String(), "--format", "json")
+		require.NoError(t, err)
+		buildDir := requirejson.Parse(t, stdout).Query(".builder_result | .build_path").String()
+		buildDir = strings.Trim(strings.ReplaceAll(buildDir, "\\\\", "\\"), "\"")
+
+		// Upload from sketch folder
+		waitForBoard(t, cli)
+		_, _, err = cli.Run("upload", "-b", board.fqbn, "-p", board.address, sketchPath.String())
+		require.NoError(t, err)
+
+		// Upload from sketch file
+		waitForBoard(t, cli)
+		_, _, err = cli.Run("upload", "-b", board.fqbn, "-p", board.address, sketchFile.String())
+		require.NoError(t, err)
+
+		waitForBoard(t, cli)
+		_, stderr, err := cli.Run("upload", "-b", board.fqbn, "-p", board.address, "--input-dir", buildDir)
+		require.NoError(t, err)
+		require.Contains(t, string(stderr), "Sketches with .pde extension are deprecated, please rename the following files to .ino:")
+
+		// Upload from binary file
+		waitForBoard(t, cli)
+		// We don't need a specific file when using the --input-file flag to upload since
+		// it's just used to calculate the directory, so it's enough to get a random file
+		// that's inside that directory
+		binaryFile := paths.New(buildDir, sketchName+".pde.bin")
+		_, stderr, err = cli.Run("upload", "-b", board.fqbn, "-p", board.address, "--input-file", binaryFile.String())
+		require.NoError(t, err)
+		require.Contains(t, string(stderr), "Sketches with .pde extension are deprecated, please rename the following files to .ino:")
+	}
+}
+
+func TestUploadWithInputDirContainingMultipleBinaries(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	// This tests verifies the behaviour outlined in this issue:
+	// https://github.com/arduino/arduino-cli/issues/765#issuecomment-699678646
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Create two different sketches
+	sketchOneName := "UploadMultipleBinariesSketchOne"
+	sketchOnePath := cli.SketchbookDir().Join(sketchOneName)
+	_, _, err = cli.Run("sketch", "new", sketchOnePath.String())
+	require.NoError(t, err)
+
+	sketchTwoName := "UploadMultipleBinariesSketchTwo"
+	sketchTwoPath := cli.SketchbookDir().Join(sketchTwoName)
+	_, _, err = cli.Run("sketch", "new", sketchTwoPath.String())
+	require.NoError(t, err)
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Compile both sketches and copy binaries in the same build directory
+		binariesDir := cli.SketchbookDir().Join("build", "BuiltBinaries")
+		_, _, err = cli.Run("compile", "--clean", "-b", board.fqbn, sketchOnePath.String(), "--build-path", binariesDir.String())
+		require.NoError(t, err)
+		stdout, _, err := cli.Run("compile", "--clean", "-b", board.fqbn, sketchTwoPath.String(), "--format", "json")
+		require.NoError(t, err)
+		buildDirTwo := requirejson.Parse(t, stdout).Query(".builder_result | .build_path").String()
+		buildDirTwo = strings.Trim(strings.ReplaceAll(buildDirTwo, "\\\\", "\\"), "\"")
+		require.NoError(t, paths.New(buildDirTwo).Join(sketchTwoName+".ino.bin").CopyTo(binariesDir.Join(sketchTwoName+".ino.bin")))
+
+		waitForBoard(t, cli)
+		// Verifies upload fails because multiple binaries are found
+		_, stderr, err := cli.Run("upload", "-b", board.fqbn, "-p", board.address, "--input-dir", binariesDir.String())
+		require.Error(t, err)
+		require.Contains(t, string(stderr), "Error during Upload: ")
+		require.Contains(t, string(stderr), "Error finding build artifacts: ")
+		require.Contains(t, string(stderr), "autodetect build artifact: ")
+		require.Contains(t, string(stderr), "multiple build artifacts found:")
+
+		// Copy binaries to folder with same name of a sketch
+		binariesDirSketch := cli.SketchbookDir().Join("build", "UploadMultipleBinariesSketchOne")
+		require.NoError(t, binariesDir.CopyDirTo(binariesDirSketch))
+
+		waitForBoard(t, cli)
+		// Verifies upload is successful using the binaries with the same name of the containing folder
+		_, _, err = cli.Run("upload", "-b", board.fqbn, "-p", board.address, "--input-dir", binariesDirSketch.String())
+		require.NoError(t, err)
+	}
+}
+
+func TestCompileAndUploadComboSketchWithMismatchedCasing(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Create a sketch
+	sketchName := "CompileUploadComboMismatchCasing"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	// Rename main .ino file so casing is different from sketch name
+	require.NoError(t, sketchPath.Join(sketchName+".ino").Rename(sketchPath.Join(strings.ToLower(sketchName)+".ino")))
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Try to compile
+		_, stderr, err := cli.Run("compile", "--clean", "-b", board.fqbn, "-u", "-p", board.address, sketchPath.String())
+		require.Error(t, err)
+		require.Contains(t, string(stderr), "Error opening sketch:")
+	}
+}
+
+func TestUploadSketchWithMismatchedCasing(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Create a sketch
+	sketchName := "UploadMismatchCasing"
+	sketchPath := cli.SketchbookDir().Join(sketchName)
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	// Rename main .ino file so casing is different from sketch name
+	require.NoError(t, sketchPath.Join(sketchName+".ino").Rename(sketchPath.Join(strings.ToLower(sketchName)+".ino")))
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		// Tries to upload given sketch, it has not been compiled but it fails even before
+		// searching for binaries since the sketch is not valid
+		_, stderr, err := cli.Run("upload", "-b", board.fqbn, "-p", board.address, sketchPath.String())
+		require.Error(t, err)
+		require.Contains(t, string(stderr), "Error during Upload:")
+	}
+}
+
+func TestUploadToPortWithBoardAutodetect(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Create a sketch
+	sketchPath := cli.SketchbookDir().Join("SketchSimple")
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		_, _, err = cli.Run("compile", "-b", board.fqbn, sketchPath.String())
+		require.NoError(t, err)
+
+		_, _, err = cli.Run("upload", "-p", board.address, sketchPath.String())
+		require.NoError(t, err)
+	}
+}
+
+func TestCompileAndUploadToPortWithBoardAutodetect(t *testing.T) {
+	if os.Getenv("CI") != "" {
+		t.Skip("VMs have no serial ports")
+	}
+
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("update")
+	require.NoError(t, err)
+
+	// Create a sketch
+	sketchPath := cli.SketchbookDir().Join("SketchSimple")
+	_, _, err = cli.Run("sketch", "new", sketchPath.String())
+	require.NoError(t, err)
+
+	for _, board := range detectedBoards(t, cli) {
+		// Install core
+		_, _, err = cli.Run("core", "install", board.core)
+		require.NoError(t, err)
+
+		_, _, err = cli.Run("compile", "-u", "-p", board.address, sketchPath.String())
+		require.NoError(t, err)
+	}
+}
diff --git a/test/test_upload.py b/test/test_upload.py
deleted file mode 100644
index 5e95eb67102..00000000000
--- a/test/test_upload.py
+++ /dev/null
@@ -1,426 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
-import os
-import shutil
-import json
-from pathlib import Path
-
-import pytest
-
-from .common import running_on_ci, parse_json_traces
-
-# Skip this module when running in CI environments
-pytestmark = pytest.mark.skipif(running_on_ci(), reason="VMs have no serial ports")
-
-
-def test_upload(run_command, data_dir, detected_boards):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    for board in detected_boards:
-        # Download platform
-        run_command(["core", "install", board.core])
-        # Create a sketch
-        sketch_name = f"TestUploadSketch{board.id}"
-        sketch_path = Path(data_dir, sketch_name)
-        fqbn = board.fqbn
-        address = board.address
-        assert run_command(["sketch", "new", sketch_path])
-        # Build sketch
-        assert run_command(["compile", "-b", fqbn, sketch_path])
-
-        # Verifies binaries are not exported
-        assert not (sketch_path / "build").exists()
-
-        # Upload without port must fail
-        assert not run_command(["upload", "-b", fqbn, sketch_path])
-
-        # Upload
-        assert run_command(["upload", "-b", fqbn, "-p", address, sketch_path])
-
-
-def test_upload_with_input_dir_flag(run_command, data_dir, detected_boards):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    for board in detected_boards:
-        # Download board platform
-        run_command(["core", "install", board.core])
-
-        # Create sketch
-        sketch_name = f"TestUploadInputDirSketch{board.id}"
-        sketch_path = Path(data_dir, sketch_name)
-        fqbn = board.fqbn
-        address = board.address
-        assert run_command(["sketch", "new", sketch_path])
-
-        # Build sketch and export binaries to custom directory
-        output_dir = Path(data_dir, "test_dir", sketch_name, "build")
-        assert run_command(["compile", "-b", fqbn, sketch_path, "--output-dir", output_dir])
-
-        # Upload with --input-dir flag
-        assert run_command(["upload", "-b", fqbn, "-p", address, "--input-dir", output_dir])
-
-
-def test_upload_with_input_file_flag(run_command, data_dir, detected_boards):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    for board in detected_boards:
-        # Download board platform
-        run_command(["core", "install", board.core])
-
-        # Create sketch
-        sketch_name = f"TestUploadInputFileSketch{board.id}"
-        sketch_path = Path(data_dir, sketch_name)
-        fqbn = board.fqbn
-        address = board.address
-        assert run_command(["sketch", "new", sketch_path])
-
-        # Build sketch and export binaries to custom directory
-        output_dir = Path(data_dir, "test_dir", sketch_name, "build")
-        assert run_command(["compile", "-b", fqbn, sketch_path, "--output-dir", output_dir])
-
-        # We don't need a specific file when using the --input-file flag to upload since
-        # it's just used to calculate the directory, so it's enough to get a random file
-        # that's inside that directory
-        input_file = next(output_dir.glob(f"{sketch_name}.ino.*"))
-        # Upload using --input-file
-        assert run_command(["upload", "-b", fqbn, "-p", address, "--input-file", input_file])
-
-
-def test_upload_after_attach(run_command, data_dir, detected_boards):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    for board in detected_boards:
-        # Download core
-        run_command(["core", "install", board.core])
-        # Create a sketch
-        sketch_path = os.path.join(data_dir, "foo")
-        assert run_command(["sketch", "new", sketch_path])
-        assert run_command(["board", "attach", "-p", board.address, sketch_path])
-        # Build sketch
-        assert run_command(["compile", sketch_path])
-        # Upload
-        assert run_command(["upload", sketch_path])
-
-
-def test_compile_and_upload_combo(run_command, data_dir, detected_boards, wait_for_board):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    # Install required core(s)
-    run_command(["core", "install", "arduino:avr@1.8.3"])
-    run_command(["core", "install", "arduino:samd@1.8.6"])
-
-    # Create a test sketch
-    sketch_name = "CompileAndUploadIntegrationTest"
-    sketch_path = os.path.join(data_dir, sketch_name)
-    sketch_main_file = os.path.join(sketch_path, sketch_name + ".ino")
-    result = run_command(["sketch", "new", sketch_path])
-    assert result.ok
-    assert "Sketch created in: {}".format(sketch_path) in result.stdout
-
-    # Build sketch for each detected board
-    for board in detected_boards:
-        log_file_name = "{fqbn}-compile.log".format(fqbn=board.fqbn.replace(":", "-"))
-        log_file_path = os.path.join(data_dir, log_file_name)
-        command_log_flags = ["--log-format", "json", "--log-file", log_file_path, "--log-level", "trace"]
-
-        def run_test(s):
-            wait_for_board()
-            result = run_command(["compile", "-b", board.fqbn, "--upload", "-p", board.address, s] + command_log_flags)
-            print(result.stderr)
-            assert result.ok
-
-            # check from the logs if the bin file were uploaded on the current board
-            log_json = open(log_file_path, "r")
-            traces = parse_json_traces(log_json.readlines())
-            assert f"Compile {sketch_path} for {board.fqbn} started" in traces
-            assert f"Compile {sketch_name} for {board.fqbn} successful" in traces
-            assert f"Upload {sketch_path} on {board.fqbn} started" in traces
-            assert "Upload successful" in traces
-
-        run_test(sketch_path)
-        run_test(sketch_main_file)
-
-
-def test_compile_and_upload_combo_with_custom_build_path(run_command, data_dir, detected_boards, wait_for_board):
-    # Init the environment explicitly
-    run_command(["core", "update-index"])
-
-    # Install required core(s)
-    run_command(["core", "install", "arduino:avr@1.8.3"])
-    run_command(["core", "install", "arduino:samd@1.8.6"])
-
-    sketch_name = "CompileAndUploadCustomBuildPathIntegrationTest"
-    sketch_path = Path(data_dir, sketch_name)
-    assert run_command(["sketch", "new", sketch_path])
-
-    for board in detected_boards:
-        fqbn_normalized = board.fqbn.replace(":", "-")
-        log_file_name = f"{fqbn_normalized}-compile.log"
-        log_file = Path(data_dir, log_file_name)
-        command_log_flags = ["--log-format", "json", "--log-file", log_file, "--log-level", "trace"]
-
-        wait_for_board()
-
-        build_path = Path(data_dir, "test_dir", fqbn_normalized, "build_dir")
-        result = run_command(
-            [
-                "compile",
-                "-b",
-                board.fqbn,
-                "--upload",
-                "-p",
-                board.address,
-                "--build-path",
-                build_path,
-                sketch_path,
-            ]
-            + command_log_flags
-        )
-        print(result.stderr)
-        assert result.ok
-
-        # check from the logs if the bin file were uploaded on the current board
-        log_json = open(log_file, "r")
-        traces = parse_json_traces(log_json.readlines())
-        assert f"Compile {sketch_path} for {board.fqbn} started" in traces
-        assert f"Compile {sketch_name} for {board.fqbn} successful" in traces
-        assert f"Upload {sketch_path} on {board.fqbn} started" in traces
-        assert "Upload successful" in traces
-
-
-def test_compile_and_upload_combo_sketch_with_pde_extension(run_command, data_dir, detected_boards, wait_for_board):
-    assert run_command(["update"])
-
-    sketch_name = "CompileAndUploadPdeSketch"
-    sketch_path = Path(data_dir, sketch_name)
-
-    # Create a test sketch
-    assert run_command(["sketch", "new", sketch_path])
-
-    # Renames sketch file to pde
-    sketch_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        # Build sketch and upload from folder
-        wait_for_board()
-        res = run_command(["compile", "--clean", "-b", board.fqbn, "-u", "-p", board.address, sketch_path])
-        assert res.ok
-        assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
-        assert str(sketch_file) in res.stderr
-
-        # Build sketch and upload from file
-        wait_for_board()
-        res = run_command(["compile", "--clean", "-b", board.fqbn, "-u", "-p", board.address, sketch_file])
-        assert res.ok
-        assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
-        assert str(sketch_file) in res.stderr
-
-
-def test_upload_sketch_with_pde_extension(run_command, data_dir, detected_boards, wait_for_board):
-    assert run_command(["update"])
-
-    sketch_name = "UploadPdeSketch"
-    sketch_path = Path(data_dir, sketch_name)
-
-    # Create a test sketch
-    assert run_command(["sketch", "new", sketch_path])
-
-    # Renames sketch file to pde
-    sketch_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        # Compile sketch first
-        res = run_command(["compile", "--clean", "-b", board.fqbn, sketch_path, "--format", "json"])
-        assert res.ok
-        data = json.loads(res.stdout)
-        build_dir = Path(data["builder_result"]["build_path"])
-
-        # Upload from sketch folder
-        wait_for_board()
-        assert run_command(["upload", "-b", board.fqbn, "-p", board.address, sketch_path])
-
-        # Upload from sketch file
-        wait_for_board()
-        assert run_command(["upload", "-b", board.fqbn, "-p", board.address, sketch_file])
-
-        wait_for_board()
-        res = run_command(["upload", "-b", board.fqbn, "-p", board.address, "--input-dir", build_dir])
-        assert (
-            "Sketches with .pde extension are deprecated, please rename the following files to .ino:" not in res.stderr
-        )
-
-        # Upload from binary file
-        wait_for_board()
-        # We don't need a specific file when using the --input-file flag to upload since
-        # it's just used to calculate the directory, so it's enough to get a random file
-        # that's inside that directory
-        binary_file = next(build_dir.glob(f"{sketch_name}.pde.*"))
-        res = run_command(["upload", "-b", board.fqbn, "-p", board.address, "--input-file", binary_file])
-        assert (
-            "Sketches with .pde extension are deprecated, please rename the following files to .ino:" not in res.stderr
-        )
-
-
-def test_upload_with_input_dir_containing_multiple_binaries(run_command, data_dir, detected_boards, wait_for_board):
-    # This tests verifies the behaviour outlined in this issue:
-    # https://github.com/arduino/arduino-cli/issues/765#issuecomment-699678646
-    assert run_command(["update"])
-
-    # Create a two different sketches
-    sketch_one_name = "UploadMultipleBinariesSketchOne"
-    sketch_one_path = Path(data_dir, sketch_one_name)
-    assert run_command(["sketch", "new", sketch_one_path])
-
-    sketch_two_name = "UploadMultipleBinariesSketchTwo"
-    sketch_two_path = Path(data_dir, sketch_two_name)
-    assert run_command(["sketch", "new", sketch_two_path])
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        # Compile both sketches and copy binaries in the same directory same build directory
-        res = run_command(["compile", "--clean", "-b", board.fqbn, sketch_one_path, "--format", "json"])
-        assert res.ok
-        data = json.loads(res.stdout)
-        build_dir_one = Path(data["builder_result"]["build_path"])
-        res = run_command(["compile", "--clean", "-b", board.fqbn, sketch_two_path, "--format", "json"])
-        assert res.ok
-        data = json.loads(res.stdout)
-        build_dir_two = Path(data["builder_result"]["build_path"])
-
-        # Copy binaries to same folder
-        binaries_dir = Path(data_dir, "build", "BuiltBinaries")
-        shutil.copytree(build_dir_one, binaries_dir, dirs_exist_ok=True)
-        shutil.copytree(build_dir_two, binaries_dir, dirs_exist_ok=True)
-
-        wait_for_board()
-        # Verifies upload fails because multiple binaries are found
-        res = run_command(["upload", "-b", board.fqbn, "-p", board.address, "--input-dir", binaries_dir])
-        assert res.failed
-        assert (
-            "Error during Upload: "
-            + "Error finding build artifacts: "
-            + "autodetect build artifact: "
-            + "multiple build artifacts found:"
-            in res.stderr
-        )
-
-        # Copy binaries to folder with same name of a sketch
-        binaries_dir = Path(data_dir, "build", "UploadMultipleBinariesSketchOne")
-        shutil.copytree(build_dir_one, binaries_dir, dirs_exist_ok=True)
-        shutil.copytree(build_dir_two, binaries_dir, dirs_exist_ok=True)
-
-        wait_for_board()
-        # Verifies upload is successful using the binaries with the same name of the containing folder
-        res = run_command(["upload", "-b", board.fqbn, "-p", board.address, "--input-dir", binaries_dir])
-        assert (
-            "Sketches with .pde extension are deprecated, please rename the following files to .ino:" not in res.stderr
-        )
-
-
-def test_compile_and_upload_combo_sketch_with_mismatched_casing(run_command, data_dir, detected_boards, wait_for_board):
-    assert run_command(["update"])
-
-    # Create a sketch
-    sketch_name = "CompileUploadComboMismatchCasing"
-    sketch_path = Path(data_dir, sketch_name)
-    assert run_command(["sketch", "new", sketch_path])
-
-    # Rename main .ino file so casing is different from sketch name
-    Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name.lower()}.ino")
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        # Try to compile
-        res = run_command(["compile", "--clean", "-b", board.fqbn, "-u", "-p", board.address, sketch_path])
-        assert res.failed
-        assert "Error opening sketch:" in res.stderr
-
-
-def test_upload_sketch_with_mismatched_casing(run_command, data_dir, detected_boards, wait_for_board):
-    assert run_command(["update"])
-
-    # Create a sketch
-    sketch_name = "UploadMismatchCasing"
-    sketch_path = Path(data_dir, sketch_name)
-    assert run_command(["sketch", "new", sketch_path])
-
-    # Rename main .ino file so casing is different from sketch name
-    Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name.lower()}.ino")
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        # Tries to upload given sketch, it has not been compiled but it fails even before
-        # searching for binaries since the sketch is not valid
-        res = run_command(["upload", "-b", board.fqbn, "-p", board.address, sketch_path])
-        assert res.failed
-        assert "Error during Upload:" in res.stderr
-
-
-def test_upload_to_port_with_board_autodetect(run_command, data_dir, detected_boards):
-    assert run_command(["update"])
-
-    # Create a sketch
-    sketch_name = "SketchSimple"
-    sketch_path = Path(data_dir, sketch_name)
-    assert run_command(["sketch", "new", sketch_path])
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        assert run_command(["compile", "-b", board.fqbn, sketch_path])
-
-        res = run_command(["upload", "-p", board.address, sketch_path])
-        assert res.ok
-
-
-def test_compile_and_upload_to_port_with_board_autodetect(run_command, data_dir, detected_boards):
-    assert run_command(["update"])
-
-    # Create a sketch
-    sketch_name = "SketchSimple"
-    sketch_path = Path(data_dir, sketch_name)
-    assert run_command(["sketch", "new", sketch_path])
-
-    for board in detected_boards:
-        # Install core
-        core = ":".join(board.fqbn.split(":")[:2])
-        assert run_command(["core", "install", core])
-
-        res = run_command(["compile", "-u", "-p", board.address, sketch_path])
-        assert res.ok

From b6cc517d68874795b60a0a4bfe04b068bf8540ee Mon Sep 17 00:00:00 2001
From: MatteoPologruto <109663225+MatteoPologruto@users.noreply.github.com>
Date: Fri, 16 Dec 2022 10:03:51 +0100
Subject: [PATCH 022/606] [skip-changelog] Remove python testsuite and the
 related workflow (#2011)

* Remove python testsuite and the related workflows

* Update documentation according to the removal of the python testsuite

* Remove `check-python-task` and the related unused dependencies
---
 .flake8                                       |   16 -
 .github/tools/get_integration_tests.py        |   11 -
 .github/workflows/check-python-task.yml       |   86 -
 .../workflows/test-go-integration-task.yml    |  124 -
 README.md                                     |    1 -
 Taskfile.yml                                  |   28 +-
 docs/CONTRIBUTING.md                          |   53 +-
 .../integrationtest}/testdata/core.zip        |  Bin
 .../integrationtest}/testdata/evil.zip        |  Bin
 .../integrationtest/testdata/test_index.json  |   10 +-
 poetry.lock                                   |  973 +----
 pyproject.toml                                |   19 -
 test/README.md                                |    6 -
 test/__init__.py                              |   14 -
 test/common.py                                |   37 -
 test/conftest.py                              |  252 --
 test/pytest.ini                               |   15 -
 test/testdata/Arduino_TensorFlowLite.zip      |  Bin 3892384 -> 0 bytes
 test/testdata/boards.local.txt                |   26 -
 .../boards.local.txt                          |   11 -
 .../platform.local.txt                        |    8 -
 .../sketch_simple.ino.hex                     |  679 ----
 .../sketch_simple.ino.map                     | 3389 -----------------
 .../arduino.avr.uno/sketch_simple.ino.eep     |    1 -
 .../arduino.avr.uno/sketch_simple.ino.hex     |   29 -
 .../sketch_simple.ino.with_bootloader.hex     |   63 -
 test/testdata/sketch_simple/doc.txt           |    0
 test/testdata/sketch_simple/header.h          |    1 -
 test/testdata/sketch_simple/merged_sketch.txt |   15 -
 test/testdata/sketch_simple/old.pde           |    0
 test/testdata/sketch_simple/other.ino         |    3 -
 test/testdata/sketch_simple/s_file.S          |    0
 test/testdata/sketch_simple/sketch_simple.ino |    7 -
 test/testdata/sketch_simple/src/helper.h      |    0
 test/testdata/test_index.json                 |  210 -
 35 files changed, 223 insertions(+), 5864 deletions(-)
 delete mode 100644 .flake8
 delete mode 100644 .github/tools/get_integration_tests.py
 delete mode 100644 .github/workflows/check-python-task.yml
 delete mode 100644 .github/workflows/test-go-integration-task.yml
 rename {test => internal/integrationtest}/testdata/core.zip (100%)
 rename {test => internal/integrationtest}/testdata/evil.zip (100%)
 delete mode 100644 test/README.md
 delete mode 100644 test/__init__.py
 delete mode 100644 test/common.py
 delete mode 100644 test/conftest.py
 delete mode 100644 test/pytest.ini
 delete mode 100644 test/testdata/Arduino_TensorFlowLite.zip
 delete mode 100644 test/testdata/boards.local.txt
 delete mode 100644 test/testdata/platform_with_secure_boot/boards.local.txt
 delete mode 100644 test/testdata/platform_with_secure_boot/platform.local.txt
 delete mode 100644 test/testdata/sketch_simple/build/adafruit.samd.adafruit_feather_m0/sketch_simple.ino.hex
 delete mode 100644 test/testdata/sketch_simple/build/adafruit.samd.adafruit_feather_m0/sketch_simple.ino.map
 delete mode 100644 test/testdata/sketch_simple/build/arduino.avr.uno/sketch_simple.ino.eep
 delete mode 100644 test/testdata/sketch_simple/build/arduino.avr.uno/sketch_simple.ino.hex
 delete mode 100644 test/testdata/sketch_simple/build/arduino.avr.uno/sketch_simple.ino.with_bootloader.hex
 delete mode 100644 test/testdata/sketch_simple/doc.txt
 delete mode 100644 test/testdata/sketch_simple/header.h
 delete mode 100644 test/testdata/sketch_simple/merged_sketch.txt
 delete mode 100644 test/testdata/sketch_simple/old.pde
 delete mode 100644 test/testdata/sketch_simple/other.ino
 delete mode 100644 test/testdata/sketch_simple/s_file.S
 delete mode 100644 test/testdata/sketch_simple/sketch_simple.ino
 delete mode 100644 test/testdata/sketch_simple/src/helper.h
 delete mode 100644 test/testdata/test_index.json

diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 2f6e2a453d7..00000000000
--- a/.flake8
+++ /dev/null
@@ -1,16 +0,0 @@
-# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-python/.flake8
-# See: https://flake8.pycqa.org/en/latest/user/configuration.html
-# The code style defined in this file is the official standardized style to be used in all Arduino tooling projects and
-# should not be modified.
-
-[flake8]
-doctests = True
-per-file-ignores =
-    test/test_upload_mock.py:E501
-ignore =
-    E741,
-    # W503 and W504 are mutually exclusive. PEP 8 recommends line break before.
-    W503
-max-complexity = 10
-max-line-length = 120
-select = E,W,F,C,N
diff --git a/.github/tools/get_integration_tests.py b/.github/tools/get_integration_tests.py
deleted file mode 100644
index 93e94ab6c7b..00000000000
--- a/.github/tools/get_integration_tests.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from pathlib import Path
-import json
-
-
-if __name__ == "__main__":
-    import sys
-
-    tests_path = sys.argv[1]
-
-    test_files = [str(f) for f in Path(tests_path).glob("test_*.py")]
-    print(json.dumps(test_files))
diff --git a/.github/workflows/check-python-task.yml b/.github/workflows/check-python-task.yml
deleted file mode 100644
index 81762a78443..00000000000
--- a/.github/workflows/check-python-task.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/check-python-task.md
-name: Check Python
-
-env:
-  # See: https://github.com/actions/setup-python/tree/main#available-versions-of-python
-  PYTHON_VERSION: "3.9"
-
-# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
-on:
-  push:
-    paths:
-      - ".github/workflows/check-python-task.ya?ml"
-      - "**/.flake8"
-      - "**/poetry.lock"
-      - "**/pyproject.toml"
-      - "**/setup.cfg"
-      - "Taskfile.ya?ml"
-      - "**/tox.ini"
-      - "**.py"
-  pull_request:
-    paths:
-      - ".github/workflows/check-python-task.ya?ml"
-      - "**/.flake8"
-      - "**/poetry.lock"
-      - "**/pyproject.toml"
-      - "**/setup.cfg"
-      - "Taskfile.ya?ml"
-      - "**/tox.ini"
-      - "**.py"
-  workflow_dispatch:
-  repository_dispatch:
-
-jobs:
-  lint:
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout repository
-        uses: actions/checkout@v3
-
-      - name: Install Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: ${{ env.PYTHON_VERSION }}
-
-      - name: Install Poetry
-        run: pip install poetry
-
-      - name: Install Task
-        uses: arduino/setup-task@v1
-        with:
-          repo-token: ${{ secrets.GITHUB_TOKEN }}
-          version: 3.x
-
-      - name: Run flake8
-        uses: liskin/gh-problem-matcher-wrap@v2
-        with:
-          linters: flake8
-          run: task python:lint
-
-  formatting:
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Checkout repository
-        uses: actions/checkout@v3
-
-      - name: Install Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: ${{ env.PYTHON_VERSION }}
-
-      - name: Install Poetry
-        run: pip install poetry
-
-      - name: Install Task
-        uses: arduino/setup-task@v1
-        with:
-          repo-token: ${{ secrets.GITHUB_TOKEN }}
-          version: 3.x
-
-      - name: Format Python code
-        run: task python:format
-
-      - name: Check formatting
-        run: git diff --color --exit-code
diff --git a/.github/workflows/test-go-integration-task.yml b/.github/workflows/test-go-integration-task.yml
deleted file mode 100644
index 8964517f84d..00000000000
--- a/.github/workflows/test-go-integration-task.yml
+++ /dev/null
@@ -1,124 +0,0 @@
-# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/test-go-integration-task.md
-name: Test Integration
-
-env:
-  # See: https://github.com/actions/setup-go/tree/main#supported-version-syntax
-  GO_VERSION: "1.17"
-  # See: https://github.com/actions/setup-python/tree/main#available-versions-of-python
-  PYTHON_VERSION: "3.9"
-
-# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
-on:
-  create:
-  push:
-    paths:
-      - ".github/workflows/test-go-integration-task.ya?ml"
-      - "Taskfile.ya?ml"
-      - "**.go"
-      - "go.mod"
-      - "go.sum"
-      - "poetry.lock"
-      - "pyproject.toml"
-      - "test/**"
-  pull_request:
-    paths:
-      - ".github/workflows/test-go-integration-task.ya?ml"
-      - "Taskfile.ya?ml"
-      - "**.go"
-      - "go.mod"
-      - "go.sum"
-      - "poetry.lock"
-      - "pyproject.toml"
-      - "test/**"
-  workflow_dispatch:
-  repository_dispatch:
-
-jobs:
-  run-determination:
-    runs-on: ubuntu-latest
-    outputs:
-      result: ${{ steps.determination.outputs.result }}
-    steps:
-      - name: Determine if the rest of the workflow should run
-        id: determination
-        run: |
-          RELEASE_BRANCH_REGEX="refs/heads/[0-9]+.[0-9]+.x"
-          # The `create` event trigger doesn't support `branches` filters, so it's necessary to use Bash instead.
-          if [[ \
-            "${{ github.event_name }}" != "create" || \
-            "${{ github.ref }}" =~ $RELEASE_BRANCH_REGEX \
-          ]]; then
-            # Run the other jobs.
-            RESULT="true"
-          else
-            # There is no need to run the other jobs.
-            RESULT="false"
-          fi
-
-          echo "result=$RESULT" >> $GITHUB_OUTPUT
-
-  tests-collector:
-    runs-on: ubuntu-latest
-    needs: run-determination
-    if: needs.run-determination.outputs.result == 'true'
-    outputs:
-      tests-data: ${{ steps.collection.outputs.tests-data }}
-    steps:
-      - name: Checkout repository
-        uses: actions/checkout@v3
-
-      - name: Collect tests
-        id: collection
-        run: |
-          echo "tests-data=$(python .github/tools/get_integration_tests.py ./test/)" >> $GITHUB_OUTPUT
-
-  test:
-    needs: tests-collector
-    strategy:
-      matrix:
-        operating-system:
-          - ubuntu-latest
-          - windows-latest
-          - macos-latest
-        tests: ${{ fromJSON(needs.tests-collector.outputs.tests-data) }}
-
-    runs-on: ${{ matrix.operating-system }}
-
-    env:
-      ARDUINO_CLI_USER_AGENT_EXTENSION: ${{ secrets.CLOUDFLARE_SPAMCHECK_BYPASS_TOKEN }}
-
-    steps:
-      # By default, actions/checkout converts the repo's LF line endings to CRLF on the Windows runner.
-      - name: Disable EOL conversions
-        run: git config --global core.autocrlf false
-
-      - name: Checkout repository
-        uses: actions/checkout@v3
-
-      - name: Install Go
-        uses: actions/setup-go@v3
-        with:
-          go-version: ${{ env.GO_VERSION }}
-
-      - name: Install Python
-        uses: actions/setup-python@v4
-        with:
-          python-version: ${{ env.PYTHON_VERSION }}
-
-      - name: Install Poetry
-        run: pip install poetry
-
-      - name: Install Task
-        uses: arduino/setup-task@v1
-        with:
-          repo-token: ${{ secrets.GITHUB_TOKEN }}
-          version: 3.x
-
-      - name: Build Arduino CLI
-        run: task go:build
-
-      - name: Install poetry deps
-        run: task poetry:install-deps
-
-      - name: Run integration tests
-        run: poetry run pytest ${{ matrix.tests }}
diff --git a/README.md b/README.md
index 050ffe316b0..0f96633766e 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,6 @@ Arduino CLI is an all-in-one solution that provides Boards/Library Managers, ske
 and many other tools needed to use any Arduino compatible board and platform from command line or machine interfaces.
 
 [![Test Go status](https://github.com/arduino/arduino-cli/actions/workflows/test-go-task.yml/badge.svg)](https://github.com/arduino/arduino-cli/actions/workflows/test-go-task.yml)
-[![Test Integration status](https://github.com/arduino/arduino-cli/actions/workflows/test-go-integration-task.yml/badge.svg)](https://github.com/arduino/arduino-cli/actions/workflows/test-go-integration-task.yml)
 [![Publish Nightly Build status](https://github.com/arduino/arduino-cli/actions/workflows/publish-go-nightly-task.yml/badge.svg)](https://github.com/arduino/arduino-cli/actions/workflows/publish-go-nightly-task.yml)
 [![Deploy Website status](https://github.com/arduino/arduino-cli/actions/workflows/deploy-cobra-mkdocs-versioned-poetry.yml/badge.svg)](https://github.com/arduino/arduino-cli/actions/workflows/deploy-cobra-mkdocs-versioned-poetry.yml)
 [![Codecov](https://codecov.io/gh/arduino/arduino-cli/branch/main/graph/badge.svg)](https://codecov.io/gh/arduino/arduino-cli)
diff --git a/Taskfile.yml b/Taskfile.yml
index a143e51a286..0a37a4a8a76 100755
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -122,15 +122,6 @@ tasks:
           {{default .DEFAULT_INTEGRATIONTEST_GO_PACKAGES .GO_PACKAGES}} \
           {{.TEST_LDFLAGS}}
 
-  # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-go-integration-task/Taskfile.yml
-  go:test-integration:
-    desc: Run integration tests
-    deps:
-      - task: go:build
-      - task: poetry:install-deps
-    cmds:
-      - poetry run pytest test
-
   # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-go-task/Taskfile.yml
   go:vet:
     desc: Check for errors in Go code
@@ -244,22 +235,6 @@ tasks:
     cmds:
       - clang-format -i rpc/cc/arduino/cli/*/*/*.proto
 
-  # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-python-task/Taskfile.yml
-  python:format:
-    desc: Format Python files
-    deps:
-      - task: poetry:install-deps
-    cmds:
-      - poetry run black .
-
-  # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/check-python-task/Taskfile.yml
-  python:lint:
-    desc: Lint Python code
-    deps:
-      - task: poetry:install-deps
-    cmds:
-      - poetry run flake8 --show-source
-
   build:
     desc: Build the project
     deps:
@@ -269,7 +244,7 @@ tasks:
     desc: Run the full testsuite, `legacy` will be skipped
     cmds:
       - task: go:test
-      - task: go:test-integration
+      - task: go:integration-test
 
   test-legacy:
     desc: Run tests for the `legacy` package
@@ -297,7 +272,6 @@ tasks:
     cmds:
       - task: go:vet
       - task: go:lint
-      - task: python:lint
       - task: protoc:check
 
   check-legacy:
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 56048aafb32..bcde8955f7b 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -76,7 +76,6 @@ To build the Arduino CLI from sources you need the following tools to be availab
 If you want to run integration tests you will also need:
 
 - A serial port with an Arduino board attached
-- A working [Python][3] environment, version 3.8 or later
 
 If you're working on the gRPC interface you will also have to:
 
@@ -115,7 +114,7 @@ task go:test
 To run integration tests (these will take some time and require special setup, see following paragraph):
 
 ```shell
-task go:test-integration
+task go:integration-test
 ```
 
 #### Running only some tests
@@ -163,65 +162,29 @@ the above requirements.
 
 ##### Software requirements for running integration tests:
 
-A working Python environment. Chances are that you already have Python installed in your system, if this is not the case
-you can [download][3] the official distribution or use the package manager provided by your Operating System.
-
-Some dependencies need to be installed before running the tests and to avoid polluting your global Python environment
-with dependencies that might be only used by the Arduino CLI, to do so we use [Poetry][poetry-website]. First you need
-to install it (you might need to `sudo` the following command):
-
-```shell
-pip3 install --user poetry
-```
-
-For more installation options read the [official documentation][poetry-docs].
+A working Go environment. Chances are that you already have Go installed in your system, if this is not the case you can
+[download][1] the official distribution or use the package manager provided by your Operating System.
 
 #### Running tests
 
 After the software requirements have been installed you should be able to run the tests with:
 
 ```shell
-task go:test-integration
+task go:integration-test
 ```
 
-This will automatically install the necessary dependencies, if not already installed, and run the integration tests
-automatically.
+This will run the integration tests automatically.
 
-To run specific modules you must run `pytest` from the virtual environment created by Poetry.
+To run specific packages you must run `go test`.
 
 ```shell
-poetry run pytest test/test_lib.py
+go test -v github.com/arduino/arduino-cli/internal/integrationtest/lib
 ```
 
 To run very specific test functions:
 
 ```shell
-poetry run pytest test/test_lib.py::test_list
-```
-
-You can avoid writing the `poetry run` prefix each time by creating a new shell inside the virtual environment:
-
-```shell
-poetry shell
-pytest test_lib.py
-pytest test_lib.py::test_list
-```
-
-#### Linting and formatting
-
-When editing any Python file in the project remember to run linting checks with:
-
-```shell
-task python:lint
-```
-
-This will run `flake8` automatically and return any error in the code formatting, if not already installed it will also
-install integration tests dependencies.
-
-In case of linting errors you should be able to solve most of them by automatically formatting with:
-
-```shell
-task python:format
+go test -v github.com/arduino/arduino-cli/internal/integrationtest/lib -run TestLibUpgradeCommand
 ```
 
 ### Dependency license metadata
diff --git a/test/testdata/core.zip b/internal/integrationtest/testdata/core.zip
similarity index 100%
rename from test/testdata/core.zip
rename to internal/integrationtest/testdata/core.zip
diff --git a/test/testdata/evil.zip b/internal/integrationtest/testdata/evil.zip
similarity index 100%
rename from test/testdata/evil.zip
rename to internal/integrationtest/testdata/evil.zip
diff --git a/internal/integrationtest/testdata/test_index.json b/internal/integrationtest/testdata/test_index.json
index f5b5c6c35bd..63f2672a2f0 100644
--- a/internal/integrationtest/testdata/test_index.json
+++ b/internal/integrationtest/testdata/test_index.json
@@ -12,7 +12,7 @@
           "help": {
             "online": "https://github.com/Arduino/arduino-cli"
           },
-          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/core.zip",
+          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/internal/integrationtest/testdata/core.zip",
           "checksum": "SHA-256:6a338cf4d6d501176a2d352c87a8d72ac7488b8c5b82cdf2a4e2cef630391092",
           "name": "test_core",
           "version": "1.0.0",
@@ -31,7 +31,7 @@
           "help": {
             "online": "https://github.com/Arduino/arduino-cli"
           },
-          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/core.zip",
+          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/internal/integrationtest/testdata/core.zip",
           "checksum": "SHA-256:6a338cf4d6d501176a2d352c87a8d72ac7488b8c5b82cdf2a4e2cef630391092",
           "name": "test_core",
           "version": "2.0.0",
@@ -65,7 +65,7 @@
           "help": {
             "online": "https://github.com/Arduino/arduino-cli"
           },
-          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/evil.zip",
+          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/internal/integrationtest/testdata/evil.zip",
           "checksum": "SHA-256:9b85dfe23f13318efc0e541327f584a0f3674a773d46a7eb8b25f0f408d07f96",
           "name": "zipslip",
           "version": "1.0.0",
@@ -96,7 +96,7 @@
           "help": {
             "online": "https://github.com/Arduino/arduino-cli"
           },
-          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/core.zip",
+          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/internal/integrationtest/testdata/core.zip",
           "checksum": "SHA-256:1a338cf4d6d501176a2d352c87a8d72ac7488b8c5b82cdf2a4e2cef630391092",
           "name": "zipslip",
           "version": "1.0.0",
@@ -189,7 +189,7 @@
           "help": {
             "online": "https://github.com/Arduino/arduino-cli"
           },
-          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/test/testdata/core.zip",
+          "url": "https://raw.githubusercontent.com/arduino/arduino-cli/master/internal/integrationtest/testdata/core.zip",
           "checksum": "SHA-256:6a338cf4d6d501176a2d352c87a8d72ac7488b8c5b82cdf2a4e2cef630391092",
           "name": "Platform",
           "version": "1.2.3",
diff --git a/poetry.lock b/poetry.lock
index 0f0f5465be0..e3c37013c9e 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,65 +1,4 @@
-[[package]]
-name = "atomicwrites"
-version = "1.4.0"
-description = "Atomic file writes."
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[[package]]
-name = "attrs"
-version = "21.4.0"
-description = "Classes Without Boilerplate"
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[package.extras]
-dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"]
-docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
-tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"]
-tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"]
-
-[[package]]
-name = "black"
-version = "22.3.0"
-description = "The uncompromising code formatter."
-category = "dev"
-optional = false
-python-versions = ">=3.6.2"
-
-[package.dependencies]
-click = ">=8.0.0"
-mypy-extensions = ">=0.4.3"
-pathspec = ">=0.9.0"
-platformdirs = ">=2"
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
-
-[package.extras]
-colorama = ["colorama (>=0.4.3)"]
-d = ["aiohttp (>=3.7.4)"]
-jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
-uvloop = ["uvloop (>=0.15.2)"]
-
-[[package]]
-name = "certifi"
-version = "2022.12.7"
-description = "Python package for providing Mozilla's CA Bundle."
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[[package]]
-name = "charset-normalizer"
-version = "2.0.12"
-description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-category = "main"
-optional = false
-python-versions = ">=3.5.0"
-
-[package.extras]
-unicode-backport = ["unicodedata2"]
+# This file is automatically @generated by Poetry and should not be changed by hand.
 
 [[package]]
 name = "click"
@@ -68,6 +7,10 @@ description = "Composable command line interface toolkit"
 category = "dev"
 optional = false
 python-versions = ">=3.7"
+files = [
+    {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
+    {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+]
 
 [package.dependencies]
 colorama = {version = "*", markers = "platform_system == \"Windows\""}
@@ -76,56 +19,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
 name = "colorama"
 version = "0.4.4"
 description = "Cross-platform colored terminal text."
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[[package]]
-name = "execnet"
-version = "1.9.0"
-description = "execnet: rapid multi-Python deployment"
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[package.extras]
-testing = ["pre-commit"]
-
-[[package]]
-name = "filelock"
-version = "3.7.0"
-description = "A platform independent file lock."
-category = "main"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
-testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
-
-[[package]]
-name = "flake8"
-version = "3.9.2"
-description = "the modular source code checker: pep8 pyflakes and co"
-category = "dev"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-
-[package.dependencies]
-mccabe = ">=0.6.0,<0.7.0"
-pycodestyle = ">=2.7.0,<2.8.0"
-pyflakes = ">=2.3.0,<2.4.0"
-
-[[package]]
-name = "flake8-polyfill"
-version = "1.0.2"
-description = "Polyfill package for Flake8 plugins"
 category = "dev"
 optional = false
-python-versions = "*"
-
-[package.dependencies]
-flake8 = "*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+    {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
+    {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
+]
 
 [[package]]
 name = "ghp-import"
@@ -134,6 +34,10 @@ description = "Copy your docs directly to the gh-pages branch."
 category = "dev"
 optional = false
 python-versions = "*"
+files = [
+    {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
+    {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
+]
 
 [package.dependencies]
 python-dateutil = ">=2.8.1"
@@ -145,32 +49,32 @@ dev = ["flake8", "markdown", "twine", "wheel"]
 name = "gitdb"
 version = "4.0.9"
 description = "Git Object Database"
-category = "main"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
+    {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
+]
 
 [package.dependencies]
 smmap = ">=3.0.1,<6"
 
 [[package]]
 name = "gitpython"
-version = "3.1.27"
+version = "3.1.29"
 description = "GitPython is a python library used to interact with Git repositories"
-category = "main"
+category = "dev"
 optional = false
 python-versions = ">=3.7"
+files = [
+    {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"},
+    {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"},
+]
 
 [package.dependencies]
 gitdb = ">=4.0.1,<5"
 
-[[package]]
-name = "idna"
-version = "3.3"
-description = "Internationalized Domain Names in Applications (IDNA)"
-category = "main"
-optional = false
-python-versions = ">=3.5"
-
 [[package]]
 name = "importlib-metadata"
 version = "4.11.4"
@@ -178,6 +82,10 @@ description = "Read metadata from Python packages"
 category = "dev"
 optional = false
 python-versions = ">=3.7"
+files = [
+    {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"},
+    {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"},
+]
 
 [package.dependencies]
 zipp = ">=0.5"
@@ -187,22 +95,6 @@ docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
 perf = ["ipython"]
 testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
 
-[[package]]
-name = "iniconfig"
-version = "1.1.1"
-description = "iniconfig: brain-dead simple config-ini parsing"
-category = "main"
-optional = false
-python-versions = "*"
-
-[[package]]
-name = "invoke"
-version = "1.4.1"
-description = "Pythonic task execution"
-category = "main"
-optional = false
-python-versions = "*"
-
 [[package]]
 name = "jinja2"
 version = "3.1.2"
@@ -210,6 +102,10 @@ description = "A very fast and expressive template engine."
 category = "dev"
 optional = false
 python-versions = ">=3.7"
+files = [
+    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
 
 [package.dependencies]
 MarkupSafe = ">=2.0"
@@ -224,6 +120,10 @@ description = "Python implementation of Markdown."
 category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"},
+    {file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"},
+]
 
 [package.dependencies]
 importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
@@ -238,14 +138,48 @@ description = "Safely add untrusted strings to HTML/XML markup."
 category = "dev"
 optional = false
 python-versions = ">=3.7"
-
-[[package]]
-name = "mccabe"
-version = "0.6.1"
-description = "McCabe checker, plugin for flake8"
-category = "dev"
-optional = false
-python-versions = "*"
+files = [
+    {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
+    {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
+    {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
+    {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
+    {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
+    {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
+]
 
 [[package]]
 name = "mdx-truly-sane-lists"
@@ -254,6 +188,10 @@ description = "Extension for Python-Markdown that makes lists truly sane. Custom
 category = "dev"
 optional = false
 python-versions = "*"
+files = [
+    {file = "mdx_truly_sane_lists-1.2-py3-none-any.whl", hash = "sha256:cc8bfa00f331403504e12377a9c94e6b40fc7db031e283316baeeeeac68f1da9"},
+    {file = "mdx_truly_sane_lists-1.2.tar.gz", hash = "sha256:4600ade0fbd452db8233e25d644b62f59b2798e40595ea2e1923e29bc40c5b98"},
+]
 
 [package.dependencies]
 Markdown = ">=2.6"
@@ -265,6 +203,10 @@ description = "A deep merge function for 🐍."
 category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
+    {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
+]
 
 [[package]]
 name = "mike"
@@ -273,6 +215,10 @@ description = "Manage multiple versions of your MkDocs-powered documentation"
 category = "dev"
 optional = false
 python-versions = "*"
+files = [
+    {file = "mike-1.1.2-py3-none-any.whl", hash = "sha256:4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca"},
+    {file = "mike-1.1.2.tar.gz", hash = "sha256:56c3f1794c2d0b5fdccfa9b9487beb013ca813de2e3ad0744724e9d34d40b77b"},
+]
 
 [package.dependencies]
 jinja2 = "*"
@@ -291,6 +237,10 @@ description = "Project documentation with Markdown."
 category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "mkdocs-1.3.0-py3-none-any.whl", hash = "sha256:26bd2b03d739ac57a3e6eed0b7bcc86168703b719c27b99ad6ca91dc439aacde"},
+    {file = "mkdocs-1.3.0.tar.gz", hash = "sha256:b504405b04da38795fec9b2e5e28f6aa3a73bb0960cb6d5d27ead28952bd35ea"},
+]
 
 [package.dependencies]
 click = ">=3.3"
@@ -314,6 +264,10 @@ description = "A Material Design theme for MkDocs"
 category = "dev"
 optional = false
 python-versions = "*"
+files = [
+    {file = "mkdocs-material-7.3.6.tar.gz", hash = "sha256:1b1dbd8ef2508b358d93af55a5c5db3f141c95667fad802301ec621c40c7c217"},
+    {file = "mkdocs_material-7.3.6-py2.py3-none-any.whl", hash = "sha256:1b6b3e9e09f922c2d7f1160fe15c8f43d4adc0d6fb81aa6ff0cbc7ef5b78ec75"},
+]
 
 [package.dependencies]
 jinja2 = ">=2.11.1"
@@ -330,101 +284,26 @@ description = "Extension pack for Python Markdown."
 category = "dev"
 optional = false
 python-versions = ">=3.6"
-
-[[package]]
-name = "more-itertools"
-version = "8.13.0"
-description = "More routines for operating on iterables, beyond itertools"
-category = "main"
-optional = false
-python-versions = ">=3.5"
-
-[[package]]
-name = "mypy-extensions"
-version = "0.4.3"
-description = "Experimental type system extensions for programs checked with the mypy typechecker."
-category = "dev"
-optional = false
-python-versions = "*"
+files = [
+    {file = "mkdocs-material-extensions-1.0.3.tar.gz", hash = "sha256:bfd24dfdef7b41c312ede42648f9eb83476ea168ec163b613f9abd12bbfddba2"},
+    {file = "mkdocs_material_extensions-1.0.3-py3-none-any.whl", hash = "sha256:a82b70e533ce060b2a5d9eb2bc2e1be201cf61f901f93704b4acf6e3d5983a44"},
+]
 
 [[package]]
 name = "packaging"
 version = "21.3"
 description = "Core utilities for Python packages"
-category = "main"
+category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
+    {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
+]
 
 [package.dependencies]
 pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
 
-[[package]]
-name = "pathspec"
-version = "0.9.0"
-description = "Utility library for gitignore style pattern matching of file paths."
-category = "dev"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-
-[[package]]
-name = "pep8-naming"
-version = "0.12.1"
-description = "Check PEP-8 naming conventions, plugin for flake8"
-category = "dev"
-optional = false
-python-versions = "*"
-
-[package.dependencies]
-flake8 = ">=3.9.1"
-flake8-polyfill = ">=1.0.2,<2"
-
-[[package]]
-name = "platformdirs"
-version = "2.5.2"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"]
-test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
-
-[[package]]
-name = "pluggy"
-version = "0.13.1"
-description = "plugin and hook calling mechanisms for python"
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[package.extras]
-dev = ["pre-commit", "tox"]
-
-[[package]]
-name = "py"
-version = "1.11.0"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-
-[[package]]
-name = "pycodestyle"
-version = "2.7.0"
-description = "Python style guide checker"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[[package]]
-name = "pyflakes"
-version = "2.3.1"
-description = "passive checker of Python programs"
-category = "dev"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
 [[package]]
 name = "pygments"
 version = "2.12.0"
@@ -432,6 +311,10 @@ description = "Pygments is a syntax highlighting package written in Python."
 category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
+    {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"},
+]
 
 [[package]]
 name = "pymdown-extensions"
@@ -440,6 +323,10 @@ description = "Extension pack for Python Markdown."
 category = "dev"
 optional = false
 python-versions = ">=3.7"
+files = [
+    {file = "pymdown_extensions-9.4-py3-none-any.whl", hash = "sha256:5b7432456bf555ce2b0ab3c2439401084cda8110f24f6b3ecef952b8313dfa1b"},
+    {file = "pymdown_extensions-9.4.tar.gz", hash = "sha256:1baa22a60550f731630474cad28feb0405c8101f1a7ddc3ec0ed86ee510bcc43"},
+]
 
 [package.dependencies]
 markdown = ">=3.2"
@@ -448,100 +335,17 @@ markdown = ">=3.2"
 name = "pyparsing"
 version = "3.0.9"
 description = "pyparsing module - Classes and methods to define and execute parsing grammars"
-category = "main"
+category = "dev"
 optional = false
 python-versions = ">=3.6.8"
+files = [
+    {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
+    {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
+]
 
 [package.extras]
 diagrams = ["jinja2", "railroad-diagrams"]
 
-[[package]]
-name = "pyserial"
-version = "3.4"
-description = "Python Serial Port Extension"
-category = "main"
-optional = false
-python-versions = "*"
-
-[[package]]
-name = "pytest"
-version = "6.0.2"
-description = "pytest: simple powerful testing with Python"
-category = "main"
-optional = false
-python-versions = ">=3.5"
-
-[package.dependencies]
-atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
-attrs = ">=17.4.0"
-colorama = {version = "*", markers = "sys_platform == \"win32\""}
-iniconfig = "*"
-more-itertools = ">=4.0.0"
-packaging = "*"
-pluggy = ">=0.12,<1.0"
-py = ">=1.8.2"
-toml = "*"
-
-[package.extras]
-checkqa-mypy = ["mypy (==0.780)"]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
-
-[[package]]
-name = "pytest-forked"
-version = "1.4.0"
-description = "run tests in isolated forked subprocesses"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-py = "*"
-pytest = ">=3.10"
-
-[[package]]
-name = "pytest-httpserver"
-version = "0.3.8"
-description = "pytest-httpserver is a httpserver for pytest"
-category = "main"
-optional = false
-python-versions = ">=3.4"
-
-[package.dependencies]
-werkzeug = "*"
-
-[package.extras]
-dev = ["autopep8", "coverage", "flake8", "ipdb", "pytest", "pytest-cov", "reno", "requests", "sphinx", "sphinx-rtd-theme", "wheel"]
-test = ["coverage", "pytest", "pytest-cov", "requests"]
-
-[[package]]
-name = "pytest-timeout"
-version = "1.3.4"
-description = "py.test plugin to abort hanging tests"
-category = "main"
-optional = false
-python-versions = "*"
-
-[package.dependencies]
-pytest = ">=3.6.0"
-
-[[package]]
-name = "pytest-xdist"
-version = "2.4.0"
-description = "pytest xdist plugin for distributed testing and loop-on-failing modes"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-execnet = ">=1.1"
-pytest = ">=6.0.0"
-pytest-forked = "*"
-
-[package.extras]
-psutil = ["psutil (>=3.0)"]
-setproctitle = ["setproctitle"]
-testing = ["filelock"]
-
 [[package]]
 name = "python-dateutil"
 version = "2.8.2"
@@ -549,17 +353,63 @@ description = "Extensions to the standard Python datetime module"
 category = "dev"
 optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+    {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
+    {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+]
 
 [package.dependencies]
 six = ">=1.5"
 
 [[package]]
 name = "pyyaml"
-version = "5.4"
+version = "6.0"
 description = "YAML parser and emitter for Python"
-category = "main"
+category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+python-versions = ">=3.6"
+files = [
+    {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
+    {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
+    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
+    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
+    {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
+    {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
+    {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
+    {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
+    {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
+    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
+    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
+    {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
+    {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
+    {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
+    {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
+    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
+    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
+    {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
+    {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
+    {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
+    {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
+    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
+    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
+    {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
+    {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
+    {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
+    {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
+    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
+    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
+    {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
+    {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
+    {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
+    {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
+    {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
+    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
+    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
+    {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
+    {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
+    {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
+    {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
+]
 
 [[package]]
 name = "pyyaml-env-tag"
@@ -568,44 +418,14 @@ description = "A custom YAML tag for referencing environment variables in YAML f
 category = "dev"
 optional = false
 python-versions = ">=3.6"
+files = [
+    {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
+    {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
+]
 
 [package.dependencies]
 pyyaml = "*"
 
-[[package]]
-name = "requests"
-version = "2.27.1"
-description = "Python HTTP for Humans."
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
-
-[package.dependencies]
-certifi = ">=2017.4.17"
-charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""}
-idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""}
-urllib3 = ">=1.21.1,<1.27"
-
-[package.extras]
-socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
-use-chardet-on-py3 = ["chardet (>=3.0.2,<5)"]
-
-[[package]]
-name = "semver"
-version = "2.13.0"
-description = "Python helper for Semantic Versioning (http://semver.org/)"
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-
-[[package]]
-name = "simplejson"
-version = "3.17.0"
-description = "Simple, fast, extensible JSON encoder/decoder for Python"
-category = "main"
-optional = false
-python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*"
-
 [[package]]
 name = "six"
 version = "1.16.0"
@@ -613,51 +433,22 @@ description = "Python 2 and 3 compatibility utilities"
 category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+    {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+    {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
 
 [[package]]
 name = "smmap"
 version = "5.0.0"
 description = "A pure Python implementation of a sliding window memory map manager"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[[package]]
-name = "toml"
-version = "0.10.2"
-description = "Python Library for Tom's Obvious, Minimal Language"
-category = "main"
-optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-
-[[package]]
-name = "tomli"
-version = "2.0.1"
-description = "A lil' TOML parser"
 category = "dev"
 optional = false
-python-versions = ">=3.7"
-
-[[package]]
-name = "typing-extensions"
-version = "4.2.0"
-description = "Backported and Experimental Type Hints for Python 3.7+"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[[package]]
-name = "urllib3"
-version = "1.26.9"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
-category = "main"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
-
-[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
-secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"]
-socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+python-versions = ">=3.6"
+files = [
+    {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
+    {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
+]
 
 [[package]]
 name = "verspec"
@@ -666,6 +457,10 @@ description = "Flexible version handling"
 category = "dev"
 optional = false
 python-versions = "*"
+files = [
+    {file = "verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31"},
+    {file = "verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e"},
+]
 
 [package.extras]
 test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"]
@@ -677,373 +472,7 @@ description = "Filesystem events monitoring"
 category = "dev"
 optional = false
 python-versions = ">=3.6"
-
-[package.extras]
-watchmedo = ["PyYAML (>=3.10)"]
-
-[[package]]
-name = "werkzeug"
-version = "2.1.2"
-description = "The comprehensive WSGI web application library."
-category = "main"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-watchdog = ["watchdog"]
-
-[[package]]
-name = "zipp"
-version = "3.8.0"
-description = "Backport of pathlib-compatible object wrapper for zip files"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-
-[package.extras]
-docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
-testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
-
-[metadata]
-lock-version = "1.1"
-python-versions = ">=3.8, !=3.9.7, <4"
-content-hash = "02d695d90b699667497c5bc6052db88a854d2cdc931e90876a9622116d8cac10"
-
-[metadata.files]
-atomicwrites = [
-    {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
-    {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
-]
-attrs = [
-    {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
-    {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
-]
-black = [
-    {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"},
-    {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"},
-    {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"},
-    {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"},
-    {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"},
-    {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"},
-    {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"},
-    {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"},
-    {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"},
-    {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"},
-    {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"},
-    {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"},
-    {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"},
-    {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"},
-    {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"},
-    {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"},
-    {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"},
-    {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"},
-    {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"},
-    {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"},
-    {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"},
-    {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"},
-    {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"},
-]
-certifi = [
-    {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
-    {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
-]
-charset-normalizer = [
-    {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"},
-    {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"},
-]
-click = [
-    {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
-    {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
-]
-colorama = [
-    {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
-    {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
-]
-execnet = [
-    {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"},
-    {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"},
-]
-filelock = [
-    {file = "filelock-3.7.0-py3-none-any.whl", hash = "sha256:c7b5fdb219b398a5b28c8e4c1893ef5f98ece6a38c6ab2c22e26ec161556fed6"},
-    {file = "filelock-3.7.0.tar.gz", hash = "sha256:b795f1b42a61bbf8ec7113c341dad679d772567b936fbd1bf43c9a238e673e20"},
-]
-flake8 = [
-    {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
-    {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
-]
-flake8-polyfill = [
-    {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"},
-    {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"},
-]
-ghp-import = [
-    {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
-    {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
-]
-gitdb = [
-    {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
-    {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
-]
-gitpython = [
-    {file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"},
-    {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"},
-]
-idna = [
-    {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
-    {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
-]
-importlib-metadata = [
-    {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"},
-    {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"},
-]
-iniconfig = [
-    {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
-    {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
-]
-invoke = [
-    {file = "invoke-1.4.1-py2-none-any.whl", hash = "sha256:93e12876d88130c8e0d7fd6618dd5387d6b36da55ad541481dfa5e001656f134"},
-    {file = "invoke-1.4.1-py3-none-any.whl", hash = "sha256:87b3ef9d72a1667e104f89b159eaf8a514dbf2f3576885b2bbdefe74c3fb2132"},
-    {file = "invoke-1.4.1.tar.gz", hash = "sha256:de3f23bfe669e3db1085789fd859eb8ca8e0c5d9c20811e2407fa042e8a5e15d"},
-]
-jinja2 = [
-    {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
-    {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
-]
-markdown = [
-    {file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"},
-    {file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"},
-]
-markupsafe = [
-    {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
-    {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
-    {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
-    {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
-    {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
-    {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
-]
-mccabe = [
-    {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
-    {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
-]
-mdx-truly-sane-lists = [
-    {file = "mdx_truly_sane_lists-1.2-py3-none-any.whl", hash = "sha256:cc8bfa00f331403504e12377a9c94e6b40fc7db031e283316baeeeeac68f1da9"},
-    {file = "mdx_truly_sane_lists-1.2.tar.gz", hash = "sha256:4600ade0fbd452db8233e25d644b62f59b2798e40595ea2e1923e29bc40c5b98"},
-]
-mergedeep = [
-    {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
-    {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
-]
-mike = [
-    {file = "mike-1.1.2-py3-none-any.whl", hash = "sha256:4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca"},
-    {file = "mike-1.1.2.tar.gz", hash = "sha256:56c3f1794c2d0b5fdccfa9b9487beb013ca813de2e3ad0744724e9d34d40b77b"},
-]
-mkdocs = [
-    {file = "mkdocs-1.3.0-py3-none-any.whl", hash = "sha256:26bd2b03d739ac57a3e6eed0b7bcc86168703b719c27b99ad6ca91dc439aacde"},
-    {file = "mkdocs-1.3.0.tar.gz", hash = "sha256:b504405b04da38795fec9b2e5e28f6aa3a73bb0960cb6d5d27ead28952bd35ea"},
-]
-mkdocs-material = [
-    {file = "mkdocs-material-7.3.6.tar.gz", hash = "sha256:1b1dbd8ef2508b358d93af55a5c5db3f141c95667fad802301ec621c40c7c217"},
-    {file = "mkdocs_material-7.3.6-py2.py3-none-any.whl", hash = "sha256:1b6b3e9e09f922c2d7f1160fe15c8f43d4adc0d6fb81aa6ff0cbc7ef5b78ec75"},
-]
-mkdocs-material-extensions = [
-    {file = "mkdocs-material-extensions-1.0.3.tar.gz", hash = "sha256:bfd24dfdef7b41c312ede42648f9eb83476ea168ec163b613f9abd12bbfddba2"},
-    {file = "mkdocs_material_extensions-1.0.3-py3-none-any.whl", hash = "sha256:a82b70e533ce060b2a5d9eb2bc2e1be201cf61f901f93704b4acf6e3d5983a44"},
-]
-more-itertools = [
-    {file = "more-itertools-8.13.0.tar.gz", hash = "sha256:a42901a0a5b169d925f6f217cd5a190e32ef54360905b9c39ee7db5313bfec0f"},
-    {file = "more_itertools-8.13.0-py3-none-any.whl", hash = "sha256:c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb"},
-]
-mypy-extensions = [
-    {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
-    {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
-]
-packaging = [
-    {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
-    {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
-]
-pathspec = [
-    {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
-    {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
-]
-pep8-naming = [
-    {file = "pep8-naming-0.12.1.tar.gz", hash = "sha256:bb2455947757d162aa4cad55dba4ce029005cd1692f2899a21d51d8630ca7841"},
-    {file = "pep8_naming-0.12.1-py2.py3-none-any.whl", hash = "sha256:4a8daeaeb33cfcde779309fc0c9c0a68a3bbe2ad8a8308b763c5068f86eb9f37"},
-]
-platformdirs = [
-    {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
-    {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
-]
-pluggy = [
-    {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
-    {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
-]
-py = [
-    {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
-    {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
-]
-pycodestyle = [
-    {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
-    {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
-]
-pyflakes = [
-    {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
-    {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
-]
-pygments = [
-    {file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
-    {file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"},
-]
-pymdown-extensions = [
-    {file = "pymdown_extensions-9.4-py3-none-any.whl", hash = "sha256:5b7432456bf555ce2b0ab3c2439401084cda8110f24f6b3ecef952b8313dfa1b"},
-    {file = "pymdown_extensions-9.4.tar.gz", hash = "sha256:1baa22a60550f731630474cad28feb0405c8101f1a7ddc3ec0ed86ee510bcc43"},
-]
-pyparsing = [
-    {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
-    {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
-]
-pyserial = [
-    {file = "pyserial-3.4-py2.py3-none-any.whl", hash = "sha256:e0770fadba80c31013896c7e6ef703f72e7834965954a78e71a3049488d4d7d8"},
-    {file = "pyserial-3.4.tar.gz", hash = "sha256:6e2d401fdee0eab996cf734e67773a0143b932772ca8b42451440cfed942c627"},
-]
-pytest = [
-    {file = "pytest-6.0.2-py3-none-any.whl", hash = "sha256:0e37f61339c4578776e090c3b8f6b16ce4db333889d65d0efb305243ec544b40"},
-    {file = "pytest-6.0.2.tar.gz", hash = "sha256:c8f57c2a30983f469bf03e68cdfa74dc474ce56b8f280ddcb080dfd91df01043"},
-]
-pytest-forked = [
-    {file = "pytest-forked-1.4.0.tar.gz", hash = "sha256:8b67587c8f98cbbadfdd804539ed5455b6ed03802203485dd2f53c1422d7440e"},
-    {file = "pytest_forked-1.4.0-py3-none-any.whl", hash = "sha256:bbbb6717efc886b9d64537b41fb1497cfaf3c9601276be8da2cccfea5a3c8ad8"},
-]
-pytest-httpserver = [
-    {file = "pytest_httpserver-0.3.8-py3-none-any.whl", hash = "sha256:8588edd98a7cec8b5fb481ad1180df0e928648816213c242974a318842d0befe"},
-    {file = "pytest_httpserver-0.3.8.tar.gz", hash = "sha256:d896a6556e426240837891b0552040ed4148e393ddf63f675b60d47bcd2d3f39"},
-]
-pytest-timeout = [
-    {file = "pytest-timeout-1.3.4.tar.gz", hash = "sha256:80faa19cd245a42b87a51699d640c00d937c02b749052bfca6bae8bdbe12c48e"},
-    {file = "pytest_timeout-1.3.4-py2.py3-none-any.whl", hash = "sha256:95ca727d4a1dace6ec5f0534d2940b8417ff8b782f7eef0ea09240bdd94d95c2"},
-]
-pytest-xdist = [
-    {file = "pytest-xdist-2.4.0.tar.gz", hash = "sha256:89b330316f7fc475f999c81b577c2b926c9569f3d397ae432c0c2e2496d61ff9"},
-    {file = "pytest_xdist-2.4.0-py3-none-any.whl", hash = "sha256:7b61ebb46997a0820a263553179d6d1e25a8c50d8a8620cd1aa1e20e3be99168"},
-]
-python-dateutil = [
-    {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
-    {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
-]
-pyyaml = [
-    {file = "PyYAML-5.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f7a21e3d99aa3095ef0553e7ceba36fb693998fbb1226f1392ce33681047465f"},
-    {file = "PyYAML-5.4-cp27-cp27m-win32.whl", hash = "sha256:52bf0930903818e600ae6c2901f748bc4869c0c406056f679ab9614e5d21a166"},
-    {file = "PyYAML-5.4-cp27-cp27m-win_amd64.whl", hash = "sha256:a36a48a51e5471513a5aea920cdad84cbd56d70a5057cca3499a637496ea379c"},
-    {file = "PyYAML-5.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:5e7ac4e0e79a53451dc2814f6876c2fa6f71452de1498bbe29c0b54b69a986f4"},
-    {file = "PyYAML-5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc552b6434b90d9dbed6a4f13339625dc466fd82597119897e9489c953acbc22"},
-    {file = "PyYAML-5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0dc9f2eb2e3c97640928dec63fd8dc1dd91e6b6ed236bd5ac00332b99b5c2ff9"},
-    {file = "PyYAML-5.4-cp36-cp36m-win32.whl", hash = "sha256:5a3f345acff76cad4aa9cb171ee76c590f37394186325d53d1aa25318b0d4a09"},
-    {file = "PyYAML-5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:f3790156c606299ff499ec44db422f66f05a7363b39eb9d5b064f17bd7d7c47b"},
-    {file = "PyYAML-5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:124fd7c7bc1e95b1eafc60825f2daf67c73ce7b33f1194731240d24b0d1bf628"},
-    {file = "PyYAML-5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8b818b6c5a920cbe4203b5a6b14256f0e5244338244560da89b7b0f1313ea4b6"},
-    {file = "PyYAML-5.4-cp37-cp37m-win32.whl", hash = "sha256:737bd70e454a284d456aa1fa71a0b429dd527bcbf52c5c33f7c8eee81ac16b89"},
-    {file = "PyYAML-5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:7242790ab6c20316b8e7bb545be48d7ed36e26bbe279fd56f2c4a12510e60b4b"},
-    {file = "PyYAML-5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cc547d3ead3754712223abb7b403f0a184e4c3eae18c9bb7fd15adef1597cc4b"},
-    {file = "PyYAML-5.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8635d53223b1f561b081ff4adecb828fd484b8efffe542edcfdff471997f7c39"},
-    {file = "PyYAML-5.4-cp38-cp38-win32.whl", hash = "sha256:26fcb33776857f4072601502d93e1a619f166c9c00befb52826e7b774efaa9db"},
-    {file = "PyYAML-5.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2243dd033fd02c01212ad5c601dafb44fbb293065f430b0d3dbf03f3254d615"},
-    {file = "PyYAML-5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:31ba07c54ef4a897758563e3a0fcc60077698df10180abe4b8165d9895c00ebf"},
-    {file = "PyYAML-5.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:02c78d77281d8f8d07a255e57abdbf43b02257f59f50cc6b636937d68efa5dd0"},
-    {file = "PyYAML-5.4-cp39-cp39-win32.whl", hash = "sha256:fdc6b2cb4b19e431994f25a9160695cc59a4e861710cc6fc97161c5e845fc579"},
-    {file = "PyYAML-5.4-cp39-cp39-win_amd64.whl", hash = "sha256:8bf38641b4713d77da19e91f8b5296b832e4db87338d6aeffe422d42f1ca896d"},
-    {file = "PyYAML-5.4.tar.gz", hash = "sha256:3c49e39ac034fd64fd576d63bb4db53cda89b362768a67f07749d55f128ac18a"},
-]
-pyyaml-env-tag = [
-    {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"},
-    {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
-]
-requests = [
-    {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"},
-    {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"},
-]
-semver = [
-    {file = "semver-2.13.0-py2.py3-none-any.whl", hash = "sha256:ced8b23dceb22134307c1b8abfa523da14198793d9787ac838e70e29e77458d4"},
-    {file = "semver-2.13.0.tar.gz", hash = "sha256:fa0fe2722ee1c3f57eac478820c3a5ae2f624af8264cbdf9000c980ff7f75e3f"},
-]
-simplejson = [
-    {file = "simplejson-3.17.0-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:87d349517b572964350cc1adc5a31b493bbcee284505e81637d0174b2758ba17"},
-    {file = "simplejson-3.17.0-cp27-cp27m-win32.whl", hash = "sha256:1d1e929cdd15151f3c0b2efe953b3281b2fd5ad5f234f77aca725f28486466f6"},
-    {file = "simplejson-3.17.0-cp27-cp27m-win_amd64.whl", hash = "sha256:1ea59f570b9d4916ae5540a9181f9c978e16863383738b69a70363bc5e63c4cb"},
-    {file = "simplejson-3.17.0-cp33-cp33m-win32.whl", hash = "sha256:8027bd5f1e633eb61b8239994e6fc3aba0346e76294beac22a892eb8faa92ba1"},
-    {file = "simplejson-3.17.0-cp33-cp33m-win_amd64.whl", hash = "sha256:22a7acb81968a7c64eba7526af2cf566e7e2ded1cb5c83f0906b17ff1540f866"},
-    {file = "simplejson-3.17.0-cp34-cp34m-win32.whl", hash = "sha256:17163e643dbf125bb552de17c826b0161c68c970335d270e174363d19e7ea882"},
-    {file = "simplejson-3.17.0-cp34-cp34m-win_amd64.whl", hash = "sha256:0fe3994207485efb63d8f10a833ff31236ed27e3b23dadd0bf51c9900313f8f2"},
-    {file = "simplejson-3.17.0-cp35-cp35m-win32.whl", hash = "sha256:4cf91aab51b02b3327c9d51897960c554f00891f9b31abd8a2f50fd4a0071ce8"},
-    {file = "simplejson-3.17.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fc9051d249dd5512e541f20330a74592f7a65b2d62e18122ca89bf71f94db748"},
-    {file = "simplejson-3.17.0-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:86afc5b5cbd42d706efd33f280fec7bd7e2772ef54e3f34cf6b30777cd19a614"},
-    {file = "simplejson-3.17.0-cp36-cp36m-win32.whl", hash = "sha256:926bcbef9eb60e798eabda9cd0bbcb0fca70d2779aa0aa56845749d973eb7ad5"},
-    {file = "simplejson-3.17.0-cp36-cp36m-win_amd64.whl", hash = "sha256:daaf4d11db982791be74b23ff4729af2c7da79316de0bebf880fa2d60bcc8c5a"},
-    {file = "simplejson-3.17.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:9a126c3a91df5b1403e965ba63b304a50b53d8efc908a8c71545ed72535374a3"},
-    {file = "simplejson-3.17.0-cp37-cp37m-win32.whl", hash = "sha256:fc046afda0ed8f5295212068266c92991ab1f4a50c6a7144b69364bdee4a0159"},
-    {file = "simplejson-3.17.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7cce4bac7e0d66f3a080b80212c2238e063211fe327f98d764c6acbc214497fc"},
-    {file = "simplejson-3.17.0.tar.gz", hash = "sha256:2b4b2b738b3b99819a17feaf118265d0753d5536049ea570b3c43b51c4701e81"},
-]
-six = [
-    {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
-    {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
-]
-smmap = [
-    {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
-    {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
-]
-toml = [
-    {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
-    {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
-]
-tomli = [
-    {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
-    {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
-]
-typing-extensions = [
-    {file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"},
-    {file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"},
-]
-urllib3 = [
-    {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"},
-    {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"},
-]
-verspec = [
-    {file = "verspec-0.1.0-py3-none-any.whl", hash = "sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31"},
-    {file = "verspec-0.1.0.tar.gz", hash = "sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e"},
-]
-watchdog = [
+files = [
     {file = "watchdog-2.1.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:676263bee67b165f16b05abc52acc7a94feac5b5ab2449b491f1a97638a79277"},
     {file = "watchdog-2.1.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:aa68d2d9a89d686fae99d28a6edf3b18595e78f5adf4f5c18fbfda549ac0f20c"},
     {file = "watchdog-2.1.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e2e51c53666850c3ecffe9d265fc5d7351db644de17b15e9c685dd3cdcd6f97"},
@@ -1070,11 +499,27 @@ watchdog = [
     {file = "watchdog-2.1.8-py3-none-win_ia64.whl", hash = "sha256:0fb60c7d31474b21acba54079ce9ff0136411183e9a591369417cddb1d7d00d7"},
     {file = "watchdog-2.1.8.tar.gz", hash = "sha256:6d03149126864abd32715d4e9267d2754cede25a69052901399356ad3bc5ecff"},
 ]
-werkzeug = [
-    {file = "Werkzeug-2.1.2-py3-none-any.whl", hash = "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"},
-    {file = "Werkzeug-2.1.2.tar.gz", hash = "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6"},
-]
-zipp = [
+
+[package.extras]
+watchmedo = ["PyYAML (>=3.10)"]
+
+[[package]]
+name = "zipp"
+version = "3.8.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
     {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
     {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
 ]
+
+[package.extras]
+docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
+testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = ">=3.8, !=3.9.7, <4"
+content-hash = "609b3f624d4cffecdfb1d363139aee30f917c528d0a4312880e41025411771a2"
diff --git a/pyproject.toml b/pyproject.toml
index 7aeb397e825..7ba3326a15c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,18 +6,6 @@ authors = []
 
 [tool.poetry.dependencies]
 python = ">=3.8, !=3.9.7, <4"
-pytest = "6.0.2"
-simplejson = "3.17.0"
-semver = "2.13.0"
-pyserial = "3.4"
-pyyaml = "5.4"
-requests = "^2.22.0"
-pytest-timeout = "1.3.4"
-invoke = "1.4.1"
-filelock = "^3.0.12"
-pytest-xdist = "^2.1.0"
-pytest_httpserver = "^0.3.5"
-GitPython = "^3.1.12"
 
 [tool.poetry.dev-dependencies]
 mkdocs = "^1.2.1"
@@ -25,10 +13,3 @@ mkdocs-material = "^7.1.8"
 mdx-truly-sane-lists = "^1.2"
 GitPython = "^3.1.20"
 mike = "^1.0.1"
-black = "^22.3"
-flake8 = "^3.9.2"
-pep8-naming = "^0.12.1"
-
-[tool.black]
-line-length = 120
-target-version = ["py38"]
diff --git a/test/README.md b/test/README.md
deleted file mode 100644
index fcf7e751bd3..00000000000
--- a/test/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Integration tests
-
-This dir contains integration tests, aimed to test the Command Line Interface and its output from a pure user point of
-view.
-
-For instructions, see the [contributing guide](../docs/CONTRIBUTING.md#integration-tests).
diff --git a/test/__init__.py b/test/__init__.py
deleted file mode 100644
index 964bc6c4306..00000000000
--- a/test/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
diff --git a/test/common.py b/test/common.py
deleted file mode 100644
index a7500612583..00000000000
--- a/test/common.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
-import os
-import collections
-import json
-
-
-Board = collections.namedtuple("Board", "address fqbn package architecture id core")
-
-
-def running_on_ci():
-    """
-    Returns whether the program is running on a CI environment
-    """
-    val = os.getenv("APPVEYOR") or os.getenv("DRONE") or os.getenv("GITHUB_WORKFLOW")
-    return val is not None
-
-
-def parse_json_traces(log_json_lines):
-    trace_entries = []
-    for entry in log_json_lines:
-        entry = json.loads(entry)
-        if entry.get("level") == "trace":
-            trace_entries.append(entry.get("msg"))
-    return trace_entries
diff --git a/test/conftest.py b/test/conftest.py
deleted file mode 100644
index 8f164848385..00000000000
--- a/test/conftest.py
+++ /dev/null
@@ -1,252 +0,0 @@
-# This file is part of arduino-cli.
-#
-# Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
-#
-# This software is released under the GNU General Public License version 3,
-# which covers the main part of arduino-cli.
-# The terms of this license can be found at:
-# https://www.gnu.org/licenses/gpl-3.0.en.html
-#
-# You can be released from the requirements of the above licenses by purchasing
-# a commercial license. Buying such a license is mandatory if you want to modify or
-# otherwise use the software for commercial activities involving the Arduino
-# software without disclosing the source code of your own applications. To purchase
-# a commercial license, send an email to license@arduino.cc.
-import os
-import platform
-import signal
-import shutil
-import time
-from pathlib import Path
-
-import pytest
-import simplejson as json
-from invoke import Local
-from invoke.context import Context
-import tempfile
-from filelock import FileLock
-
-from .common import Board
-
-
-def create_data_dir(tmpdir_factory):
-    # it seems that paths generated by pytest's tmpdir_factory are too
-    # long and may lead to arduino-cli compile failures due to the
-    # combination of (some or all of) the following reasons:
-    # 1) Windows not liking path >260 chars in len
-    # 2) arm-gcc not fully optimizing long paths
-    # 3) libraries requiring headers deep down the include path
-    # for example:
-    #
-    #             from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/Thread.h:29, # noqa: E501
-    #             from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/rtos/rtos.h:28, # noqa: E501
-    #             from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/mbed/mbed.h:23, # noqa: E501
-    #             from C:\Users\runneradmin\AppData\Local\Temp\pytest-of-runneradmin\pytest-0\A7\packages\arduino\hardware\mbed\1.1.4\cores\arduino/Arduino.h:32, # noqa: E501
-    #             from C:\Users\RUNNER~1\AppData\Local\Temp\arduino-sketch-739B2B6DD21EB014317DA2A46062811B\sketch\magic_wand.ino.cpp:1: # noqa: E501
-    # [error]c:\users\runneradmin\appdata\local\temp\pytest-of-runneradmin\pytest-0\a7\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4\arm-none-eabi\include\c++\7.2.1\new:39:10: fatal error: bits/c++config.h: No such file or directory # noqa: E501
-    #
-    # due to the above on Windows we cut the tmp path straight to /tmp/xxxxxxxx
-    if platform.system() == "Windows":
-        with tempfile.TemporaryDirectory() as tmp:
-            yield os.path.realpath(tmp)
-            # We don't need to remove the directory since
-            # tempfile.TemporaryDirectory deletes itself
-            # automatically when exits its scope.
-    else:
-        data = tmpdir_factory.mktemp("ArduinoTest")
-        yield os.path.realpath(data)
-        shutil.rmtree(data, ignore_errors=True)
-
-
-@pytest.fixture(scope="session")
-def session_data_dir(tmpdir_factory):
-    yield from create_data_dir(tmpdir_factory)
-
-
-@pytest.fixture(scope="function")
-def data_dir(tmpdir_factory):
-    """
-    A tmp folder will be created before running
-    each test and deleted at the end, this way all the
-    tests work in isolation.
-    """
-    yield from create_data_dir(tmpdir_factory)
-
-
-@pytest.fixture(scope="session")
-def downloads_dir(tmpdir_factory, worker_id):
-    """
-    To save time and bandwidth, all the tests will access
-    the same download cache folder.
-    """
-    download_dir = tmpdir_factory.mktemp("ArduinoTest", numbered=False)
-
-    # This folders should be created only once per session, if we're running
-    # tests in parallel using multiple processes we need to make sure this
-    # this fixture is executed only once, thus the use of the lockfile
-    if not worker_id == "master":
-        lock = Path(download_dir / "lock")
-        with FileLock(lock):
-            if not lock.is_file():
-                lock.touch()
-
-    yield os.path.realpath(download_dir)
-    shutil.rmtree(download_dir, ignore_errors=True)
-
-
-@pytest.fixture(scope="function")
-def working_dir(tmpdir_factory):
-    """
-    A tmp folder to work in
-    will be created before running each test and deleted
-    at the end, this way all the tests work in isolation.
-    """
-    work_dir = tmpdir_factory.mktemp("ArduinoTestWork")
-    yield os.path.realpath(work_dir)
-    shutil.rmtree(work_dir, ignore_errors=True)
-
-
-@pytest.fixture(scope="function")
-def run_command(pytestconfig, data_dir, downloads_dir, working_dir):
-    """
-    Provide a wrapper around invoke's `run` API so that every test
-    will work in the same temporary folder.
-
-    Useful reference:
-        http://docs.pyinvoke.org/en/1.4/api/runners.html#invoke.runners.Result
-    """
-
-    cli_path = Path(pytestconfig.rootdir).parent / "arduino-cli"
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-    }
-    (Path(data_dir) / "packages").mkdir(exist_ok=True)
-
-    def _run(cmd: list, custom_working_dir=None, custom_env=None, hide=False):
-        if cmd is None:
-            cmd = []
-        quoted_cmd = [f'"{t}"' for t in cmd]
-
-        if not custom_working_dir:
-            custom_working_dir = working_dir
-        if not custom_env:
-            custom_env = env
-        cli_full_line = '"{}" {}'.format(cli_path, " ".join(quoted_cmd))
-        run_context = Context()
-        # It might happen that we need to change directories between drives on Windows,
-        # in that case the "/d" flag must be used otherwise directory wouldn't change
-        cd_command = "cd"
-        if platform.system() == "Windows":
-            cd_command += " /d"
-        # Context.cd() is not used since it doesn't work correctly on Windows.
-        # It escapes spaces in the path using "\ " but it doesn't always work,
-        # wrapping the path in quotation marks is the safest approach
-        with run_context.prefix(f'{cd_command} "{custom_working_dir}"'):
-            return run_context.run(cli_full_line, echo=True, hide=hide, warn=True, env=custom_env, encoding="utf-8")
-
-    return _run
-
-
-@pytest.fixture(scope="function")
-def daemon_runner(pytestconfig, data_dir, downloads_dir, working_dir):
-    """
-    Provide an invoke's `Local` object that has started the arduino-cli in daemon mode.
-    This way is simple to start and kill the daemon when the test is finished
-    via the kill() function
-
-    Useful reference:
-        http://docs.pyinvoke.org/en/1.4/api/runners.html#invoke.runners.Local
-        http://docs.pyinvoke.org/en/1.4/api/runners.html
-    """
-    cli_path = Path(pytestconfig.rootdir).parent / "arduino-cli"
-    cli_full_line = f'"{cli_path}" daemon'
-    env = {
-        "ARDUINO_DATA_DIR": data_dir,
-        "ARDUINO_DOWNLOADS_DIR": downloads_dir,
-        "ARDUINO_SKETCHBOOK_DIR": data_dir,
-    }
-    (Path(data_dir) / "packages").mkdir()
-    run_context = Context()
-    # It might happen that we need to change directories between drives on Windows,
-    # in that case the "/d" flag must be used otherwise directory wouldn't change
-    cd_command = "cd"
-    if platform.system() == "Windows":
-        cd_command += " /d"
-    # Context.cd() is not used since it doesn't work correctly on Windows.
-    # It escapes spaces in the path using "\ " but it doesn't always work,
-    # wrapping the path in quotation marks is the safest approach
-    run_context.prefix(f'{cd_command} "{working_dir}"')
-    # Local Class is the implementation of a Runner abstract class
-    runner = Local(run_context)
-    runner.run(cli_full_line, echo=False, hide=True, warn=True, env=env, asynchronous=True)
-
-    # we block here until the test function using this fixture has returned
-    yield runner
-
-    # Kill the runner's process as we finished our test (platform dependent)
-    os_signal = signal.SIGTERM
-    if platform.system() != "Windows":
-        os_signal = signal.SIGKILL
-    os.kill(runner.process.pid, os_signal)
-
-
-@pytest.fixture(scope="function")
-def detected_boards(run_command):
-    """
-    This fixture provides a list of all the boards attached to the host.
-    This fixture will parse the JSON output of `arduino-cli board list --format json`
-    to extract all the connected boards data.
-
-    :returns a list `Board` objects.
-    """
-    assert run_command(["core", "update-index"])
-    result = run_command(["board", "list", "--format", "json"])
-    assert result.ok
-
-    detected_boards = []
-    for port in json.loads(result.stdout):
-        for board in port.get("matching_boards", []):
-            fqbn = board.get("fqbn")
-            package, architecture, _id = fqbn.split(":")
-            detected_boards.append(
-                Board(
-                    address=port["port"]["address"],
-                    fqbn=fqbn,
-                    package=package,
-                    architecture=architecture,
-                    id=_id,
-                    core="{}:{}".format(package, architecture),
-                )
-            )
-
-    return detected_boards
-
-
-@pytest.fixture(scope="function")
-def copy_sketch(working_dir):
-    def _copy(sketch_name):
-        # Copies sketch to working directory for testing
-        sketch_path = Path(__file__).parent / "testdata" / sketch_name
-        test_sketch_path = Path(working_dir, sketch_name)
-        shutil.copytree(sketch_path, test_sketch_path)
-        return str(test_sketch_path)
-
-    return _copy
-
-
-@pytest.fixture(scope="function")
-def wait_for_board(run_command):
-    def _waiter(seconds=10):
-        # Waits for the specified amount of second for a board to be visible.
-        # This is necessary since it might happen that a board is not immediately
-        # available after a test upload and subsequent tests might consequently fail.
-        time_end = time.time() + seconds
-        while time.time() < time_end:
-            result = run_command(["board", "list", "--format", "json"])
-            ports = json.loads(result.stdout)
-            if len([p.get("boards", []) for p in ports]) > 0:
-                break
-
-    return _waiter
diff --git a/test/pytest.ini b/test/pytest.ini
deleted file mode 100644
index efa3923446b..00000000000
--- a/test/pytest.ini
+++ /dev/null
@@ -1,15 +0,0 @@
-[pytest]
-filterwarnings =
-    error
-    ignore::DeprecationWarning
-    ignore::ResourceWarning
-
-markers =
-    slow: marks tests as slow (deselect with '-m "not slow"')
-
-# -x to exit at first failure
-# -s to disable per-test capture
-# --verbose is what is says it is
-# --tb=long sets the length of the traceback in case of failures
-# See https://pypi.org/project/pytest-xdist/#parallelization for more info on parallelization
-addopts = -x -s --verbose --tb=long
diff --git a/test/testdata/Arduino_TensorFlowLite.zip b/test/testdata/Arduino_TensorFlowLite.zip
deleted file mode 100644
index e4a790e82b53b7f98c14c879d7e6c402b4359770..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3892384
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