Repository: Redocly/redocly-cli
Pull request #678 (2022-05-07 18:33:23)

docs: README update
## What/Why/How?

README update after name change.


Patch:
diff --git a/Dockerfile b/Dockerfile
index ffe7490e..1568b47c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -14,14 +14,14 @@ RUN npm ci --no-optional --ignore-scripts
 COPY . /build/
 RUN npm run prepare
 
-# Install openapi-cli globally, similar to npm install --global @redocly/openapi-cli
+# Install redocly-cli globally, similar to npm install --global @redocly/cli
 # but the local package is used here
-RUN mv -- "$(npm pack packages/cli/)" redocly-openapi-cli.tgz && \
-	  npm install --global redocly-openapi-cli.tgz
+RUN mv -- "$(npm pack packages/cli/)" redocly-cli.tgz && \
+	  npm install --global redocly-cli.tgz
 
 # npm pack in the previous RUN command does not include these assets
-RUN cp packages/cli/src/commands/preview-docs/preview-server/default.hbs /usr/local/lib/node_modules/@redocly/openapi-cli/lib/commands/preview-docs/preview-server/default.hbs && \
-	  cp packages/cli/src/commands/preview-docs/preview-server/hot.js /usr/local/lib/node_modules/@redocly/openapi-cli/lib/commands/preview-docs/preview-server/hot.js
+RUN cp packages/cli/src/commands/preview-docs/preview-server/default.hbs /usr/local/lib/node_modules/@redocly/cli/lib/commands/preview-docs/preview-server/default.hbs && \
+	  cp packages/cli/src/commands/preview-docs/preview-server/hot.js /usr/local/lib/node_modules/@redocly/cli/lib/commands/preview-docs/preview-server/hot.js
 
 # Clean up to reduce image size
 RUN npm cache clean --force && rm -rf /build
diff --git a/README.md b/README.md
index d4d88a3e..80594bda 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
 # Redocly CLI toolset
 
-Redocly CLI toolbox with rich validation and bundling features.
+Redocly CLI (fka OpenAPI CLI) toolbox with rich validation and bundling features.
 
 ![Travis (.org)](https://img.shields.io/travis/Redocly/redocly-cli/master)
-![npm (scoped)](https://img.shields.io/npm/v/@redocly/redocly-cli)
-![NPM](https://img.shields.io/npm/l/@redocly/redocly-cli)
+![npm (scoped)](https://img.shields.io/npm/v/@redocly/cli)
+![NPM](https://img.shields.io/npm/l/@redocly/cli)
 
 ![OpenAPI 3 CLI toolset](./media/redocly-cli.gif)
 
@@ -21,13 +21,16 @@ Currently, @redocly/cli supports these features:
 - [x] Easy to implement custom rules.
 - [x] Bundle a multi-file definition into a single file.
 - [x] Decorators to modify a validated definition during bundling.
-- [x] Preview reference docs for local development.
+- [x] Preview docs for local development.
 - [x] Support for OpenAPI 2 (fka Swagger) and OpenAPI 3.0.
 - [x] Basic support for OpenAPI 3.1
 
 ## What makes this tool different
 
-Unlike other OpenAPI linters, `@redocly/cli` defines the possible type tree of a valid OpenAPI definition and then traverses it. This approach is very similar to how linters for programming languages work and results in major performance benefits over other approaches. Extend functionality at different points in the lifecycle with preprocessors, rules, and decorators.
+- 💨 **It's faster** (uses a type tree similar to how linters for programming languages work)
+- 🎯 **It's more accurate** (working with types is more accurate than working with JSON path)
+- ⚙️ **It's highly configurable** (comes with a lot of commands and rules)
+- 🛠️ **It's more extensible** (architected for custom plugins and types)
 
 ## Usage
 
@@ -64,7 +67,7 @@ docker build -t openapi-cli .
 docker run --rm -v $PWD:/spec openapi-cli lint path-to-root-file.yaml
 ```
 
-## [Read the docs](https://redoc.ly/docs/cli/)
+## [Read the docs](https://redocly.com/docs/cli/)
 
 ## Credits
 
@@ -72,4 +75,4 @@ Thanks to [graphql-js](https://github.com/graphql/graphql-js) and [eslint](https
 
 ## Development
 
-See [CONTRIBUTING.md](.github/CONTRIBUTING.md)
\ No newline at end of file
+See [CONTRIBUTING.md](.github/CONTRIBUTING.md)
diff --git a/docs/changelog.md b/docs/changelog.md
index d6627b2e..3b1706a5 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -289,7 +289,7 @@ lint:
 
 ### Features
 
-- Added support for the [region](./configuration/index.mdx#region) option with the `login`, `push`, and other commands.
+- Added support for the [region](./configuration/index.mdx) option with the `login`, `push`, and other commands.
 - Added two new built-in rules:
   - [no-invalid-schema-examples](./resources/built-in-rules.md#no-invalid-schema-examples)
   - [no-invalid-parameter-examples](./resources/built-in-rules.md#no-invalid-parameter-examples)
diff --git a/docs/commands/login.md b/docs/commands/login.md
index 25d7fafd..1ff3379a 100644
--- a/docs/commands/login.md
+++ b/docs/commands/login.md
@@ -32,7 +32,7 @@ Option | Type | Description
 --help | boolean | Show help.
 --verbose | boolean | Include additional output.
 --version | boolean | Show version number.
---region, -r | string | Specify which region to use when logging in. Supported values: `us`, `eu`. Read more about [configuring the region](../configuration/index.mdx#region).
+--region, -r | string | Specify which region to use when logging in. Supported values: `us`, `eu`. Read more about [configuring the region](../configuration/index.mdx).
 
 ## Examples
 
diff --git a/docs/commands/push.md b/docs/commands/push.md
index ba12b952..f949136d 100644
--- a/docs/commands/push.md
+++ b/docs/commands/push.md
@@ -82,11 +82,12 @@ entrypoint       | string    | The API definition that you want to push to the R
 destination      | string    | Conditional. The location in the API registry where you want to push or upsert your API definition. Provide it in the following format: `@organization-id/api-name@api-version` or `api-name@api-version`if organization ID is already defined in the configuration file. See [the Destination section](#destination) for more information.  |
 --branch, -b    | string  | The branch where your API definition will be pushed or upserted. Default value is `main`.  |
 --help       | boolean | Help output for the command.  |
---run-id       | string  | Specify the ID of the CI job that the current push will be associated with. See [the Run ID section](#run-id) for more information.  |
+--run-id       | string  | Specifies the ID of the CI job that the current push will be associated with. See [the Run ID section](#run-id) for more information.  |
 --skip-decorator | [string] | Ignore one or more decorators. See the [Skip decorator section](#skip-decorator) for usage examples.
 --upsert, -u | boolean | Upsert an API to the API registry. See [the Upsert an API with push section](#upsert-an-api-with-push) for more information.  |
 --version     | boolean | Show version number.  |
---region,-r    | string | Specify which region to use when logging in. Supported values: `us`, `eu`. The `eu` region is limited to enterprise customers. Default value is `us`. Read more about [configuring the region](../configuration/index.mdx#region).
+--region,-r    | string | Specifies which region to use when logging in. Supported values: `us`, `eu`. The `eu` region is limited to enterprise customers. Default value is `us`. Alternatively, set an environment variable `REDOCLY_DOMAIN` with the value the appropriate Redocly API. |
+-- public    | boolean | Make API definitions publicly accessible from the API Registry. Read more about [using the public option](#public).  |
 
 ## Examples
 
@@ -261,6 +262,15 @@ openapi push openapi/petstore.yaml @openapi-org/petstore-api@v1 --skip-decorator
 openapi push openapi/petstore.yaml @openapi-org/petstore-api@v1 --skip-decorator=test/remove-internal-operations --skip-decorator=test/remove-internal-schemas
 ```
 
+### Public
+
+The `--public` option allows you to upload your API definition and make it publicly accessible from the API Registry. By default, definitions uploaded with the `push` command are not available to the public.
+For more information on how to configure access to your APIs, check the [registry access](../../../api-registry/settings/manage-access/#set-up-access-to-api-registry) section.
+
+```bash
+openapi push openapi/petstore.yaml @openapi-org/petstore-api@v1 --public
+```
+
 ### Set up CI from Redocly Workflows
 
 The Redocly Workflows interface can help you get started with the `push` command.
diff --git a/docs/configuration/index.mdx b/docs/configuration/index.mdx
index e97af873..575c7128 100644
--- a/docs/configuration/index.mdx
+++ b/docs/configuration/index.mdx
@@ -39,7 +39,7 @@ The Redocly configuration file must be in YAML format.
   <JsonSchema
     schema={Schema}
     options={{
-      schemaExpansionLevel:2,
+      schemaExpansionLevel:1,
     }}
   />
 </StyledContent>
@@ -52,7 +52,7 @@ apis:
     root: ./openapi/openapi.yaml
     lint:
       rules:
-        example-rule: warn
+        no-ambiguous-paths: error
   external@v1:
     root: ./openapi/external.yaml
     labels:
@@ -72,26 +72,14 @@ features.openapi:
       - lang: Python
 ```
 
-### organization
+### apis object
 
-The `organization` property requires the organization ID of your Redocly Workflows organization.
-When specified in the configuration file, it can be used by the `openapi push` command.
-The `push` command uses the following order of precedence: first, it takes the organization ID from command-line arguments (if provided).
-If the organization ID is not provided explicitly, it takes it from the configuration file.
+The `apis` object is used to configure one or more APIs.
+Every API in the object is identified by its name and version in the format `name@version`.
+The version is optional, and when not provided, Redocly apps interpret it as `latest` by default.
+Every `name@version` combination listed in the object must be unique.
 
-Note that the organization ID is not the same as the organization name in Workflows.
-
-To find the organization ID, log into Workflows and access the **API registry** page.
-In your browser's address bar, find the URL of the page.
-The segment after `app.redocly.com/org/` is your organization ID.
-For example, if the URL is `app.redocly.com/org/test_docs`, the organization ID is `test_docs`.
-
-
-### apis
-
-The `apis` section is used to configure one or more APIs. Every API in the section is identified by its name and version in the format `name@version`. The version is optional, and when not provided, Redocly apps interpret it as `latest` by default. Every `name@version` combination listed in the section must be unique.
-
-For every API listed in the section, you must provide the path to the OpenAPI definition using the `root` property.
+For every API listed in the object, you must provide the path to the OpenAPI definition using the `root` property.
 
 ```yaml
 apis:
@@ -112,8 +100,7 @@ features.openapi:
       backgroundColor: '#fffff'
 ```
 
-
-The `apis` section supports several optional properties for every listed API.
+The `apis` object supports several optional properties for every listed API.
 
 **labels**
 
@@ -123,23 +110,23 @@ If you try to assign labels that don't already exist for your organization, Redo
 
 **lint**
 
-In addition to the global (top-level) `lint` section, you can add one to each API listed in `apis`. This allows you to use different rules and decorators for different APIs.
+In addition to the global (top-level) `lint` object, you can add one to each API listed in `apis`. This allows you to use different rules and decorators for different APIs.
 
 **features.openapi**
 
-In addition to the global (top-level) `features.openapi` section, you can add one to each API listed in `apis`. This allows you to use different API reference docs settings for different APIs.
-This section supports identical format and options as the global `features.openapi` section.
+In addition to the global (top-level) `features.openapi` object, you can add one to each API listed in `apis`. This allows you to use different API reference docs settings for different APIs.
+This object supports identical format and options as the global `features.openapi` object.
 
 
 :::warning Important
 
 Not all `lint` options are supported in per-API configuration.
-Consult the table below to understand how each configuration section applies to your APIs.
+Consult the table below to understand how each configuration object applies to your APIs.
 
 :::
 
 
-Configuration section | Per-API support | Behavior
+Configuration object | Per-API support | Behavior
 -- | -- | --
 lint.extends | ❗ | API settings override global settings.
 lint.rules | ✅ | API and global settings merge. In case of conflict, API takes priority.
@@ -150,14 +137,14 @@ features.openapi | ✅ | API and global settings merge. In case of conflict, API
 features.mockServer | ✅ | API and global settings merge. In case of conflict, API takes priority.
 
 
-Some of the Redocly CLI commands, such as the [lint command](../commands/lint.md), use the API names from the `apis` section as shortcuts for referencing API definitions.
-You can tell the `lint` command to validate specific API definitions by using their names from the `apis` section, like in the following example:
+Some of the Redocly CLI commands, such as the [lint command](../commands/lint.md), use the API names from the `apis` object as shortcuts for referencing API definitions.
+You can tell the `lint` command to validate specific API definitions by using their names from the `apis` object, like in the following example:
 
 ```shell
 openapi lint core
 ```
 
-On the other hand, if you run the command without specifying any aliases, it will apply to all API definitions listed in the `apis` section:
+On the other hand, if you run the command without specifying any aliases, it will apply to all API definitions listed in the `apis` object:
 
 ```shell
 openapi lint
@@ -165,10 +152,10 @@ openapi lint
 
 ### lint
 
-The `lint` section's primary purpose is to define options for the `lint` and `bundle` commands.
+The `lint` object's primary purpose is to define options for the `lint` and `bundle` commands.
 You may also import plugins and extends their configurations.
 
-Read more about the [lint configuration section](../guides/lint.md).
+Read more about the [lint configuration object](../guides/lint.md).
 
 
 ### features.mockServer
@@ -176,69 +163,28 @@ Read more about the [lint configuration section](../guides/lint.md).
 The API registry supports [the mock server feature](../../api-registry/guides/mock-server-quickstart.md) and allows project owners to enable it for all branches per API version.
 When the mock server is enabled for an API, you can send test requests to it from any API client.
 
-The `features.mockServer` section allows additional configuration of the mock server behavior.
-This section is optional.
+The `features.mockServer` object allows additional configuration of the mock server behavior.
+This object is optional.
 
-The `features.mockServer` section supports fields listed in the following table.
+The `features.mockServer` object supports fields listed in the following table.
 
-| Property | Description | Default |
+| Property | Type | Description |
 | --- | --- | --- |
-| errorIfForcedExampleNotFound | Users can force specific examples in the response by adding the optional `x-redocly-response-body-example` header to their requests. By default, if an example ID provided in the request is not found in the API definition, the mock server returns any other example. If you set `errorIfForcedExampleNotFound: true`, the mock server will return an error instead. | false |
-| strictExamples | By default, the mock server automatically enhances responses with heuristics like substituting the response fields with request parameter values. To prevent this behavior, set `strictExamples: true`. When this is set, examples are returned in the response unmodified, exactly how they are defined in the OpenAPI document. | false |
-
+| errorIfForcedExampleNotFound | boolean | Users can force specific examples in the response by adding the optional `x-redocly-response-body-example` header to their requests. By default, if an example ID provided in the request is not found in the API definition, the mock server returns any other example. If you set `errorIfForcedExampleNotFound: true`, the mock server will return an error instead. Default value is `false`.|
+| strictExamples | boolean | By default, the mock server automatically enhances responses with heuristics like substituting the response fields with request parameter values. To prevent this behavior, set `strictExamples: true`. When this is set, examples are returned in the response unmodified, exactly how they are defined in the OpenAPI document. Default value is `false`.|
 
-### region
 
-For optimized performance or for compliance purposes, you can specify which region to use when logging into Redocly services (such as the API registry). Supported regions are `us` (used by default) and `eu`.
+### resolve object
 
-You should log into the region that corresponds to your Redocly Workflows organization. If you're a member of multiple organizations in different regions, it's technically possible to log into two different regions at the same time, but it's neither the most common nor the recommended use-case.
-
-Every supported region uses its own domain.
-
-Region | Domain
------|:---------
-`us` | api.redoc.ly
-`eu` | api.eu.redocly.com
-
-The `eu` region is limited to enterprise customers.
-
-To configure which domain will be used, you can use any of the following:
-
-- the `REDOCLY_DOMAIN` environment variable
-
-```sh
-export REDOCLY_DOMAIN={domain}
-```
+Redocly will automatically resolve any API registry link or public URL in your API definitions. However, you may want to resolve links that are not API registry links or publicly accessible. To accomplish that, add the `resolve` object to the configuration file.
 
-- the `--region` option with `login` and `push` commands
-
-```sh
-openapi login --region=eu
-```
-
-- the `region` top-level property in the Redocly configuration file
-
-```yaml
-apis:
-  core@v1:
-    root: ./openapi.yaml
-region: eu
-lint:
-  extends: []
-```
-
-
-### resolve
-
-Redocly will automatically resolve any API registry link or public URL in your API definitions. However, you may want to resolve links that are not API registry links or publicly accessible. To accomplish that, add the `resolve` section to the configuration file.
-
-Redocly CLI only supports `http` headers. Only one `http` header per URL is supported in the `resolve` section.
+Redocly CLI only supports `http` headers. Only one `http` header per URL is supported in the `resolve` object.
 
 We recommend using environment variables whenever possible.
 
 #### Resolving external links
 
-The `resolve` section should be structured like this:
+The `resolve` object should be structured like this:
 
 ```yaml
 resolve:
@@ -247,7 +193,7 @@ resolve:
       - # header configuration
 ```
 
-The `headers` section supports fields listed in the following table.
+The `headers` object supports fields listed in the following table.
 
 | Property | Description | Examples |
 | --- | --- | --- |
@@ -256,7 +202,7 @@ The `headers` section supports fields listed in the following table.
 | value | The value of the header. Mutually exclusive with `envVariable`. | `123-abc`|
 | envVariable | The name of the environment variable that contains the value of the header. Mutually exclusive with `value`. |`SECRET_KEY`|
 
-Here is a structured example for adding header definitions:
+Here is an example for adding header definitions:
 
 ```yaml
 resolve:
@@ -273,10 +219,8 @@ resolve:
 The first match takes precedence when a URL matches multiple patterns. Therefore, only the header from the first match will be used in the request.
 
 
-### features.openapi
-
-The `features.openapi` section configures features (availability and options) and theming (style, fonts, colors) for API reference documentation generated from API definitions.
+### features.openapi object
 
-There are two products: Redoc Community Edition (CE) and Redocly Reference. Reference supports all configuration options from Redoc Community Edition plus a set of premium options.
+The `features.openapi` object configures features (availability and options) and theming (style, fonts, colors) for API documentation generated from OpenAPI definitions.
 
 Find the full list of supported options on the [Reference docs configuration page](../../api-reference-docs/configuration/index.mdx).
diff --git a/docs/configuration/schema.yaml b/docs/configuration/schema.yaml
index 38d9d0a5..90ff0696 100644
--- a/docs/configuration/schema.yaml
+++ b/docs/configuration/schema.yaml
@@ -15,58 +15,79 @@ properties:
 
       For example, if the URL is `app.redocly.com/org/test_docs`, the organization ID is `test_docs`.
   apis:
+    type: object
+    title: APIs object
+    description: >-
+      Lets you configure one or more API definition files.
+      This gives you the flexibility to reference specific files in commands, and configure each file at a granular level.
     additionalProperties:
       x-additionalPropertiesName: "{name}@{version}"
       type: object
       minItems: 1
       required:
         - root
-      description: |-
+      description: >-
         Specifies the name and version of an API associated with the root API definition with the pattern `{name}@{version}`.
         If the version is omitted, Redocly apps interpret it as 'latest' by default.
       properties:
         root:
           type: string
-          description: "Path to the root API definition file of the specified API."
+          description: The path to the root API definition file of the specified API.
         labels:
           type: array
-          description: "Optional labels assigned to the specified API in the Redocly API registry. The labels must exist in the Redocly Workflows organization in order to apply them."
+          description: >-
+            Use it to assign one or more existing Redocly Workflows organization-wide labels to your APIs.
+            You must have a Redocly Workflows account with an active organization, and add the top-level `organization` property to the configuration file.
+
+            If you try to assign labels that don't already exist for your organization, Redocly apps will display a warning in the output and will only assign the existing labels (if any).
           items:
             type: string
         lint:
           type: object
-          description: |-
+          description: >-
             Configures linting options for the specified API.
-            Supports the same format and options as the global lint section described further in the schema.
+            Supports the same format and options as the global `lint` object.
+            API-level configuration will always override global configuration.
         features.openapi:
+          type: object
+          description: >-
+            Defines theming and functionality for an API definition.
+            Supports the same format and options as the [global `features.openapi` object](https://redocly.com/docs/api-reference-docs/configuration/functionality/).
+            API-level configuration will always override global configuration.
+        features.mockServer:
           type: object
           description: |-
-            Configures API reference documentation options for the specified API.
-            Supports the same format and options as the global `features.openapi` section described further in the schema.
+            Defines mock server behavior for an API definition.
+            Supports the same format and options as the global `features.mockServer` object.
+            API-level configuration will always override global configuration.
   lint:
     type: object
-    description: A set of configurations to lint and decorate your APIs used when the `lint` and `bundle` commands execute.
+    description: Lets you set rules and decorators that control how the `lint` and `bundle` commands behave.
     properties:
       plugins:
         type: array
         description: >-
-          Import any local plugins (e.g. `./local-plugins.js`).
-          The built-in plugins do not need to be imported.
-          There is not support for community plugins yet.
+          Import any local filesystem plugins (e.g. `./local-plugins.js`).
+          Note that community plugins are not yet supported.
         example: ['./local-plugin.js']
         items:
           type: string
           format: path
       extends:
         type: array
-        description: Choose the base configuration. Defaults to `recommended`. You may also use `minimal` or add your own plugins.
+        description: >-
+          Inherit lint configurations.
+          In case of conflict, priority goes to configurations further down the list.
+          Finally, explicit declaration of any rules inline takes precedence over configurations inherited through the `extends` feature.
+          Built in configurations include `recommended`, `minimal`, `all`.
         items:
           type: string
+          example: recommended
       preprocessors:
         type: object
+        title: Preprocessors object
         description: >-
           Change the severity level of any preprocessors in your extended configurations.
-          Some rules may also receive additional configurations.
           Preprocessors run first during `lint` and `bundle`.
         additionalProperties:
           description: >-
@@ -74,12 +95,12 @@ properties:
             For example, `do-this-first`.
           oneOf:
             - type: string
-              description: Specify the severity level as a string shortcut (or more explicitly as an object).
+              description: Specifies the severity level as a string shortcut (or more explicitly as an object).
               enum:
                 - on
                 - off
             - type: object
-              description: Specify the severity level as an object. Useful when you need to supply additional properties for configuration.
+              description: Specifies the severity level as an object. Useful when you need to supply additional properties for configuration.
               properties:
                 severity:
                   type: string
@@ -90,7 +111,7 @@ properties:
               additionalProperties: true
       rules:
         type: object
-        title: Rules Object
+        title: Rules object
         description: >-
           Change the severity level of any rules in your extended configurations.
           Some rules may also receive additional configurations.
@@ -102,13 +123,14 @@ properties:
             For example, `no-empty-servers`.
           oneOf:
             - type: string
-              description: Specify the severity level as a string shortcut (or more explicitly as an object).
+              description: Specifies the severity level as a string shortcut (or more explicitly as an object).
               enum:
                 - error
                 - warn
                 - off
             - type: object
-              description: Specify the severity level as an object. Useful when you need to supply additional properties for configuration.
+              title: Rule configuration object
+              description: Specifies the severity level as an object. Useful when you need to supply additional properties for configuration.
               required:
                 - severity
               properties:
@@ -123,20 +145,21 @@ properties:
       decorators:
         type: object
         description: >-
-          Enable or disable decorators.
-          They run during the `bundle` command after linting.
+          Used to enable or disable decorators.
+          Decorators run during the `bundle` command after linting.
         additionalProperties:
-          description: >
+          description: >-
             List each decorator by name.
             For example, `remove-x-internal`.
           oneOf:
             - type: string
-              description: Specify the severity level as a string shortcut (or more explicitly as an object).
+              description: Specifies the severity level as a string shortcut (or more explicitly as an object).
               enum:
                 - off
                 - on
             - type: object
-              description: Specify the severity level as an object. Useful when you need to supply additional properties for configuration.
+              title: Decorator configuration object
+              description: Specifies the severity level as an object. Useful when you need to supply additional properties for configuration.
               properties:
                 severity:
                   type: string
@@ -147,19 +170,24 @@ properties:
               additionalProperties: true
   features.mockServer:
     type: object
-    description: Configure the mock server behavior in the API registry.
+    description: Lets you toggle features that control how mock servers behave.
     properties:
       errorIfForcedExampleNotFound:
-        description: When using the custom `x-redocly-response-body-example` header in the request, return an error if the requested example is not found in the API definition.
+        description: >-
+          You can force specific examples to appear in the response by adding the optional `x-redocly-response-body-example` header to your requests.
+          If you pass an example ID that can't be found in the API definition, the mock server will return any other example unless `errorIfForcedExampleNotFound` is `true`.
+          Then the mock server will return an error instead.
         type: boolean
         default: false
       strictExamples:
-        description: Always return examples exactly how they are defined in the API definition without modifying their contents.
+        description: >-
+          By default, the mock server automatically enhances responses with heuristics, such as substituting response fields with request parameter values.
+          If you set `strictExamples:true`, examples are returned in the response unmodified, and exactly how they are described in the OpenAPI definition.
         type: boolean
         default: false
   features.openapi:
     type: object
-    description: |-
+    description: >-
       Configuration options supported by Redocly for rendering OpenAPI into web pages.
       Used when previewing or building the docs.
       See the [list of options supported](https://redocly.com/docs/api-reference-docs/configuration/functionality/).
@@ -169,12 +197,15 @@ properties:
       - us
       - eu
     default: us
-    description: Sets the region used for the `login` and `push` commands. The `eu` region is limited to enterprise customers.
+    description: >-
+      Sets the region used for the `login` and `push` commands. The `eu` region is limited to enterprise customers.
+      Alternatively, set the environment variable `REDOCLY_DOMAIN` to the appropriate Redocly destination's domain (such as `https://api.redocly.com`).
   resolve:
     type: object
-    description: >
-      Use this when you have external links in your definition that are not publicly accessible (except for Redocly API registry links).
-      We recommend using environment variables where possible.
+    description: >-
+      All API registry links and public URLs in your API definitions will automatically resolve.
+      If you want to resolve links that are neither API registry links nor publicly accessible, include this object to add an HTTP request header.
+      Use environment variables where possible.
     properties:
       http:
         type: object
@@ -197,7 +228,7 @@ properties:
                   description: The header name. For example, `X-API-KEY`.
                 value:
                   type: string
-                  description: The value of the header. We recommend to use `envVariable` instead for any secrets.
+                  description: The value of the header. Mutually exclusive with `envVariable`. We recommend to use `envVariable` instead for any secrets.
                 envVariable:
                   type: string
-                  description: The environment variable name which will be resolved and should contain the value.
+                  description: The environment variable name which will be resolved and should contain the value. Mutually exclusive with `value`.
diff --git a/package-lock.json b/package-lock.json
index bd81e201..10c4a54b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
       ],
       "devDependencies": {
         "@types/jest": "^26.0.15",
+        "@types/node": "^17.0.31",
         "jest": "^26.6.3",
         "null-loader": "^4.0.0",
         "outdent": "^0.7.1",
@@ -1083,9 +1084,9 @@
       "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
     },
     "node_modules/@types/node": {
-      "version": "17.0.23",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
-      "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
+      "version": "17.0.31",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz",
+      "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q=="
     },
     "node_modules/@types/node-fetch": {
       "version": "2.6.1",
@@ -1599,9 +1600,9 @@
       }
     },
     "node_modules/async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
       "dependencies": {
         "lodash": "^4.17.14"
       }
@@ -10126,7 +10127,6 @@
       "license": "MIT",
       "dependencies": {
         "@redocly/openapi-core": "1.0.0-beta.96",
-        "@types/node": "^14.11.8",
         "assert-node-version": "^1.0.3",
         "chokidar": "^3.5.1",
         "colorette": "^1.2.0",
@@ -10149,11 +10149,6 @@
         "node": ">=12.0.0"
       }
     },
-    "packages/cli/node_modules/@types/node": {
-      "version": "14.18.12",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz",
-      "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A=="
-    },
     "packages/core": {
       "name": "@redocly/openapi-core",
       "version": "1.0.0-beta.96",
@@ -10165,7 +10160,7 @@
         "js-levenshtein": "^1.1.6",
         "js-yaml": "^4.1.0",
         "lodash.isequal": "^4.5.0",
-        "minimatch": "^3.0.4",
+        "minimatch": "^5.0.1",
         "node-fetch": "^2.6.1",
         "pluralize": "^8.0.0",
         "yaml-ast-parser": "0.0.43"
@@ -10174,7 +10169,7 @@
         "@types/js-levenshtein": "^1.1.0",
         "@types/js-yaml": "^4.0.3",
         "@types/lodash.isequal": "^4.5.5",
-        "@types/minimatch": "^3.0.3",
+        "@types/minimatch": "^3.0.5",
         "@types/node-fetch": "^2.5.7",
         "@types/pluralize": "^0.0.29",
         "typescript": "^4.0.5"
@@ -10187,6 +10182,25 @@
       "version": "14.18.12",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz",
       "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A=="
+    },
+    "packages/core/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "packages/core/node_modules/minimatch": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
     }
   },
   "dependencies": {
@@ -10896,7 +10910,6 @@
       "version": "file:packages/cli",
       "requires": {
         "@redocly/openapi-core": "1.0.0-beta.96",
-        "@types/node": "^14.11.8",
         "@types/yargs": "16.0.2",
         "assert-node-version": "^1.0.3",
         "chokidar": "^3.5.1",
@@ -10908,13 +10921,6 @@
         "simple-websocket": "^9.0.0",
         "typescript": "^4.0.3",
         "yargs": "17.0.1"
-      },
-      "dependencies": {
-        "@types/node": {
-          "version": "14.18.12",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz",
-          "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A=="
-        }
       }
     },
     "@redocly/openapi-core": {
@@ -10924,7 +10930,7 @@
         "@types/js-levenshtein": "^1.1.0",
         "@types/js-yaml": "^4.0.3",
         "@types/lodash.isequal": "^4.5.5",
-        "@types/minimatch": "^3.0.3",
+        "@types/minimatch": "^3.0.5",
         "@types/node": "^14.11.8",
         "@types/node-fetch": "^2.5.7",
         "@types/pluralize": "^0.0.29",
@@ -10932,7 +10938,7 @@
         "js-levenshtein": "^1.1.6",
         "js-yaml": "^4.1.0",
         "lodash.isequal": "^4.5.0",
-        "minimatch": "^3.0.4",
+        "minimatch": "^5.0.1",
         "node-fetch": "^2.6.1",
         "pluralize": "^8.0.0",
         "typescript": "^4.0.5",
@@ -10943,6 +10949,22 @@
           "version": "14.18.12",
           "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz",
           "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A=="
+        },
+        "brace-expansion": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+          "requires": {
+            "balanced-match": "^1.0.0"
+          }
+        },
+        "minimatch": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+          "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+          "requires": {
+            "brace-expansion": "^2.0.1"
+          }
         }
       }
     },
@@ -11102,9 +11124,9 @@
       "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
     },
     "@types/node": {
-      "version": "17.0.23",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz",
-      "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw=="
+      "version": "17.0.31",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.31.tgz",
+      "integrity": "sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q=="
     },
     "@types/node-fetch": {
       "version": "2.6.1",
@@ -11563,9 +11585,9 @@
       "dev": true
     },
     "async": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
-      "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+      "version": "2.6.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+      "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
       "requires": {
         "lodash": "^4.17.14"
       }
diff --git a/package.json b/package.json
index e7e076e4..1ee6f2f1 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
   "license": "MIT",
   "devDependencies": {
     "@types/jest": "^26.0.15",
+    "@types/node": "^17.0.31",
     "jest": "^26.6.3",
     "null-loader": "^4.0.0",
     "outdent": "^0.7.1",
diff --git a/packages/cli/package.json b/packages/cli/package.json
index e483057e..470999bb 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -36,7 +36,6 @@
   ],
   "dependencies": {
     "@redocly/openapi-core": "1.0.0-beta.96",
-    "@types/node": "^14.11.8",
     "assert-node-version": "^1.0.3",
     "chokidar": "^3.5.1",
     "colorette": "^1.2.0",
diff --git a/packages/cli/src/commands/login.ts b/packages/cli/src/commands/login.ts
index 1aa3d370..3148e8b4 100644
--- a/packages/cli/src/commands/login.ts
+++ b/packages/cli/src/commands/login.ts
@@ -1,5 +1,5 @@
 import { Region, RedoclyClient, loadConfig } from '@redocly/openapi-core';
-import { blue, green } from 'colorette';
+import { blue, green, gray } from 'colorette';
 import { promptUser } from '../utils';
 
 export function promptClientToken(domain: string) {
@@ -15,5 +15,7 @@ export async function handleLogin(argv: { verbose?: boolean; region?: Region })
   const region = argv.region || (await loadConfig()).region;
   const client = new RedoclyClient(region);
   const clientToken = await promptClientToken(client.domain);
-  client.login(clientToken, argv.verbose);
+  process.stdout.write(gray('\n  Logging in...\n'));
+  await client.login(clientToken, argv.verbose);
+  process.stdout.write(green('  Authorization confirmed. ✅\n\n'));
 }
diff --git a/packages/cli/src/commands/preview-docs/preview-server/preview-server.ts b/packages/cli/src/commands/preview-docs/preview-server/preview-server.ts
index 1d9438f1..b7b767c0 100644
--- a/packages/cli/src/commands/preview-docs/preview-server/preview-server.ts
+++ b/packages/cli/src/commands/preview-docs/preview-server/preview-server.ts
@@ -98,19 +98,24 @@ export default async function startPreviewServer(
         });
       }
     } else {
-      const filePath =
+      let filePath =
         // @ts-ignore
         {
           '/hot.js': path.join(__dirname, 'hot.js'),
           '/oauth2-redirect.html': path.join(__dirname, 'oauth2-redirect.html'),
           '/simplewebsocket.min.js': require.resolve('simple-websocket/simplewebsocket.min.js'),
-        }[request.url || ''] ||
-        path.resolve(htmlTemplate ? path.dirname(htmlTemplate) : process.cwd(), `.${request.url}`);
+        }[request.url || ''];
 
-      if (!isSubdir(process.cwd(), filePath)) {
-        respondWithGzip('404 Not Found', request, response, { 'Content-Type': 'text/html' }, 404);
-        console.timeEnd(colorette.dim(`GET ${request.url}`));
-        return;
+      if (!filePath) {
+        const basePath = htmlTemplate ? path.dirname(htmlTemplate) : process.cwd();
+
+        filePath = path.resolve(basePath, `.${request.url}`);
+
+        if (!isSubdir(basePath, filePath)) {
+          respondWithGzip('404 Not Found', request, response, { 'Content-Type': 'text/html' }, 404);
+          console.timeEnd(colorette.dim(`GET ${request.url}`));
+          return;
+        }
       }
 
       const extname = String(path.extname(filePath)).toLowerCase() as keyof typeof mimeTypes;
diff --git a/packages/cli/src/commands/push.ts b/packages/cli/src/commands/push.ts
index d0f4c9a0..94d27d17 100644
--- a/packages/cli/src/commands/push.ts
+++ b/packages/cli/src/commands/push.ts
@@ -35,6 +35,7 @@ type PushArgs = {
   'run-id'?: string;
   region?: Region;
   'skip-decorator'?: string[];
+  'public'?: boolean;
 };
 
 export async function handlePush(argv: PushArgs): Promise<void> {
@@ -147,6 +148,7 @@ export async function handlePush(argv: PushArgs): Promise<void> {
         filePaths,
         branch: branchName,
         isUpsert: upsert,
+        isPublic: argv['public']
       });
     } catch (error) {
       if (error.message === 'ORGANIZATION_NOT_FOUND') {
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 73664de4..d8b79114 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -106,6 +106,10 @@ yargs
             array: true,
             type: 'string',
           },
+          'public': {
+            description: 'Make API registry available to the public',
+            type: 'boolean',
+          },
         }),
     transformPush(handlePush),
   )
@@ -261,6 +265,7 @@ yargs
     async () => {
       const client = new RedoclyClient();
       client.logout();
+      process.stdout.write('Logged out from the Redocly account. ✋\n');
     },
   )
   .command(
diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json
index 9cac47d3..0566dc3b 100644
--- a/packages/core/package-lock.json
+++ b/packages/core/package-lock.json
@@ -15,7 +15,7 @@
         "js-levenshtein": "^1.1.6",
         "js-yaml": "^4.1.0",
         "lodash.isequal": "^4.5.0",
-        "minimatch": "^3.0.4",
+        "minimatch": "^5.0.1",
         "node-fetch": "^2.6.1",
         "pluralize": "^8.0.0",
         "yaml-ast-parser": "0.0.43"
@@ -24,7 +24,7 @@
         "@types/js-levenshtein": "^1.1.0",
         "@types/js-yaml": "^4.0.3",
         "@types/lodash.isequal": "^4.5.5",
-        "@types/minimatch": "^3.0.3",
+        "@types/minimatch": "^3.0.5",
         "@types/node-fetch": "^2.5.7",
         "@types/pluralize": "^0.0.29",
         "typescript": "^4.0.5"
@@ -118,12 +118,11 @@
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
     "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
       "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
+        "balanced-match": "^1.0.0"
       }
     },
     "node_modules/colorette": {
@@ -143,11 +142,6 @@
         "node": ">= 0.8"
       }
     },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
-    },
     "node_modules/delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -227,14 +221,14 @@
       }
     },
     "node_modules/minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
       "dependencies": {
-        "brace-expansion": "^1.1.7"
+        "brace-expansion": "^2.0.1"
       },
       "engines": {
-        "node": "*"
+        "node": ">=10"
       }
     },
     "node_modules/node-fetch": {
@@ -407,12 +401,11 @@
       "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
     },
     "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
       "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
+        "balanced-match": "^1.0.0"
       }
     },
     "colorette": {
@@ -429,11 +422,6 @@
         "delayed-stream": "~1.0.0"
       }
     },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
-    },
     "delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -495,11 +483,11 @@
       }
     },
     "minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
       "requires": {
-        "brace-expansion": "^1.1.7"
+        "brace-expansion": "^2.0.1"
       }
     },
     "node-fetch": {
diff --git a/packages/core/package.json b/packages/core/package.json
index 60c32f67..175e18bb 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -39,7 +39,7 @@
     "js-levenshtein": "^1.1.6",
     "js-yaml": "^4.1.0",
     "lodash.isequal": "^4.5.0",
-    "minimatch": "^3.0.4",
+    "minimatch": "^5.0.1",
     "node-fetch": "^2.6.1",
     "pluralize": "^8.0.0",
     "yaml-ast-parser": "0.0.43"
@@ -48,7 +48,7 @@
     "@types/js-levenshtein": "^1.1.0",
     "@types/js-yaml": "^4.0.3",
     "@types/lodash.isequal": "^4.5.5",
-    "@types/minimatch": "^3.0.3",
+    "@types/minimatch": "^3.0.5",
     "@types/node-fetch": "^2.5.7",
     "@types/pluralize": "^0.0.29",
     "typescript": "^4.0.5"
diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts
index 7dafdb58..5d1aa3d3 100755
--- a/packages/core/src/config/config.ts
+++ b/packages/core/src/config/config.ts
@@ -19,25 +19,34 @@ import type {
 } from './types';
 import { getResolveConfig } from './utils';
 
+// Alias environment here so this file can work in browser environments too.
+export const env = typeof process !== 'undefined' ? process.env || {} : {};
+
 export const IGNORE_FILE = '.redocly.lint-ignore.yaml';
 const IGNORE_BANNER =
   `# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API.\n` +
   `# See https://redoc.ly/docs/cli/ for more information.\n`;
 
 export const DEFAULT_REGION = 'us';
-const REDOCLY_DOMAIN = process.env.REDOCLY_DOMAIN;
-export const DOMAINS: { [region in Region]: string } = {
-  us: 'redocly.com',
-  eu: 'eu.redocly.com',
-};
-
-// FIXME: temporary fix for our lab environments
-if (REDOCLY_DOMAIN?.endsWith('.redocly.host')) {
-  DOMAINS[REDOCLY_DOMAIN.split('.')[0] as Region] = REDOCLY_DOMAIN;
-}
-if (REDOCLY_DOMAIN === 'redoc.online') {
-  DOMAINS[REDOCLY_DOMAIN as Region] = REDOCLY_DOMAIN;
+
+function getDomains() {
+  const domains: { [region in Region]: string } = {
+    us: 'redocly.com',
+    eu: 'eu.redocly.com',
+  };
+
+  // FIXME: temporary fix for our lab environments
+  const domain = env.REDOCLY_DOMAIN;
+  if (domain?.endsWith('.redocly.host')) {
+    domains[domain.split('.')[0] as Region] = domain;
+  }
+  if (domain === 'redoc.online') {
+    domains[domain as Region] = domain;
+  }
+  return domains;
 }
+
+export const DOMAINS = getDomains();
 export const AVAILABLE_REGIONS = Object.keys(DOMAINS) as Region[];
 
 export class LintConfig {
diff --git a/packages/core/src/format/format.ts b/packages/core/src/format/format.ts
index f4c94efc..924e6099 100644
--- a/packages/core/src/format/format.ts
+++ b/packages/core/src/format/format.ts
@@ -14,6 +14,7 @@ const coreVersion = require('../../package.json').version;
 
 import { NormalizedProblem, ProblemSeverity, LineColLocationObject, LocationObject } from '../walk';
 import { getCodeframe, getLineColLocation } from './codeframes';
+import { env } from "../config";
 
 export type Totals = {
   errors: number;
@@ -202,7 +203,7 @@ export function formatProblems(
             : undefined,
         };
 
-        if (process.env.FORMAT_JSON_WITH_CODEFRAMES) {
+        if (env.FORMAT_JSON_WITH_CODEFRAMES) {
           const location = p.location[0]; // TODO: support multiple locations
           const loc = getLineColLocation(location);
           (problem as any).codeframe = getCodeframe(loc, color);
diff --git a/packages/core/src/redocly/index.ts b/packages/core/src/redocly/index.ts
index e06d7563..66121baa 100644
--- a/packages/core/src/redocly/index.ts
+++ b/packages/core/src/redocly/index.ts
@@ -1,9 +1,9 @@
 import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
 import { resolve } from 'path';
 import { homedir } from 'os';
-import { red, green, gray, yellow } from 'colorette';
+import { green } from 'colorette';
 import { RegistryApi } from './registry-api';
-import { DEFAULT_REGION, DOMAINS, AVAILABLE_REGIONS } from '../config/config';
+import { DEFAULT_REGION, DOMAINS, AVAILABLE_REGIONS, env } from '../config/config';
 import { RegionalToken, RegionalTokenWithValidity } from './redocly-client-types';
 import { isNotEmptyObject } from '../utils';
 
@@ -11,7 +11,6 @@ import type { AccessTokens, Region } from '../config/types';
 
 const TOKEN_FILENAME = '.redocly-config.json';
 
-let REDOCLY_DOMAIN: string; // workaround for the isRedoclyRegistryURL, see more below
 export class RedoclyClient {
   private accessTokens: AccessTokens = {};
   private region: Region;
@@ -21,31 +20,20 @@ export class RedoclyClient {
   constructor(region?: Region) {
     this.region = this.loadRegion(region);
     this.loadTokens();
-    this.domain = region ? DOMAINS[region] : process.env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
+    this.domain = region ? DOMAINS[region] : env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
 
-    /*
-     * We can't use process.env here because it is replaced by a const in some client-side bundles,
-     * which breaks assignment.
-     */
-    REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
+    env.REDOCLY_DOMAIN = this.domain; // isRedoclyRegistryURL depends on the value to be set
     this.registryApi = new RegistryApi(this.accessTokens, this.region);
   }
 
   loadRegion(region?: Region) {
     if (region && !DOMAINS[region]) {
-      process.stdout.write(
-        red(
-          `Invalid argument: region in config file.\nGiven: ${green(
-            region,
-          )}, choices: "us", "eu".\n`,
-        ),
-      );
-      process.exit(1);
+      throw new Error(`Invalid argument: region in config file.\nGiven: ${green(region)}, choices: "us", "eu".`);
     }
 
-    if (process.env.REDOCLY_DOMAIN) {
+    if (env.REDOCLY_DOMAIN) {
       return (AVAILABLE_REGIONS.find(
-        (region) => DOMAINS[region as Region] === process.env.REDOCLY_DOMAIN,
+        (region) => DOMAINS[region as Region] === env.REDOCLY_DOMAIN,
       ) || DEFAULT_REGION) as Region;
     }
     return region || DEFAULT_REGION;
@@ -65,18 +53,7 @@ export class RedoclyClient {
   }
 
   async getAuthorizationHeader(): Promise<string | undefined> {
-    const token = this.accessTokens[this.region];
-    // print this only if there is token but invalid
-    if (token && !this.isAuthorizedWithRedoclyByRegion()) {
-      process.stderr.write(
-        `${yellow(
-          'Warning:',
-        )} invalid Redocly API key. Use "npx @redocly/cli login" to provide your API key\n`,
-      );
-      return undefined;
-    }
-
-    return token;
+    return this.accessTokens[this.region];
   }
   // </backward compatibility: portal>
 
@@ -96,10 +73,10 @@ export class RedoclyClient {
           }),
       });
     }
-    if (process.env.REDOCLY_AUTHORIZATION) {
+    if (env.REDOCLY_AUTHORIZATION) {
       this.setAccessTokens({
         ...this.accessTokens,
-        [this.region]: process.env.REDOCLY_AUTHORIZATION,
+        [this.region]: env.REDOCLY_AUTHORIZATION,
       });
     }
   }
@@ -164,15 +141,11 @@ export class RedoclyClient {
 
   async login(accessToken: string, verbose: boolean = false) {
     const credentialsPath = resolve(homedir(), TOKEN_FILENAME);
-    process.stdout.write(gray('\n  Logging in...\n'));
 
     try {
       await this.verifyToken(accessToken, this.region, verbose);
     } catch (err) {
-      process.stdout.write(
-        red('Authorization failed. Please check if you entered a valid API key.\n'),
-      );
-      process.exit(1);
+      throw new Error('Authorization failed. Please check if you entered a valid API key.');
     }
 
     const credentials = {
@@ -183,7 +156,6 @@ export class RedoclyClient {
     this.accessTokens = credentials;
     this.registryApi.setAccessTokens(credentials);
     writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2));
-    process.stdout.write(green('  Authorization confirmed. ✅\n\n'));
   }
 
   logout(): void {
@@ -191,12 +163,11 @@ export class RedoclyClient {
     if (existsSync(credentialsPath)) {
       unlinkSync(credentialsPath);
     }
-    process.stdout.write('Logged out from the Redocly account. ✋\n');
   }
 }
 
 export function isRedoclyRegistryURL(link: string): boolean {
-  const domain = REDOCLY_DOMAIN || process.env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
+  const domain = env.REDOCLY_DOMAIN || DOMAINS[DEFAULT_REGION];
 
   const legacyDomain = domain === 'redocly.com' ? 'redoc.ly' : domain;
 
diff --git a/packages/core/src/redocly/registry-api-types.ts b/packages/core/src/redocly/registry-api-types.ts
index 1d6b313f..1a92de9c 100644
--- a/packages/core/src/redocly/registry-api-types.ts
+++ b/packages/core/src/redocly/registry-api-types.ts
@@ -16,6 +16,7 @@ export namespace RegistryApiTypes {
     filePaths: string[];
     branch?: string;
     isUpsert?: boolean;
+    isPublic?: boolean;
   }
 
   export interface PrepareFileuploadOKResponse {
diff --git a/packages/core/src/redocly/registry-api.ts b/packages/core/src/redocly/registry-api.ts
index c6582cc1..70749eed 100644
--- a/packages/core/src/redocly/registry-api.ts
+++ b/packages/core/src/redocly/registry-api.ts
@@ -104,6 +104,7 @@ export class RegistryApi {
     filePaths,
     branch,
     isUpsert,
+    isPublic,
   }: RegistryApiTypes.PushApiParams) {
     const response = await this.request(
       `/${organizationId}/${name}/${version}`,
@@ -118,6 +119,7 @@ export class RegistryApi {
           filePaths,
           branch,
           isUpsert,
+          isPublic,
         }),
       },
       this.region,
diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts
index 5b11b0f0..0533011c 100644
--- a/packages/core/src/utils.ts
+++ b/packages/core/src/utils.ts
@@ -5,6 +5,7 @@ import * as pluralize from 'pluralize';
 import { parseYaml } from './js-yaml';
 import { UserContext } from './walk';
 import type { HttpResolveConfig } from './config';
+import { env } from "./config";
 
 export { parseYaml, stringifyYaml } from './js-yaml';
 
@@ -51,7 +52,7 @@ export async function readFileFromUrl(url: string, config: HttpResolveConfig) {
   for (const header of config.headers) {
     if (match(url, header.matches)) {
       headers[header.name] =
-        header.envVariable !== undefined ? process.env[header.envVariable] || '' : header.value;
+        header.envVariable !== undefined ? env[header.envVariable] || '' : header.value;
     }
   }
 
@@ -66,7 +67,7 @@ export async function readFileFromUrl(url: string, config: HttpResolveConfig) {
   return { body: await req.text(), mimeType: req.headers.get('content-type') };
 }
 
-export function match(url: string, pattern: string) {
+function match(url: string, pattern: string) {
   if (!pattern.match(/^https?:\/\//)) {
     // if pattern doesn't specify protocol directly, do not match against it
     url = url.replace(/^https?:\/\//, '');


Test patch:
diff --git a/packages/cli/src/__tests__/commands/push.test.ts b/packages/cli/src/__tests__/commands/push.test.ts
index f6b05f0a..bb0fff6a 100644
--- a/packages/cli/src/__tests__/commands/push.test.ts
+++ b/packages/cli/src/__tests__/commands/push.test.ts
@@ -31,6 +31,7 @@ describe('push', () => {
       entrypoint: 'spec.json',
       destination: '@org/my-api@1.0.0',
       branchName: 'test',
+      'public': true
     });
 
     expect(redoclyClient.registryApi.prepareFileUpload).toBeCalledTimes(1);
@@ -39,6 +40,7 @@ describe('push', () => {
       branch: 'test',
       filePaths: ['filePath'],
       isUpsert: true,
+      isPublic: true,
       name: 'my-api',
       organizationId: 'org',
       rootFilePath: 'filePath',