Add lock artifacts during `meltano add` for stability and portability of plugin definitions

This has come up twice this week, especially in context of pipelines and integrations with external tools.

## Original proposal

Original proposal recommends an actual `.lock.yml` file.

<details><summary>Click to expand</summary>

1. `meltano lock` would generate or update a lock file - also in yaml format.
2. This would resolve all dependencies, including the `discovery.yml` ref and combination of all `include-path` files for multi-meltano files.

In future iterations this could be expanded to:

3. Include `catalog.json` caches.
4. Resolve all config representations of `environments` so that each environment has a fully resolved schema (_except_ secrets and the content of any externally-managed environment variables.)~~ - Not needed in initial release.
5. Optionally, include rich information of the DAG structure for known/declared pipelines or schedules.

Based on this lock file artifact, external tools such as Terraform, Databand, etc. could build environments and/or obtain rich project metadata needed for integration.

This may also provide improved stability projects for projects running in the wild, as discussed in this comment: https://gitlab.com/groups/meltano/-/epics/128#note_734475476

</details>

### Alternate implementation option (2022-02-10)

Here's an alternative that just focuses on freezing the plugin definitions, ideally copying those verbatim from their source of truth on hub.meltano.com

#### Stable Installations via `meltano add`

We alter how `meltano add` installs new plugins:

1. Instead of installing directly from `discovery.yml` and relying on the `discovery.yml` definition for resolution, we go to https://hub.meltano.com and download the file associated with the plugin.
2. The downloaded definition file will be installed into `${MELTANO_PROJECT_DIR}/plugins/` as `${MELTANO_PROJECT_DIR}/plugins/extractors/tap-mytap--variantname.yml`.
3. An optional `plugin_definitions_path: <str>` config option in `meltano.yml` will allow users to change the default path. This would simply default to `${MELTANO_PROJECT_DIR}/plugins` if not set by the user.
    - This is separate from [include_paths](https://docs.meltano.com/concepts/project#multiple-yaml-files) in `meltano.yml`, since (1) we need to know exactly where to download new definitions and (2) the plugin definition files adhere to a new plugin spec format and not to the `meltano.yml` project format.
4. After downloading the definition, the plugin entry will be added to `meltano.yml` exactly as is performed today.
5. Instead of resolving setting definitions via `discovery.yml`, `meltano.yml` will only refer to the downloaded definitions.
    - This will require a one-time update to our parser to also interpret and import data from the native/standard plugin definitions from hub.meltano.com.

#### Definition updates via `meltano add --upgrade`

We add something like `meltano add extractor tap-mytap --upgrade` which will replace the current definition with the new definition.

#### Migration to locked definitions via `meltano install --lock` or `meltano install --freeze`

For projects already in the wild, we can add a `--lock` or `--freeze` option to `meltano install` which generates a "locked" plugin definition file for any which are missing. As above, this would create one file per plugin used in the project. If a plugin definition already exists, we skip adding that file.

#### "Single-file option"

I think we've declined this option so I'm collapsing it. Please sound off in comments if you have a strong preference otherwise.

<details><summary>Click to expand</summary>

~~As an alternative to downloading and adding files individually, we could follow basically the same behavior as described, except we import/merge definitions in a single file called something at the root of the Meltano project dir like `plugins-registry.yml`, `registered-plugins.yml`, or `plugins-definitions.yml`. Since it would be a single file, we could have it at a fixed path relative to the root, and perhaps in the future allow the user to specify their own path to that file.

(AJ Speaking) I'm personally less inclined towards the single-lock file approach after thinking on this more. The one-file-per-plugin approach creates cleaner file diffs and is more scalable for a large number of plugins.~~

</details>

#### Deprecating `discovery.yml`

After implementing this proposal, `discovery.yml` as it exists today would be fully deprecated. Projects which have not yet had their definitions locked would still fall back to the bundled `discovery.yml` file. For the purposes of not breaking users on older versions, we would simply leave the online version of this file (https://discovery.meltano.com/discovery.yml) frozen at a point in time without needing to continue maintaining updates in `discovery.yml`.

#### Spec versioning

As @aphethean calls out in a thread on this issue https://gitlab.com/meltano/meltano/-/issues/3031#note_842196683, we also need to handle spec versioning so that the file spec can evolve without breaking users.

For instance, @aphethean provides a sample used by Kubernetes (`apiVersion: networking.k8s.io/v1beta1`) and we can see something similar in `dbt`'s use of `config-version: 2`.

This makes sure we meet this requirement as expressed in the comment:

> 1. ‘meltano add extractor tap-csv’
> 1. Aeons later, tap-csv plugin definition will always work with my meltano project.

Story points: 12.0