Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial draft of dotnet nuget trusted-signers commands spec #10628

Merged
merged 9 commits into from
Mar 15, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions proposed/2021/DotnetNugetTrustedSigners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# Title
zkat marked this conversation as resolved.
Show resolved Hide resolved

zkat marked this conversation as resolved.
Show resolved Hide resolved
- Author Name [Kat Marchan (@zkat)](https://github.com/zkat)
- Start Date 2021-03-04
- GitHub Issue (GitHub Issue link)
zkat marked this conversation as resolved.
Show resolved Hide resolved
- GitHub PR (GitHub PR link)

## Summary

This specifies the syntax and behavior for the `dotnet.exe nuget trusted-signers` command.
zkat marked this conversation as resolved.
Show resolved Hide resolved

## Motivation

This is part of a larger effort to reach full parity between `nuget.exe` and
`dotnet.exe` for NuGet-related operations.

## Explanation

### Functional explanation

#### `dotnet nuget trusted-signers`

```
Provides the ability to manage the list of trusted signers.
zkat marked this conversation as resolved.
Show resolved Hide resolved

USAGE:
dotnet nuget trusted-signer [OPTIONS] [COMMAND]
zkat marked this conversation as resolved.
Show resolved Hide resolved
zkat marked this conversation as resolved.
Show resolved Hide resolved

COMMANDS:
list (default)
trust-package <name> <package>...
trust-source <name> [source-url]
trust-certificate <name> <fingerprint>
remove <name>
sync <name>
```

#### `dotnet nuget trusted-signers list`
zkat marked this conversation as resolved.
Show resolved Hide resolved

```
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], it means that certificate entry has allowUntrustedRoot set as true.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of this?

Suggested change
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], it means that certificate entry has allowUntrustedRoot set as true.
Lists all the trusted signers in the configuration. This option will include all the certificates (with fingerprint and fingerprint algorithm) each signer has. If a certificate has a preceding [U], NuGet will not reject the certificate if it chains to an untrusted root.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. I think it's good to make it clear that the [U] corresponds to an actual option in the config file, you know? What do you think, @heng-liu ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... IMHO ideally no one ever uses allowUntrustedRoot. If so, maybe we shouldn't bring up such an advanced topic in the command description? It is difficult to balance between useful information and verbosity. What do you think of only explaning [U] in command output if the user has allowUntrustedRoot enabled somewhere as per #10628 (comment)? If so, we can detail both the allowUntrustedRoot config plus give a quick human description of what that entails.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just pointing out... you can use links to docs on more advanced topics. We anticipate doing this when we clean up all the CLI help near the end of .NET 6 or start of 7.


USAGE:
dotnet nuget trusted-signers [OPTIONS] list

OPTIONS:
-h, --help Prints help information.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
zkat marked this conversation as resolved.
Show resolved Hide resolved
--interactive Allows command to stop and wait for user input or action.
--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.

EXAMPLE:
$ dotnet nuget trusted-signers list
Registered trusted signers:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like the example being included here. The user will see this output as soon as they run the command and it will push the usage off the screen if you do not maximize your terminal window.

Also, will the list be long? Consider putting in your backlog doing a partial match, but talk to me about making your format consistent with the rest of the CLI direction if you do that (so maybe wait and see what people want).


1. nuget.org [repository]
Service Index: https://api.nuget.org/v3/index.json
Certificate fingerprint(s):
loic-sharma marked this conversation as resolved.
Show resolved Hide resolved
zkat marked this conversation as resolved.
Show resolved Hide resolved
SHA256 - 0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D

2. microsoft [author]
Certificate fingerprint(s):
SHA256 - 3F9001EA83C560D712C24CF213C3D312CB3BFF51EE89435D3430BD06B5D0EECE
SHA256 - AA12DA22A49BCE7D5C1AE64CC1F3D892F150DA76140F210ABD2CBFFCA2C18A27

3. myUntrustedAuthorSignature [author]
Certificate fingerprint(s):
[U] SHA256 - 518F9CF082C0872025EFB2587B6A6AB198208F63EA58DD54D2B9FF6735CA4434
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dotnet list package describes the markers like [U] at the bottom of the command output. For example (LINK):

Project 'SentimentAnalysis' has the following package references
   ...
   > Microsoft.NETCore.App   (A)   [2.1.0, )   2.1.0

(A) : Auto-referenced package.

Personally I find that describing the markers at the bottom of the command output grabs my attention more than the end of the command's help description. What do you think of adding the markers at the bottom of the output too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like if we use markers to describe the output, then we haven't done a good enough job explaining the output in the first place. I especially think describing allowUntrustedRoot is going to be difficult to explain in a single line at the bottom of the command.

Copy link
Contributor

@loic-sharma loic-sharma Mar 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we either:

  1. Remove the [U] marker altogether, or...
  2. Replace the marker with some text next to the SHA-256 fingerprint, or...
  3. Define the [U] marker somewhere in this output. For the single line explanation, I suggest: [U]: NuGet will not reject the certificate if it chains to an untrusted root.. We can skip definition if no certs allow an untrusted root.

I'd vote for option 2 or 3 personally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm impartial. tbh just tell me which one y'all like best and I'll do that :)


#### `dotnet nuget trusted-signers sync`
zkat marked this conversation as resolved.
Show resolved Hide resolved

```
Requests the latest list of certificates used in a currently trusted repository to update the the existing certificate list in the trusted signer.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only updates the trusted source, not trusted author, right? Maybe trusted-source is better than trusted-signers, if it doen't also sync to the latest author certificates.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the code, yes you're right, it just sync certificate of repository signature.
I think trusted-signers means both author signers and repository signers.
An example is: we add certificate of repository signature by running trusted-signers add command.
So the question is, it good enough to only call it out explicitly in the document, that author certs will not be synced?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As someone not familiar with this space, I found it difficult to understand this sentence. Is the most important part first? If not try that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a generalized concern that this feature is very complex and hard to explain in general, and I'm having trouble figuring out how to write these docs in a way that creates clarity. :(


Note: This gesture will delete the current list of certificates and replace them with an up-to-date list from the repository.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, wait. If this is what it does, why not just use this note as the description?


USAGE:
dotnet nuget trusted-signers sync [OPTIONS] <name>

OPTIONS:
-h, --help Prints help information.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update this in all commands please.

These are now the standard CLI/.NET Tools verbosities and MSBuild is just to be specific among ourselves.

Suggested change
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
-v, --verbosity <LEVEL> Set the verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].

--interactive Allows command to stop and wait for user input or action.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually include -i as abbrev for --interactive, unless you have a legacy conflict. Suggest adding for all commands.

--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at this in the output and see how bad the wrapping is. I do not think the second sentence is helpful and this seems long and verbose for help. This is probably a description you use a lot across NuGet help (and the CLI), so let's see if we can find some nice concise consistent language.

```

#### `dotnet nuget trusted-signers remove`

```
Removes any trusted signers that match the given name.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it confusing that when adding a trusted signer you need to specify either source or package, but when you remove you don't specify which 'type'?

Copy link
Contributor

@heng-liu heng-liu Mar 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the code , there is a checking on duplicate names in trusted-signers section of config file when adding, to guarantee that there is no duplicate name, among all trusted-signers (both author and repository signers). So it might be good to just specifying the name, without 'type'.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think this is nice. When you add a signer from a package you are not adding the package, but using it to find the certificate. When you remove the package, it does not matter where you got it.

Not symmetric, but in this case the action is not symmetric


USAGE:
dotnet nuget trusted-signers remove [OPTIONS] <name>

OPTIONS:
-h, --help Prints help information.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--interactive Allows command to stop and wait for user input or action.
--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.
```

#### `dotnet nuget trusted-signers trust-package`
zkat marked this conversation as resolved.
Show resolved Hide resolved

```
Adds a trusted signer with the given name to the config, based on one or more packages.
zkat marked this conversation as resolved.
Show resolved Hide resolved

USAGE:
dotnet nuget trusted-signers trust-package [OPTIONS] <name> <package>...
zkat marked this conversation as resolved.
Show resolved Hide resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently dotnet nuget verify allows to pass more than 1 path even though nuget verify doesn't, how about here do we have same gesture behavior allow pass more than 1 paths or serviceindexes, fingerprints?
dotnet nuget verify C:\Users\xxxx\source\repos\SigningDemo\TestSigned\TestSigned.1.0.0.nupkg C:\Users\xxxx\source\repos\SigningDemo\TestSigned\*.nupkg -v d

Copy link
Contributor

@heng-liu heng-liu Mar 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very good question.
My understanding is, the reason why we change the dotnet verify command to support multiple paths, is as following:
NuGet.exe only runs Windows(except on Mono) but dotnet.exe will run cross-platform
When executing the command in powershell, the xx*.nupkg will be passed as one argument to nuget.exe,
but when executing the command in bash, the globbing will expand the xx/*.nupkg into multiple paths before passing to dotnet.exe command. So if the dotnet.exe only accept one path, it will only get the first path but ignore the rest paths, and make it inconsistent with what we have on NuGet.exe.

In one word, we change dotnet.exe to accept multiple paths because it makes dotnet acts more like NuGet.exe.

Previously when we only have NuGet.exe, we use ";" to separate elements in one option, if we have multiple serviceindexes, fingerprints.
When we have dotnet.exe later, the ";" indicates the command terminates in bash.
I agree we need to think it over and have more discussion if we want to change the separator. If we're going to deprecate NuGet.exe, we may have less impact on customers.
FYI @JonDouglas

Copy link
Contributor

@loic-sharma loic-sharma Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is globbing files a scenario customers need when updating their trusted signers? Do you have an example when this would be useful?

The reason I ask is because this scenario scares me a little bit. Ideally customers should thoroughly review each and every author/source they choose to trust.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the good question.
Just checked the code.
In NuGet.exe command, the package path could be wildcard, so there might be multiple paths after parsing.
But there is a checking on "Name" to reject any existing "Name" at https://github.com/NuGet/NuGet.Client/blob/ac97d923e633f4ee65eec5ec690c4d99d7a922f3/src/NuGet.Core/NuGet.Commands/TrustedSignersCommand/TrustedSignerActionsProvider.cs#L243
So when there are multiple packages, the first one will be added successfully, but the reset will fail for A trusted signer 'Test' already exists.
Apparently this is a bug. We should make the two consistent.
That is, do not accept multiple paths, or, accept multiple 'Name'.
Raised issue at #10647

OPTIONS:
--allow-untrusted-root Specifies if the certificate for the trusted signer should be allowed to chain to an untrusted root.
zkat marked this conversation as resolved.
Show resolved Hide resolved
--author Specifies that the author signature of the package(s) should be trusted. This option is mutually exclusive with --repository.
--repository Specifies that the repository signature or countersignature of the package(s) should be trusted. This option is mutually exclusive with --author.
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository. Only valid when using the --repository option.
-h, --help Prints help information.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--interactive Allows command to stop and wait for user input or action.
--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.
```

#### `dotnet nuget trusted-signers trust-certificate`

```
Adds a trusted signer with the given name to the config, based on a certificate fingerprint.

Note: If a trusted signer with the given name already exists, the certificate item will be added to that signer. Otherwise a trusted author will be created with a certificate item from given certificate information.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As someone unfamiliar with this space, I do not know what name means. Is it part of the certificate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name in all of these refers to the identifier the trusted signer is saved under. The name of the entity itself, if you will. It's an arbitrary name that we use to key off of.


USAGE:
dotnet nuget trusted-signers trust-certificate [OPTIONS] <name> <fingerprint>

OPTIONS:
--allow-untrusted-root Specifies if the certificate for the trusted signer should be allowed to chain to an untrusted root.
--algorithm Specifies the hash algorithm used to calculate the certificate fingerprint. Defaults to SHA256. Values supported are SHA256, SHA384 and SHA512
-h, --help Prints help information.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--interactive Allows command to stop and wait for user input or action.
--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.
```

#### `dotnet nuget trusted-signers trust-source`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's say I've already trusted 15 package owners for my mid-sized project. But now I want to add one more package that is owned by someone I did not previously trust. What would be my flow to append one more trusted owner? Do I need to provide all 16 package owners to the trust-source command? What would my flow be if I have a large project with many more owners?

The reason I ask is that I recently tried to set up trusted signers for the NuGetGallery codebase. This proved to be difficult using nuget.exe, so I resorted to manually editing the nuget.config file instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One idea may be to add a trust-owner command that appends one or more owners to a trusted repository. See @zivkan comment here: https://github.com/NuGet/Home/pull/10628/files/5263069456da2276d0f3143fd5bf616e933b7809#r589669891

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a similar question about a missing function in NuGet.exe:
After repo certificate rotation, we need to change the trustedSigners section to have two certs :

<trustedSigners>
  <repository name="nuget.org" serviceIndex="https://api.nuget.org/v3/index.json">
    <certificate fingerprint="0E5F38F57DC1BCC806D8494F4F90FBCEDD988B46760709CBEEC6F4219AA6157D" hashAlgorithm="SHA256" allowUntrustedRoot="false" />
    <certificate fingerprint="5A2901D6ADA3D18260B9C6DFE2133C95D74B9EEF6AE0E5DC334C8454D1477DF4" hashAlgorithm="SHA256" allowUntrustedRoot="false" />
  </repository>
</trustedSigners>

But seems there is no command could do that. We have to edit config file manually.
Since we don't have that for NuGet.exe either, perhaps we can address that afterwards.


```
Adds a trusted signer based on a given source.

If only `<name>` is provided, and it's an existing configured source, this command will add a trusted signer with the same name as that source to the trusted list.
Copy link
Contributor

@loic-sharma loic-sharma Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of this phrasing?

Suggested change
If only `<name>` is provided, and it's an existing configured source, this command will add a trusted signer with the same name as that source to the trusted list.
If only `<name>` is provided without `<source-url>`, the package source from your NuGet configuration files with the same name will be added to the trusted list.

This sentence is really hard! Maybe pull in a copywriter 😅


If a `source-url` is provided, it MUST be a v3 source URL (like https://api.nuget.org/v3/index.json). Other source types are not supported.
zkat marked this conversation as resolved.
Show resolved Hide resolved
zkat marked this conversation as resolved.
Show resolved Hide resolved

USAGE:
dotnet nuget trusted-signers trust-source <name> [source-url]

OPTIONS:
--allow-untrusted-root Specifies if the certificate for the trusted signer should be allowed to chain to an untrusted root.
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository. Only valid when using the --repository option.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this command doesn't have a --repository option. Consider:

Suggested change
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository. Only valid when using the --repository option.
--owners Semi-colon separated list of trusted owners to further restrict the trust of a repository.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, copy-paste fail. Thanks!

-h, --help Prints help information.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--interactive Allows command to stop and wait for user input or action.
--configfile The NuGet configuration file. If specified, only the settings from this file will be used. If not specified, the hierarchy of configuration files from the current directory will be used.

```

### Technical explanation

For the most part, these commands map pretty directly to their nuget.exe
counterparts, and most of their implementations should be reusable (removing
`#if IS_DESKTOP` as needed, from the various TrustedSigners classes).

The exception here is the `add` command, which has been split into the various
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think the add command would be better suited for being multi-purpose with different parameters. The syntax of dotnet nuget add trusted-signers trust-* seems a bit verbose compared to dotnet nuget add trusted-signers <package(s)> or dotnet nuget add trusted-signers <service url>.

In other words, it would be cool to just use one command and it sets up the trusted signers regardless of the parameter I pass in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how do you differentiate packages from service URLs? I guess we're going to start detecting whether something looks like a URL and hope the regex does the right thing? What about for relative paths like myprivatehost? Is that a service index, or a local file?

`trust-*` commands that otherwise have the same behaviors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why's that? In another comment I mentioned there are already multiple dotnet add <noun> and dotnet nuget add <noun>. Therefore, this spec is not following the convention of other commands in the dotnet cli

Copy link
Contributor

@heng-liu heng-liu Mar 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I remembered from last discussion is that dotnet want to change (they do not want to keep the same with dotnet add source any more). But I'm not 100% sure if that is the final decision.
Perhaps we can discuss with them when reviewing this document.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


I don't know if there's any significant implementation above just remapping
command invocations for dotnet.exe.

## Drawbacks

This whole feature is very complicated, but it's important for parity.

## Rationale and alternatives

I think the only one that might have a reasonable alternative here would be
the `add` command. I found the command as a whole to be inscrutable, and thus
decided splitting its behavior to be the best way forward. We could have, of
course, mostly just copied the behavior from `nuget.exe trusted-signers add`.

## Prior Art

This spec is based on `nuget.exe trusted-signers`.
zkat marked this conversation as resolved.
Show resolved Hide resolved

## Unresolved Questions

Is this the right UX? Does the naming make sense? This is a fairly complex/complicated feature and we want to make sure we
zkat marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the biggest challenge is consistency throughout the dotnet CLI. I think decisions were made in the past that we have to adhere to in this spec as it might seem odd to users when using nuget contexts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't change how the settings are saved in the nuget.config file, but otherwise can we use this as an opportunity to rethink how to make all the commands easier to use? Why do we have to have a 1:1 mapping between nuget.exe and dotnet cli commands? If we can learn from what we did in nuget.exe to make the dotnet cli commands easier to use, then that will be extra motivation for customers to use the better cli experience.

Or maybe the nuget.config schema is what you were referring to, not the commands.

Copy link
Contributor

@JonDouglas JonDouglas Mar 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mostly meant in the sense of the CLI guidelines under the nuget context umbrella. I agree we should make things easier right now if there are opportunities to do so.


## Future Possibilities

I don't know.
zkat marked this conversation as resolved.
Show resolved Hide resolved